Metadata-Version: 2.4
Name: py-nfi
Version: 0.1.1
Summary: Normalized frequency index (nFI) computation for earthquake source spectra
Author-email: Ian Vandevert <ivandevert@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/ivandevert/py-nfi
Project-URL: Repository, https://github.com/ivandevert/py-nfi
Project-URL: Issues, https://github.com/ivandevert/py-nfi/issues
Project-URL: Paper, https://doi.org/10.1785/0120250171
Keywords: seismology,earthquake,spectral analysis,source spectra
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: pandas
Requires-Dist: scipy
Requires-Dist: tqdm
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# py-nfi

[![PyPI version](https://img.shields.io/pypi/v/py-nfi.svg)](https://pypi.org/project/py-nfi/)
[![Python versions](https://img.shields.io/pypi/pyversions/py-nfi.svg)](https://pypi.org/project/py-nfi/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Compute the **normalized frequency index (nFI)** from earthquake spectra. nFI is a
data-driven measure of the relative high-frequency content of a seismic source,
providing an observation-based alternative to stress-drop estimation for
characterizing source behavior at high frequencies.

## Installation

```bash
pip install py-nfi
```

or, with conda:

```bash
conda install -c conda-forge py-nfi
```

## Quick start

```python
import numpy as np
import pandas as pd
from nfi import nFIEstimator

# df_records: one row per event-station record (a single observed spectrum)
# spectra:    N x nf array of signal amplitude spectra, aligned row-for-row
#             with df_records (the signal windows; noise spectra are used
#             upstream for signal-to-noise screening, not passed here)
# f:          length-nf frequency array (0 to Nyquist)

est = nFIEstimator(df_records, spectra, f, save_dir="results/")
est.compute()

# per-event results, including the 'nfi' column, are written to results/
# and available as est.df_events
```

`df_records` must contain, at minimum, the columns `event_name`, `channel_name`,
`emag`, `elat`, `elon`, `edep`, `slat`, `slon`, `selev`, and `deldist`, where
`e*` fields describe the event and `s*` fields describe the recording station.

## Method

nFI is computed from spectra in three stages.

**1. Frequency index.** For every observed spectrum, we take the log ratio of the
median amplitude in a high-frequency band to that in a low-frequency band:

```
logbeta = log10(A_HF) - log10(A_LF)
```

This quantifies the richness of high frequencies relative to low frequencies for a
single recording. The low band should sample the flat portion of the displacement
spectrum below the corner frequency, and the high band should sample the decay
above it.

**2. Path and station correction.** Observed spectra carry path and station effects
that must be removed to isolate source variability. For each target event, we
identify small nearby "calibration" earthquakes recorded at the same stations.
Differencing `logbeta` between a target and a calibration event at a shared station
cancels the common station and path terms. Taking the median of these differences
across calibration events per station, then the median across stations, yields the
corrected source term `dlogbeta` for each event. Calibration events are selected
within a narrow magnitude range and a limited horizontal and vertical distance of
the target.

**3. Magnitude correction.** Larger earthquakes radiate proportionally less
high-frequency energy, so `dlogbeta` retains a magnitude dependence. We estimate
this trend by taking the median `dlogbeta` in magnitude bins, smoothing it, and
subtracting the interpolated trend from each event. The result is **nFI**: by
construction it has approximately zero median at any magnitude, with positive
values indicating high-frequency enrichment and negative values indicating
depletion.

For full detail and validation of the method, see Vandevert et al. (2026) below.

## Reproducing the Ridgecrest results

<!-- TODO: describe how to run ridgecrest/run_beta_compute.ipynb against the
bundled spectra and catalogs to reproduce the published figures. -->

## Where the spectra come from

<!-- TODO: describe the upstream waveform download and spectral estimation steps
that produce the N x nf spectra consumed by this package. -->

## Citation

If you use this software, please cite:

> Vandevert, I., Shearer, P. M., & Fan, W. (2026). Using a High-to-Low-Frequency
> Spectral Ratio to Distinguish Variations in Earthquake Source Properties.
> *Bulletin of the Seismological Society of America.*
> https://doi.org/10.1785/0120250171

## License

Released under the [MIT License](LICENSE).
