Skip to main content

Decode AEwin64 .WFS streaming files into numpy arrays

Project description

decode-wfs — GitHub

Decode binary .WFS (Waveform Stream) files produced by Physical Acoustics AEwin64 / EasyAE acoustic emission software into numpy arrays.

The AEwin64 manual describes a format using message ID 173 (0xAD), but real streaming captures use ID 174 (0xAE) with a slightly different layout. This library handles the empirically observed streaming format and has been verified against real captures. Voltage values are recovered with the calibration factor used by AEwin64's own ASCII waveform exporter (raw_counts / 16384).


Installation

pip install decode-wfs

Requires Python 3.10+ and numpy.


Quick start

decode_wfs() — full access to every record

from decode_wfs import decode_wfs

wfs = decode_wfs("capture.wfs")

print(f"Sample rate : {wfs.sample_rate_hz:,} Hz")
print(f"Channels    : {wfs.channels()}")
print(f"Records     : {len(wfs.waveforms)}")

# Iterate individual waveform records
for rec in wfs.waveforms:
    print(rec.channel, rec.samples.shape, rec.samples.max())

# Time axis for each record (includes pretrigger offset when present)
t = wfs.waveforms[0].time_axis_s   # 1-D float64 array in seconds

# Stack all records from channel 1 into a 2-D array (records × samples)
arr = wfs.to_array(channel=1)      # shape (n_records, n_samples), float64 volts

wfs_to_numpy() — one-liner for a 2-D array

from decode_wfs import wfs_to_numpy

# shape: (n_waveforms, n_samples_per_waveform), dtype float64, units volts
arr = wfs_to_numpy("capture.wfs", channel=1)

# Optionally return the per-waveform time axis as well
arr, t = wfs_to_numpy("capture.wfs", channel=1, return_time_axis=True)

load_continuous() — single concatenated time series

Reconstructs the continuous stream from all records, preserving absolute timing when the file contains per-record position pointers.

from decode_wfs import load_continuous

samples, time, sr = load_continuous("capture.wfs", channel=1)
# samples: 1-D float64 array, volts
# time   : 1-D float64 array, seconds (negative at pretrigger)
# sr     : sample rate in Hz

# Example: compute a power spectrum
import numpy as np
freqs = np.fft.rfftfreq(len(samples), d=1 / sr)
psd   = np.abs(np.fft.rfft(samples)) ** 2

API summary

Function / class Returns When to use
decode_wfs(path) WFSFile Need per-record metadata or multi-channel data
wfs_to_numpy(path) ndarray (n×m) Just need the voltage array
load_continuous(path) (samples, time, sr) Spectral analysis on a single channel
WFSFile.to_array(channel) ndarray (n×m) After decode_wfs, stack records into an array
WFSFile.waveform_time_axis_s() ndarray (m,) Shared time axis for all waveform records
WFSFile.channels() list[int] Which AE channel numbers are in the file
WaveformRecord.time_axis_s ndarray (m,) Per-record time axis including pretrigger

Logging

decode_wfs uses the standard logging module under the logger name decode_wfs. To see progress messages:

import logging
logging.basicConfig(level=logging.INFO)

CLI

decode-wfs <file.wfs> [--channel N] [--max-records N]

Example:

$ decode-wfs capture.wfs --channel 1

File          : capture.wfs
Sample rate   : 1,000,000 Hz  (1.000 MSPS)
Sample format : ADT=2  (16-bit signed samples)
Setup blocks  : 2
Pretrigger    : -256 samples
Total records : 512
Channels      : [1, 2]

  [0] ch=1  n=4096 samples  min=-0.03125000 V  max=0.04394531 V  std=0.00201416 V
  [1] ch=1  n=4096 samples  min=-0.02832031 V  max=0.03955078 V  std=0.00198364 V
  ...

numpy array shape : (256, 4096)  dtype=float64
Done.

Notes

  • Voltage calibration — ADC counts are divided by 16384 to match the voltages in AEwin64's ASCII waveform exports. This factor was determined empirically and may not hold for all hardware configurations.
  • Pretrigger — when a pretrigger window is configured, time_axis_s and the time axis from load_continuous start at a negative time offset so that t=0 corresponds to the trigger point.
  • Multi-channel files — records from all channels are interleaved in the file. Use the channel parameter to filter, or iterate WFSFile.waveforms and check rec.channel.
  • Large files — pass max_records=N to any function to stop after reading N waveform records, useful during development.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

decode_wfs-0.1.1.tar.gz (11.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

decode_wfs-0.1.1-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

File details

Details for the file decode_wfs-0.1.1.tar.gz.

File metadata

  • Download URL: decode_wfs-0.1.1.tar.gz
  • Upload date:
  • Size: 11.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for decode_wfs-0.1.1.tar.gz
Algorithm Hash digest
SHA256 00075f37808199b5764281fca1b5d41f5af5cb179897d02fe6b9f719bbbf5b89
MD5 11c0a9fdcda6b2cf6c422bd06f9f55bb
BLAKE2b-256 1ec643c248fa1e07fcb647114f91af4599b1a2e93b3b4639555b209c3007756b

See more details on using hashes here.

File details

Details for the file decode_wfs-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: decode_wfs-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for decode_wfs-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ff54645fbd1ca1d228cfd4c04200f6d55e12be480aa7ddf10b0a4bfabb8deaff
MD5 51c735bc189c67476ec0b4693f1f2f94
BLAKE2b-256 6465e37e7b44b45b6bd5bbef2b50b9d36e9ccdfe59f314f16f028c8796704b18

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page