Skip to main content

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.

Metadata

Release files for decode-wfs 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for decode-wfs 0.1.3
File Size Uploaded Provenance Actions
decode_wfs-0.1.3.tar.gz 12.4 kB Without provenance Details for decode_wfs-0.1.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for decode-wfs 0.1.3
File Interpreter ABI Platform Actions
decode_wfs-0.1.3-py3-none-any.whl Python 3 none any Details for decode_wfs-0.1.3-py3-none-any.whl

Total release size: 24.7 kB

Release files / decode_wfs-0.1.3.tar.gz

Download URL decode_wfs-0.1.3.tar.gz
Size 12.4 kB
Tags Source
SHA-256 checksum
How to use checksums
9926620a4f3f00ef370846f33ed2b9afc661a5a5eb18d3a95d3feeb92f544e16
BLAKE2b-256 checksum
How to use checksums
523f3bafaad0e102b8912f24b5981adb717f0de0100ab1c872a1c8fd2fc66d22
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.9

Release files / decode_wfs-0.1.3-py3-none-any.whl

Download URL decode_wfs-0.1.3-py3-none-any.whl
Size 12.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8f6a19250a9f74c9967f61d570090136cfd0d386767d8548bb9b74aa8bc3d4d6
BLAKE2b-256 checksum
How to use checksums
14521847c0af94f2d0f6774d85a7b3c866dbee1b2f00b24e73fffb62072e7978
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.9

Security for decode-wfs 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page