Skip to main content

Decode AEwin64 .WFS streaming files into numpy arrays

Project description

decode-wfs

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.0.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.0-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: decode_wfs-0.1.0.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.0.tar.gz
Algorithm Hash digest
SHA256 84d2f13c4810403e380d75f64e2efcbe9d6b3acdc57c8cbba2f162789aa78b78
MD5 3e79830a96592bb1b3e5d7cb524e7545
BLAKE2b-256 aaec51993e6887ee3db69578e747749002071f77e8c16bb8d34e9c72da3be9bd

See more details on using hashes here.

File details

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

File metadata

  • Download URL: decode_wfs-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.4 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5e9fe4ecd9e6e163d0d405e99d652cfac19273b03293abc3bc251495674562ad
MD5 423bdd5dca5a10fa171b66bde19617e1
BLAKE2b-256 86ecacea5e5e162885819bfc0f6000bba876fcdc596b6984137d21cdf8cb1d8e

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