An open API service indexing awesome lists of open source software.

https://github.com/wamriewdan/ae_arrival_picker

Python package for automatic first-arrival time picking in acoustic emission and microseismic data using AIC, STA/LTA, and energy-based methods.
https://github.com/wamriewdan/ae_arrival_picker

acoustic-emission aic arrival-time-picking geophysics microseismic python seismology signal-processing sta-lta waveform-analysis

Last synced: 22 days ago
JSON representation

Python package for automatic first-arrival time picking in acoustic emission and microseismic data using AIC, STA/LTA, and energy-based methods.

Awesome Lists containing this project

README

          

# ae-picker

[DOI: 10.5281/zenodo.20126965](https://doi.org/10.5281/zenodo.20126965)

`ae-picker` is a Python package for automatic first-arrival time picking in
acoustic emission (AE) and microseismic waveform data.

It includes waveform readers, multiple picking algorithms, batch processing,
and plotting helpers for review and comparison.

## Algorithm notes

### AIC picker

The AIC picker treats the waveform as two segments split at sample `k` and
selects the split that minimizes the Akaike Information Criterion:

```text
AIC(k) = k * log(var(x[0:k])) + (N - k - 1) * log(var(x[k+1:N]))
```

Short explanation:

- Before the arrival, the signal is assumed to behave like background noise.
- After the arrival, the variance changes because the waveform contains the
first motion and subsequent energy.
- The best onset is the sample where this two-segment model fits best.

### Refined STA/LTA picker

The refined STA/LTA picker in this package is a two-stage method:

1. A recursive STA/LTA trigger finds a coarse onset window.
2. A Hilbert-envelope refinement step walks back to the earliest persistent
onset inside that window.

The STA/LTA trigger is based on the ratio

```text
CFT(i) = STA(i) / LTA(i)
```

where the fallback implementation in this package uses

```text
STA(i) = mean(|x[i-nsta:i]|)
LTA(i) = mean(|x[i-nlta:i]|)
```

and triggers when `CFT(i)` rises above the on-threshold and ends when it falls
below the off-threshold.

The envelope-refinement stage uses the analytic-signal envelope

```text
e(i) = |H{x}(i)|
```

and robust noise statistics

```text
sigma ~= 1.4826 * MAD(e_noise)
thr_high = median(e_noise) + k_high * sigma
thr_low = median(e_noise) + k_low * sigma
```

Short explanation:

- STA/LTA provides a stable first trigger for emergent arrivals.
- The envelope stage then refines that trigger by requiring a persistent rise
above a lower threshold, which improves onset timing.
- In this repository, the "refined STA/LTA" picker is this package-specific
combination of recursive STA/LTA and envelope-based onset refinement.

## Plotting

### `plot_sta_lta_overlay` — STA/LTA diagnostic plot

Produces a three-panel figure for diagnosing the STA/LTA picker on a single
channel:

1. **Waveform** — raw amplitude time series.
2. **STA & LTA envelopes** — centered moving averages of `|amp|` showing how
the short- and long-term averages evolve around the arrival.
3. **STA/LTA characteristic function** — the recursive ratio with trigger-on
and trigger-off threshold lines, and optional onset marker lines.

```python
from ae_picker import refined_stalta_picker, plot_sta_lta_overlay

amp, time = channels[0]["amp"], channels[0]["time"]
N = len(time)

pick_idx, cft, triggers = refined_stalta_picker(
amp, time,
sta_s=2e-6, lta_s=100e-6,
sta_thresh=2.5, lta_thresh=1.5,
search_start=int(0.5 * N), # filtered records: no triggers before t=0
)

fig, axes = plot_sta_lta_overlay(
amp, time,
sta_s=2e-6, lta_s=100e-6,
sta_thresh=2.5, lta_thresh=1.5,
triggers=triggers, # draws onset vline on all panels
tlim_us=(-100, 200), # zoom to ±µs around arrival (relative to time[0])
)
```

Key parameters:

| Parameter | Description | Default |
|---|---|---|
| `sta_s`, `lta_s` | STA and LTA window lengths (seconds) | `5e-6`, `50e-6` |
| `sta_thresh`, `lta_thresh` | Trigger on/off threshold lines | `2.5`, `1.5` |
| `triggers` | `[[onset, offset], ...]` sample pairs from `refined_stalta_picker` | `None` |
| `manual_picks_s` | Additional pick times (seconds) to overlay | `None` |
| `tlim_us` | X-axis limits in microseconds relative to `time[0]` | `None` (full record) |
| `savepath` | File path to save the figure | `None` |

---

### `plot_wave_and_spectrogram` — waveform + PSD spectrogram

Produces a two-panel figure with the normalised waveform above and the
Power Spectral Density spectrogram (Hann window, Welch method) below, sharing
the same time axis. Suitable for journal figures.

```python
from ae_picker import plot_wave_and_spectrogram

fig, (ax_wave, ax_spec) = plot_wave_and_spectrogram(
amp, time,
fmax=500e3, # Hz — clip frequency axis at 500 kHz
tmin=time[0], # display window start (seconds)
tmax=time[-1], # display window end (seconds)
dyn_range_db=80, # colour dynamic range
title="Channel 1",
savepath="ch1_spec.png",
)
```

Key parameters:

| Parameter | Description | Default |
|---|---|---|
| `fmax` | Upper frequency limit for the spectrogram (Hz) | `None` (Nyquist) |
| `nperseg` | STFT window length (samples); `None` → auto (~2 ms) | `None` |
| `overlap` | Fractional window overlap `[0, 1)` | `0.90` |
| `dyn_range_db` | Colour dynamic range in dB | `80` |
| `norm_percentile` | Percentile used to normalise the waveform | `99.9` |
| `tmin`, `tmax` | Display window start/end (seconds) | `None` (full record) |
| `savepath` | File path to save the figure | `None` |

## Features

- AIC, envelope-based, and STA/LTA picking workflows
- Readers for the repository's filtered and unfiltered waveform formats
- Batch processing that writes a single `picks_summary.csv`
- Plot helpers for waveform review and picker comparison
- A command-line interface exposed as `ae-picker`

## Installation

Install from PyPI after the package is published:

```bash
pip install ae-picker
```

Install from a local checkout:

```bash
git clone https://github.com/wamriewdan/ae_arrival_picker
cd ae_arrival_picker
pip install .
```

Optional extras:

```bash
pip install -e ".[dev]"
pip install ".[obspy]"
```

The package is installed as `ae-picker` but imported as `ae_picker`.

## Quick start

Batch process a dataset with the Python API:

```python
from ae_picker import run

df = run("path/to/your/data_dir", plot=False, save_plots=False)
print(df.head())
```

Run the CLI:

```bash
ae-picker path/to/your/data_dir --save-plots
```

Pick a single file:

```python
from ae_picker import aic_picker, plot_channels, read_unfiltered

meta, channels = read_unfiltered("my_ae_file.txt")

aic_picks = []
for ch in channels:
idx, _ = aic_picker(ch["amp"], search_start=1, search_end=10)
aic_picks.append(idx)
print(f"P arrival at {ch['time'][idx] * 1e6:.1f} us")

fig = plot_channels(meta, channels, picks={"AIC": aic_picks})
fig.savefig("picks.png", dpi=150)
```

## Batch input layout

The batch runner expects a root directory containing one or both of these
subdirectories:

```text
your_data_dir/
|-- unfiltered_signals/
`-- filtered_signals/
```

`run()` and `ae-picker` scan those folders, infer the signal type from the
folder name, and write results to `picks_output/picks_summary.csv` by default.

## References

1. Maeda, N. (1985). *A Method for Reading and Checking Phase Time in
Auto-Processing System of Seismic Wave Data*. Zisin, 38(3), 365-379.
https://doi.org/10.4294/zisin1948.38.3_365
2. Allen, R. V. (1978). *Automatic Earthquake Recognition and Timing from
Single Traces*. Bulletin of the Seismological Society of America, 68(5),
1521-1532. https://doi.org/10.1785/BSSA0680051521
3. Beyreuther, M., Barsch, R., Krischer, L., Megies, T., Behr, Y., and
Wassermann, J. (2010). *ObsPy: A Python Toolbox for Seismology*.
Seismological Research Letters, 81(3), 530-533.
https://doi.org/10.1785/gssrl.81.3.530

## Citation

If you use `ae-picker`, please cite:

1. Wamriew, D. (2026). ae-picker. Zenodo. https://doi.org/10.5281/zenodo.20126965

## License

MIT