Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/octave_reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- run: pip install -e '.[test]'

# cross-validates PyBMD against the real bmd.m/cbmd.m under Octave; see
# docs/octave_cross_validation.md for the method and measured tables
# tests/octave/octave_cross_validation.md for the method and measured tables
- run: pytest tests/test_octave_reference.py -q
env:
PYBMD_REQUIRE_OCTAVE_REF: '1'
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ htmlcov/
# results written by fit() and by the examples
bmd_results/
example*_out/
cylinder_sumdiff_out/

# refs/ holds copies of external reference material used only for local/CI
# cross-validation (see docs/octave_cross_validation.md). The MATLAB source
# cross-validation (see tests/octave/octave_cross_validation.md). The MATLAB source
# itself (refs/bmd) is a git submodule -- tracked as a pointer, never
# vendored -- so its own license (research/non-commercial) never applies to
# this MIT-licensed repo. Everything else under refs/ (the paper preprint,
Expand Down
16 changes: 11 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ pip install -e '.[mpi,io,test]' # editable install; extras: mpi, io (.mat/.
git submodule update --init # populate refs/bmd (the MATLAB reference), only needed
# for tests/test_octave_reference.py -- see tests/CLAUDE.md

pytest # full suite, ~90 s, 169 tests: 13 `slow` (Octave
# cross-validation, figure regeneration), 1 `mpi`
pytest # full suite, 143 tests: 12 `slow` (Octave
# cross-validation), 1 `mpi`
pytest -m "not slow and not mpi" # fast subset, ~30 s
pytest tests/optimizers -q # one directory (numerical-radius solver tests,
# one test function per file)
pytest tests/test_bmd_serial.py::test_bispectrum_matches_closed_form -q # one test
pytest -k "conjugate or closed_form" # by name
pytest tests/test_hypothesis.py::test_resonant_triad_is_detected -q # one test
pytest -k "hypothesis or matlab_compat" # by name

python -m pyflakes pybmd/ tests/ examples/ # only linter used; ignore the
# "f-string is missing placeholders"
Expand All @@ -38,7 +38,13 @@ BLAS reorders reductions — so set the same when comparing MPI runs by hand.

Examples run from any directory (the fixture path is resolved relative to `examples/data.py`):
`MPLBACKEND=Agg python examples/example1_cylinder.py`; they write `example*_out/` in the working
directory.
directory. Examples 4 and 5 compare against Schmidt (2020)'s figures:
`examples/example4_hypothesis_testing.py` (surrogate data, Figs. 4-5; its helpers are also
imported by `tests/test_hypothesis.py`) and `examples/example5_cylinder_paper.py` (the
full-resolution cylinder bispectrum and the modes of its labelled triads, Figs. 7-9, ~2-4.5 min,
needs the `refs/bmd` submodule; see `examples/example5_cylinder_paper.md`). The Octave report
figures are regenerated by
`python tests/octave/build_report.py` into `tests/octave/figures/`.

## Architecture

Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ associated with it, distinguishing sum- from difference-interactions and produci
maps that identify the regions of nonlinear coupling.

The architecture follows [PySPOD](https://github.com/MathEXLab/PySPOD): a `params`-dict-driven
`Base`/`Standard` class pair, an optional MPI communicator, disk-backed mode storage, and a YAML
config reader.
`Base`/`Standard` class pair, an optional MPI communicator and disk-backed mode storage.

```
f2 or l
Expand Down Expand Up @@ -114,7 +113,10 @@ cbmd = Cross(params=dict(params, state_idx=[0], qr_idx=[[1, 2]]),
```

See [`examples/`](examples/) for the three worked cases, which mirror `example1.m`–`example3.m` of
the original MATLAB implementation.
the original MATLAB implementation, and for reproductions of Schmidt (2020)'s figures:
`example4_hypothesis_testing.py` (surrogate data, Figs. 4 and 5)
and `example5_cylinder_paper.py` (cylinder-wake mode bispectrum and modes, Figs. 7-9; see
`example5_cylinder_paper.md`).

## Parameters

Expand Down Expand Up @@ -183,7 +185,7 @@ is the default.
`MengiOverton` bug-for-bug, confirmed live
against the real MATLAB source under Octave to a few micro-relative on well-scaled problems. It
exists **only** to reproduce a specific published MATLAB result — it reproduces a confirmed
under-estimation bug and should never be used to analyse new data. See `docs/octave_cross_validation.md`
under-estimation bug and should never be used to analyse new data. See `tests/octave/octave_cross_validation.md`
for the measured figures and `pybmd.bmd.optimizers.mengi_overton`'s docstring for the caveats.

## Testing
Expand All @@ -193,12 +195,10 @@ pytest # everything, ~90 s (Octave cross-validation,
pytest -m "not slow and not mpi" # fast subset, ~30 s
```

The suite verifies the bispectrum against a **closed-form analytic result** — for an on-grid,
boxcar-windowed, block-random-phase signal, `L(k,l) = (a_k a_l a_{k+l} / 8) Σ w conj(φ_{k+l}) φ_k φ_l`
for every triad — as well as conjugate symmetry, exact triad counts, CBMD reducing to BMD when the
three variables coincide, bit-identical results between `mpirun -n 1` and `-n 2`, and a
regression against the original MATLAB implementation run live under Octave on the cylinder-wake
dataset (see [`tests/CLAUDE.md`](tests/CLAUDE.md)).
The suite checks the numerical-radius solvers against brute force, reproduces Schmidt (2020)'s
hypothesis test on surrogate data, asserts bit-identical results between `mpirun -n 1` and `-n 2`,
and regresses `L`, `T`, the modes and CBMD against the original MATLAB implementation run live
under Octave on the cylinder-wake dataset (see [`tests/CLAUDE.md`](tests/CLAUDE.md)).

## References

Expand Down
Loading
Loading