specmod 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {specmod-0.2.0 → specmod-0.2.2}/.github/workflows/docs.yml +6 -1
- {specmod-0.2.0 → specmod-0.2.2}/.github/workflows/release.yml +33 -9
- {specmod-0.2.0 → specmod-0.2.2}/.gitignore +11 -3
- {specmod-0.2.0 → specmod-0.2.2}/.readthedocs.yaml +7 -1
- specmod-0.2.2/.release-please-manifest.json +3 -0
- {specmod-0.2.0 → specmod-0.2.2}/CHANGELOG.md +33 -1
- {specmod-0.2.0 → specmod-0.2.2}/CITATION.cff +7 -0
- {specmod-0.2.0 → specmod-0.2.2}/PKG-INFO +34 -5
- {specmod-0.2.0 → specmod-0.2.2}/README.md +33 -4
- {specmod-0.2.0 → specmod-0.2.2}/docs/conf.py +61 -7
- {specmod-0.2.0 → specmod-0.2.2}/docs/documentation.md +39 -2
- {specmod-0.2.0 → specmod-0.2.2}/docs/index.md +10 -4
- {specmod-0.2.0 → specmod-0.2.2}/docs/releasing.md +80 -23
- specmod-0.2.2/docs/roadmap.md +157 -0
- specmod-0.2.2/tutorial/SpecModTutorial.ipynb +1032 -0
- specmod-0.2.0/.release-please-manifest.json +0 -3
- specmod-0.2.0/docs/roadmap.md +0 -109
- specmod-0.2.0/tutorial/SpecModTutorial.ipynb +0 -2000
- specmod-0.2.0/tutorial/data/events/2019-08-26T07:30:47.000000Z/spectra/2019-08-26T07:30:47.000000Z.h5 +0 -0
- specmod-0.2.0/tutorial/data/events/2019-08-26T07:30:47.000000Z/spectra/flatfiles/2019-08-26T07:30:47.000000Z.csv +0 -29
- specmod-0.2.0/tutorial/data/events/2019-08-26T07:30:47.000000Z/spectra/flatfiles/2019-08-26T07:30:47.000000Z.parquet +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/.git-blame-ignore-revs +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/.github/workflows/build.yml +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/.github/workflows/test.yml +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/.pre-commit-config.yaml +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/AGENTS.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/CLAUDE.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/CONTRIBUTING.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/LICENSE +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/datasets/magna_2020.toml +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/datasets/pnr_2019.toml +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/REFACTOR_PLAN.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/api.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/choosing-a-transform.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/development.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/notebooks/_build_notebook.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/notebooks/choosing-a-transform.ipynb +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/notes/api-audit.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/notes/window-position.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/pick-formats.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/processing.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/docs/releasing-data.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/pyproject.toml +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/release-please-config.json +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/requirements.txt +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/_vendor/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/_vendor/qiinv.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/acquire.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/api.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/cli.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/config/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/config/layers.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/config/provenance.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/config/sections.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/config/serialize.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/core/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/core/bandwidth.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/core/collection.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/core/noise.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/core/scalogram.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/core/spectrum.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/core/units.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/datasets.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/distance.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/exceptions.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/fitting/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/fitting/base.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/fitting/event.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/fitting/guess.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/fitting/spectrum.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/io.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/magnitude.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/picks/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/picks/base.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/picks/delimited.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/picks/events.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/picks/resolution.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/picks/snuffler.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/pipeline.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/plotting.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/preprocess.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/smoothing/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/smoothing/base.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/smoothing/konno_ohmachi.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/smoothing/log_bins.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/sources/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/sources/attenuation.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/sources/composite.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/sources/motion.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/sources/source.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/spreading.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/staged.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/tables.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/transforms/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/transforms/base.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/transforms/cwt.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/transforms/fft.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/transforms/multitaper.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/transforms/prieto.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/transforms/quadratic.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/src/specmod/utils.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/README.md +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/lmfit/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/lmfit/model.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/lmfit/parameter.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/clients/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/clients/fdsn/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/core/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/core/event.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/core/inventory.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/core/stream.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/core/trace.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/core/utcdatetime.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/core/util/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/core/util/base.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/geodetics/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/signal/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/stubs/obspy/signal/konnoohmachismoothing.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/studies/magna_2020_paper.toml +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/conftest.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/golden/motion_reference.json +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/golden/pipeline_reference.json +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/golden/window_reference.json +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_acquire.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_ambient_state.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_api_surface.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_collection.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_config.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_cwt.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_datasets.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_docs_are_current.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_end_to_end.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_fitting_defaults.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_golden_reference.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_import.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_io_and_plotting.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_legacy_fixes.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_magnitude.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_make_golden.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_pick_plugins.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_pick_readers.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_picks.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_pipeline.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_pipeline_smoke.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_preprocess.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_prieto.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_quadratic.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_release_config.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_smoothing.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_sources.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_spectral_wiring.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_staged.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_stubs.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_transforms.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_tutorial.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_typing_backlog.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_utils.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tests/test_versioning.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tools/check_built_version.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tools/check_floors.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tools/make_golden.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tools/measure_docs.py +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/picks/2019-08-26T07:30:47.000000Z.picks +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/picks/2019-08-26T07:30:47.000000Z.xml +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/stations/inventory.xml +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L001..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L001..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L001..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L002..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L002..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L002..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L006..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L006..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L006..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L007..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L007..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L007..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L008..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L008..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L008..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L009..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L009..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L009..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.LD06..HH1_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.LD06..HH2_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.LD06..HH3_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ01.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ01.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ01.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ02.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ03.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ03.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ03.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ04.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ04.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ04.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ05.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ05.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ05.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ06.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ06.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ06.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ07.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ07.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ07.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ09.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ09.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ09.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ10.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ10.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.2.0 → specmod-0.2.2}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ10.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
|
@@ -33,7 +33,12 @@ jobs:
|
|
|
33
33
|
|
|
34
34
|
# The package itself, not just the docs extra: autodoc imports every
|
|
35
35
|
# module it documents, so a docs build is also an import check.
|
|
36
|
-
|
|
36
|
+
#
|
|
37
|
+
# `tutorial` supplies the Jupyter kernel. `docs/conf.py` executes the
|
|
38
|
+
# tutorial notebook on every build instead of trusting committed outputs,
|
|
39
|
+
# so without ipykernel the build fails on a missing kernel. Keep this list
|
|
40
|
+
# in step with `.readthedocs.yaml`, which installs the same three.
|
|
41
|
+
- run: uv pip install -e ".[docs,io,tutorial]"
|
|
37
42
|
|
|
38
43
|
- name: Build
|
|
39
44
|
# No -W. Intersphinx resolves seven inventories over the network and
|
|
@@ -28,20 +28,44 @@ jobs:
|
|
|
28
28
|
- uses: googleapis/release-please-action@v4
|
|
29
29
|
id: release
|
|
30
30
|
with:
|
|
31
|
+
# A pull request opened with the default GITHUB_TOKEN starts no
|
|
32
|
+
# workflow runs at all — "events triggered by the GITHUB_TOKEN will
|
|
33
|
+
# not create a new workflow run". The release PR therefore arrived
|
|
34
|
+
# with *zero* checks, and since `ci`, `docs` and `build` are required
|
|
35
|
+
# on main, it could never satisfy them: permanently blocked, with no
|
|
36
|
+
# failure to point at. v0.2.0 shipped only because the PR was closed
|
|
37
|
+
# and reopened by hand, which re-fires the event from a real account.
|
|
38
|
+
#
|
|
39
|
+
# RELEASE_PLEASE_TOKEN_SPECMOD is a fine-grained PAT (contents + pull
|
|
40
|
+
# requests, write) so the PR is opened by a user and CI runs on it
|
|
41
|
+
# normally. It is *not* a PyPI credential — the upload below still
|
|
42
|
+
# authenticates by OIDC, so the number of publishing secrets is
|
|
43
|
+
# still zero. See docs/releasing.md for how to mint and renew it.
|
|
44
|
+
#
|
|
45
|
+
# The fallback keeps the workflow working in a fork or before the
|
|
46
|
+
# secret exists; it degrades to the blocked-PR behaviour, not to a
|
|
47
|
+
# broken run.
|
|
48
|
+
token: ${{ secrets.RELEASE_PLEASE_TOKEN_SPECMOD || secrets.GITHUB_TOKEN }}
|
|
31
49
|
config-file: release-please-config.json
|
|
32
50
|
manifest-file: .release-please-manifest.json
|
|
33
51
|
|
|
34
52
|
# Deliberately in this workflow rather than a separate publish.yml keyed on
|
|
35
|
-
# `release: published`, which is what §6.5 of the plan used to describe.
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
# new workflow run" — so that publish workflow would never fire. The
|
|
39
|
-
# alternative is a personal access token in secrets, which is the one thing
|
|
40
|
-
# Trusted Publishing exists to avoid. Gating on the action's own output
|
|
41
|
-
# keeps the token count at zero.
|
|
53
|
+
# `release: published`, which is what §6.5 of the plan used to describe. That
|
|
54
|
+
# workflow could not fire at all while release-please ran on GITHUB_TOKEN,
|
|
55
|
+
# so this job gates on the action's own `release_created` output instead.
|
|
42
56
|
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
57
|
+
# With RELEASE_PLEASE_TOKEN_SPECMOD the release is created by a PAT, which
|
|
58
|
+
# *does* start workflow runs, so a separate publish.yml would now work. Still
|
|
59
|
+
# not worth splitting: one workflow is one concurrency group and one place to
|
|
60
|
+
# read, with no race between two runs when two merges land together. The
|
|
61
|
+
# `release_created` gate is also exact, where an event key would fire on any
|
|
62
|
+
# release — including one created by hand.
|
|
63
|
+
#
|
|
64
|
+
# Note the PAT is not a publishing credential: the upload below authenticates
|
|
65
|
+
# by OIDC, so the number of secrets that can push to PyPI is still zero.
|
|
66
|
+
#
|
|
67
|
+
# Zenodo is unaffected either way: it listens to the release *webhook*, which
|
|
68
|
+
# is not subject to the token restriction, so the DOI is minted regardless.
|
|
45
69
|
publish:
|
|
46
70
|
needs: release-please
|
|
47
71
|
if: needs.release-please.outputs.release_created == 'true'
|
|
@@ -26,6 +26,11 @@ htmlcov/
|
|
|
26
26
|
|
|
27
27
|
# Docs
|
|
28
28
|
docs/_build/
|
|
29
|
+
# `docs/conf.py` copies `tutorial/` here so Sphinx can build the notebook from
|
|
30
|
+
# inside its source directory, with the data it reads by relative path. The
|
|
31
|
+
# copy is also what the notebook's own output lands in, which is the point —
|
|
32
|
+
# executing it where it lives would write into the working tree.
|
|
33
|
+
docs/tutorial/
|
|
29
34
|
|
|
30
35
|
# Editors / OS
|
|
31
36
|
.ftpconfig
|
|
@@ -39,9 +44,12 @@ docs/_build/
|
|
|
39
44
|
|
|
40
45
|
# Tutorial output. Regenerated by running the notebook; committing it means a
|
|
41
46
|
# diff every time anyone executes it, and a stale copy the moment the pipeline
|
|
42
|
-
# changes. The inputs
|
|
43
|
-
|
|
44
|
-
Tutorial/Spectra
|
|
47
|
+
# changes. The inputs — waveforms, stations, picks — *are* committed.
|
|
48
|
+
#
|
|
49
|
+
# These patterns named `Tutorial/Spectra/` until now, the capitalised layout
|
|
50
|
+
# from before the `src/` move, so they had matched nothing for the whole
|
|
51
|
+
# refactor and the three files below were tracked in spite of the rule above.
|
|
52
|
+
tutorial/data/events/*/spectra/
|
|
45
53
|
|
|
46
54
|
# Created by `uv run` without --no-sync; this project resolves fresh on
|
|
47
55
|
# purpose so the floors job can test the declared minimums.
|
|
@@ -42,6 +42,12 @@ python:
|
|
|
42
42
|
extra_requirements:
|
|
43
43
|
# `io` alongside `docs` because autodoc imports every module it
|
|
44
44
|
# documents, and `specmod.io` imports h5py and pyarrow. Without it the
|
|
45
|
-
# API reference loses those pages to import errors
|
|
45
|
+
# API reference loses those pages to import errors — and the tutorial
|
|
46
|
+
# saves an HDF5 file, so it needs them at execution time too.
|
|
46
47
|
- docs
|
|
47
48
|
- io
|
|
49
|
+
# `tutorial` supplies the Jupyter kernel. `docs/conf.py` executes the
|
|
50
|
+
# notebook on every build rather than trusting committed outputs, which
|
|
51
|
+
# needs ipykernel, nbclient and nbformat present. Without it the build
|
|
52
|
+
# fails on a missing kernel rather than quietly publishing stale cells.
|
|
53
|
+
- tutorial
|
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<!-- The 0.2.0 heading below is edited by hand, and is the only entry that is.
|
|
4
|
+
release-please generated `compare/v0.1.1...v0.2.0`, which 404s: 0.1.1 predates
|
|
5
|
+
this repository's tagging and was never tagged, so there is nothing at that
|
|
6
|
+
ref. It is preserved on the frozen `master` branch instead, and comparing
|
|
7
|
+
against that branch is the same diff under a name that resolves. Only the first
|
|
8
|
+
release could have this problem — every later one has a real predecessor tag —
|
|
9
|
+
so leave subsequent headings as generated. release-please only prepends to this
|
|
10
|
+
file, so this edit survives. -->
|
|
11
|
+
|
|
12
|
+
## [0.2.2](https://github.com/sgjholt/SpecMod/compare/v0.2.1...v0.2.2) (2026-09-05)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* ignore the tutorial output at the path it is actually written to ([ad34cc7](https://github.com/sgjholt/SpecMod/commit/ad34cc7d44208e5bd49a2d1f1277516670848dc7))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Documentation
|
|
21
|
+
|
|
22
|
+
* publish the tutorial, executed on every build ([ccd1842](https://github.com/sgjholt/SpecMod/commit/ccd18429b9da5db875885d88269fb70686e6eaa3))
|
|
23
|
+
|
|
24
|
+
## [0.2.1](https://github.com/sgjholt/SpecMod/compare/v0.2.0...v0.2.1) (2026-08-23)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Documentation
|
|
28
|
+
|
|
29
|
+
* add the Zenodo DOI to the README and the citation metadata ([8a89884](https://github.com/sgjholt/SpecMod/commit/8a89884f654b14bf5eb9ed8a32d10dc22d5e5fb4))
|
|
30
|
+
* PyPI and docs badges, and an install section for people who are not us ([d444397](https://github.com/sgjholt/SpecMod/commit/d44439762214b93fd8eef3f64745570b3b8be2b0))
|
|
31
|
+
* repoint the 0.2.0 changelog link, which 404s ([f1bbe31](https://github.com/sgjholt/SpecMod/commit/f1bbe3143ca3ca6dd58f584546e716d2170a790a))
|
|
32
|
+
* say where the code behind the publication lives ([ae7e906](https://github.com/sgjholt/SpecMod/commit/ae7e906209a87844cf2106a826be5111a6ef2036))
|
|
33
|
+
* turn the roadmap's stages into milestones against versions ([b933e69](https://github.com/sgjholt/SpecMod/commit/b933e69d219a54e4a7db894797a507a3bb24e31c))
|
|
34
|
+
|
|
35
|
+
## [0.2.0](https://github.com/sgjholt/SpecMod/compare/master...v0.2.0) (2026-08-23)
|
|
4
36
|
|
|
5
37
|
|
|
6
38
|
### ⚠ BREAKING CHANGES
|
|
@@ -7,6 +7,13 @@ authors:
|
|
|
7
7
|
given-names: James
|
|
8
8
|
repository-code: "https://github.com/sgjholt/SpecMod"
|
|
9
9
|
license: MIT
|
|
10
|
+
identifiers:
|
|
11
|
+
# The concept DOI, which always resolves to the newest release. Zenodo also
|
|
12
|
+
# mints a version DOI per release; cite that one instead when reproducibility
|
|
13
|
+
# matters and you need the reader to land on the exact version you ran.
|
|
14
|
+
- type: doi
|
|
15
|
+
value: "10.5281/zenodo.22071455"
|
|
16
|
+
description: "Concept DOI — resolves to the latest release."
|
|
10
17
|
keywords:
|
|
11
18
|
- seismology
|
|
12
19
|
- spectral modelling
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: specmod
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A Python toolbox for processing and modelling seismic spectra
|
|
5
5
|
Project-URL: Homepage, https://github.com/sgjholt/SpecMod
|
|
6
6
|
Project-URL: Repository, https://github.com/sgjholt/SpecMod
|
|
@@ -56,6 +56,10 @@ Description-Content-Type: text/markdown
|
|
|
56
56
|
|
|
57
57
|
# SpecMod
|
|
58
58
|
|
|
59
|
+
[](https://pypi.org/project/specmod/)
|
|
60
|
+
[](https://specmod.readthedocs.io/en/stable/)
|
|
61
|
+
[](https://doi.org/10.5281/zenodo.22071455)
|
|
62
|
+
|
|
59
63
|
A Python toolbox for processing and modelling seismic spectra, following the
|
|
60
64
|
method of Edwards *et al.* (2010).
|
|
61
65
|
|
|
@@ -71,26 +75,44 @@ source model to direct-phase spectra.
|
|
|
71
75
|
> breaking changes at every `0.x` release until the API settles at 1.0 — they
|
|
72
76
|
> land in minor bumps by design, with no deprecation cycle. Pin an exact
|
|
73
77
|
> version for anything you intend to publish.
|
|
74
|
-
> [`docs/roadmap.md`](docs/roadmap.md) says
|
|
75
|
-
> will mean; [`docs/REFACTOR_PLAN.md`](docs/REFACTOR_PLAN.md) is
|
|
76
|
-
> document behind it.
|
|
78
|
+
> [`docs/roadmap.md`](docs/roadmap.md) says what has shipped, in which version,
|
|
79
|
+
> and what 1.0 will mean; [`docs/REFACTOR_PLAN.md`](docs/REFACTOR_PLAN.md) is
|
|
80
|
+
> the working document behind it.
|
|
77
81
|
|
|
78
82
|
## Installation
|
|
79
83
|
|
|
80
84
|
Requires Python 3.11 or newer.
|
|
81
85
|
|
|
86
|
+
```sh
|
|
87
|
+
pip install specmod
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
While this is `0.x`, pin the exact version in anything you intend to publish:
|
|
91
|
+
`pip install specmod==<version>`, taking the current one from the badge above.
|
|
92
|
+
The reason is in the status note — `0.x` releases move names and numbers, and
|
|
93
|
+
the pin plus the configuration stamp each output carries are together what
|
|
94
|
+
make a run reproducible.
|
|
95
|
+
|
|
96
|
+
To work on SpecMod rather than with it, clone the repository and install it
|
|
97
|
+
editable with the test and lint tooling:
|
|
98
|
+
|
|
82
99
|
```sh
|
|
83
100
|
pip install -e ".[dev]"
|
|
84
101
|
```
|
|
85
102
|
|
|
86
|
-
Optional extras
|
|
103
|
+
Optional extras, installable as `pip install "specmod[multitaper]"` or in
|
|
104
|
+
combination — `pip install "specmod[multitaper,wavelet]"`:
|
|
87
105
|
|
|
88
106
|
| Extra | Adds |
|
|
89
107
|
|---|---|
|
|
108
|
+
| `io` | `h5py` and `pyarrow` — needed to save or load spectra, as HDF5 for arrays and Parquet for tables |
|
|
90
109
|
| `multitaper` | Prieto's `multitaper` package — jackknife confidence intervals, F-test for spectral lines |
|
|
91
110
|
| `wavelet` | PyWavelets, for wavelet families beyond the built-in Morlet |
|
|
92
111
|
| `mcmc` | `emcee`, for Markov-chain Monte Carlo parameter search |
|
|
93
112
|
|
|
113
|
+
`io` is the one most people want: without it SpecMod computes and plots
|
|
114
|
+
normally, but `specmod.io` raises on the first save telling you to install it.
|
|
115
|
+
|
|
94
116
|
No Fortran compiler is needed. Multitaper estimation is implemented natively on
|
|
95
117
|
SciPy's DPSS tapers, so the historical `mtspec` dependency — Fortran source with
|
|
96
118
|
no wheels and no release since 2016 — is no longer required.
|
|
@@ -202,6 +224,13 @@ Every output records the configuration that produced it, a hash of it, and the
|
|
|
202
224
|
SpecMod version, so a locally-overridden run is still reproducible from its
|
|
203
225
|
outputs.
|
|
204
226
|
|
|
227
|
+
The published Magna results were produced with **0.1.1**, which predates this
|
|
228
|
+
refactor. That code is preserved unchanged on the
|
|
229
|
+
[`master`](https://github.com/sgjholt/SpecMod/tree/master) branch, which is
|
|
230
|
+
protected and frozen; `main` is the trunk now. `0.1.1` was never tagged or
|
|
231
|
+
published to PyPI, so the branch is the reference — there is no release to
|
|
232
|
+
install. Read it there when you need to see exactly what the paper ran.
|
|
233
|
+
|
|
205
234
|
## Documentation
|
|
206
235
|
|
|
207
236
|
The full documentation — the pipeline with its equations, the estimator
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# SpecMod
|
|
2
2
|
|
|
3
|
+
[](https://pypi.org/project/specmod/)
|
|
4
|
+
[](https://specmod.readthedocs.io/en/stable/)
|
|
5
|
+
[](https://doi.org/10.5281/zenodo.22071455)
|
|
6
|
+
|
|
3
7
|
A Python toolbox for processing and modelling seismic spectra, following the
|
|
4
8
|
method of Edwards *et al.* (2010).
|
|
5
9
|
|
|
@@ -15,26 +19,44 @@ source model to direct-phase spectra.
|
|
|
15
19
|
> breaking changes at every `0.x` release until the API settles at 1.0 — they
|
|
16
20
|
> land in minor bumps by design, with no deprecation cycle. Pin an exact
|
|
17
21
|
> version for anything you intend to publish.
|
|
18
|
-
> [`docs/roadmap.md`](docs/roadmap.md) says
|
|
19
|
-
> will mean; [`docs/REFACTOR_PLAN.md`](docs/REFACTOR_PLAN.md) is
|
|
20
|
-
> document behind it.
|
|
22
|
+
> [`docs/roadmap.md`](docs/roadmap.md) says what has shipped, in which version,
|
|
23
|
+
> and what 1.0 will mean; [`docs/REFACTOR_PLAN.md`](docs/REFACTOR_PLAN.md) is
|
|
24
|
+
> the working document behind it.
|
|
21
25
|
|
|
22
26
|
## Installation
|
|
23
27
|
|
|
24
28
|
Requires Python 3.11 or newer.
|
|
25
29
|
|
|
30
|
+
```sh
|
|
31
|
+
pip install specmod
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
While this is `0.x`, pin the exact version in anything you intend to publish:
|
|
35
|
+
`pip install specmod==<version>`, taking the current one from the badge above.
|
|
36
|
+
The reason is in the status note — `0.x` releases move names and numbers, and
|
|
37
|
+
the pin plus the configuration stamp each output carries are together what
|
|
38
|
+
make a run reproducible.
|
|
39
|
+
|
|
40
|
+
To work on SpecMod rather than with it, clone the repository and install it
|
|
41
|
+
editable with the test and lint tooling:
|
|
42
|
+
|
|
26
43
|
```sh
|
|
27
44
|
pip install -e ".[dev]"
|
|
28
45
|
```
|
|
29
46
|
|
|
30
|
-
Optional extras
|
|
47
|
+
Optional extras, installable as `pip install "specmod[multitaper]"` or in
|
|
48
|
+
combination — `pip install "specmod[multitaper,wavelet]"`:
|
|
31
49
|
|
|
32
50
|
| Extra | Adds |
|
|
33
51
|
|---|---|
|
|
52
|
+
| `io` | `h5py` and `pyarrow` — needed to save or load spectra, as HDF5 for arrays and Parquet for tables |
|
|
34
53
|
| `multitaper` | Prieto's `multitaper` package — jackknife confidence intervals, F-test for spectral lines |
|
|
35
54
|
| `wavelet` | PyWavelets, for wavelet families beyond the built-in Morlet |
|
|
36
55
|
| `mcmc` | `emcee`, for Markov-chain Monte Carlo parameter search |
|
|
37
56
|
|
|
57
|
+
`io` is the one most people want: without it SpecMod computes and plots
|
|
58
|
+
normally, but `specmod.io` raises on the first save telling you to install it.
|
|
59
|
+
|
|
38
60
|
No Fortran compiler is needed. Multitaper estimation is implemented natively on
|
|
39
61
|
SciPy's DPSS tapers, so the historical `mtspec` dependency — Fortran source with
|
|
40
62
|
no wheels and no release since 2016 — is no longer required.
|
|
@@ -146,6 +168,13 @@ Every output records the configuration that produced it, a hash of it, and the
|
|
|
146
168
|
SpecMod version, so a locally-overridden run is still reproducible from its
|
|
147
169
|
outputs.
|
|
148
170
|
|
|
171
|
+
The published Magna results were produced with **0.1.1**, which predates this
|
|
172
|
+
refactor. That code is preserved unchanged on the
|
|
173
|
+
[`master`](https://github.com/sgjholt/SpecMod/tree/master) branch, which is
|
|
174
|
+
protected and frozen; `main` is the trunk now. `0.1.1` was never tagged or
|
|
175
|
+
published to PyPI, so the branch is the reference — there is no release to
|
|
176
|
+
install. Read it there when you need to see exactly what the paper ran.
|
|
177
|
+
|
|
149
178
|
## Documentation
|
|
150
179
|
|
|
151
180
|
The full documentation — the pipeline with its equations, the estimator
|
|
@@ -14,7 +14,9 @@ gives.
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
+
import shutil
|
|
17
18
|
from importlib.metadata import PackageNotFoundError, version
|
|
19
|
+
from pathlib import Path
|
|
18
20
|
|
|
19
21
|
project = "SpecMod"
|
|
20
22
|
author = "James Holt"
|
|
@@ -32,7 +34,9 @@ except PackageNotFoundError: # pragma: no cover - docs built without an install
|
|
|
32
34
|
version = ".".join(release.split(".")[:2])
|
|
33
35
|
|
|
34
36
|
extensions = [
|
|
35
|
-
|
|
37
|
+
#: `myst_nb` supersedes `myst_parser` — it is a superset, and loading both
|
|
38
|
+
#: makes Sphinx complain that the `.md` parser is registered twice.
|
|
39
|
+
"myst_nb",
|
|
36
40
|
"sphinx.ext.autodoc",
|
|
37
41
|
"sphinx.ext.napoleon",
|
|
38
42
|
"sphinx.ext.intersphinx",
|
|
@@ -45,9 +49,10 @@ extensions = [
|
|
|
45
49
|
|
|
46
50
|
#: `REFACTOR_PLAN.md` is a working document, not documentation — it is written
|
|
47
51
|
#: for whoever is doing the refactor and records decisions and their evidence.
|
|
48
|
-
#: `notebooks/`
|
|
49
|
-
#:
|
|
50
|
-
#:
|
|
52
|
+
#: `notebooks/` holds the source for the transform comparison, which
|
|
53
|
+
#: `tools/measure_docs.py` renders into `choosing-a-transform.md`; the page is
|
|
54
|
+
#: what is published, so building the notebook too would duplicate it.
|
|
55
|
+
#: `notes/` *is* included: `choosing-a-transform.md` links to it for a
|
|
51
56
|
#: per-trace table, so excluding it broke that link.
|
|
52
57
|
exclude_patterns = [
|
|
53
58
|
"_build",
|
|
@@ -57,9 +62,58 @@ exclude_patterns = [
|
|
|
57
62
|
".DS_Store",
|
|
58
63
|
]
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
# ------------------------------------------------------- the tutorial notebook
|
|
66
|
+
|
|
67
|
+
#: The tutorial lives in `tutorial/`, outside this source directory, next to the
|
|
68
|
+
#: 1 MB of PNR waveforms it reads through paths relative to itself. Sphinx only
|
|
69
|
+
#: builds what is under `docs/`, so it is copied in here.
|
|
70
|
+
#:
|
|
71
|
+
#: A copy rather than a move, and rather than executing it where it sits,
|
|
72
|
+
#: because **the notebook writes**: cell 53 saves an HDF5 file under
|
|
73
|
+
#: `data/events/<event>/spectra/` and cell 54 writes flatfiles beside it. Run in
|
|
74
|
+
#: place, a docs build would leave those artefacts in the working tree — which
|
|
75
|
+
#: is why `tests/test_tutorial.py` executes it in a `tmp_path` copy too. This is
|
|
76
|
+
#: the same trick, and the copy is what the artefacts land in.
|
|
77
|
+
#:
|
|
78
|
+
#: Copying the data with it is what keeps the notebook's `Path("data/events")`
|
|
79
|
+
#: working, so the notebook is identical whether opened from `tutorial/`, run by
|
|
80
|
+
#: pytest, or built here. `tutorial/` stays canonical: eight other files name
|
|
81
|
+
#: `tutorial/data/events/`, and the CI job that executes it records that a
|
|
82
|
+
#: renamed data directory has already broken this once.
|
|
83
|
+
_HERE = Path(__file__).parent
|
|
84
|
+
_TUTORIAL_SRC = _HERE.parent / "tutorial"
|
|
85
|
+
_TUTORIAL_DST = _HERE / "tutorial"
|
|
86
|
+
|
|
87
|
+
if _TUTORIAL_SRC.is_dir():
|
|
88
|
+
shutil.rmtree(_TUTORIAL_DST, ignore_errors=True)
|
|
89
|
+
shutil.copytree(_TUTORIAL_SRC, _TUTORIAL_DST)
|
|
90
|
+
|
|
91
|
+
#: `force`, not `auto`. `auto` executes only notebooks that arrive without
|
|
92
|
+
#: outputs, and the tutorial is committed *with* 28 cells of them — so `auto`
|
|
93
|
+
#: would publish whatever was last saved by hand, which is the silent rot this
|
|
94
|
+
#: is meant to end. Forcing it means the page can only show output the code
|
|
95
|
+
#: actually produced against the code being documented.
|
|
96
|
+
nb_execution_mode = "force"
|
|
97
|
+
#: Matches `tests/test_tutorial.py`. The whole notebook runs in ~40s; the
|
|
98
|
+
#: default 30s is per cell, and the two-stage fit is the one that would trip it.
|
|
99
|
+
nb_execution_timeout = 600
|
|
100
|
+
#: A notebook that raises fails the build. That is the point: an executed
|
|
101
|
+
#: tutorial is only a guarantee if a broken one is loud.
|
|
102
|
+
nb_execution_raise_on_error = True
|
|
103
|
+
#: `False` keeps the kernel's working directory at the notebook's own, which is
|
|
104
|
+
#: what `Path("data/events")` resolves against.
|
|
105
|
+
nb_execution_in_temp = False
|
|
106
|
+
|
|
107
|
+
#: Markdown for the prose pages — every one in `docs/` is written that way, and
|
|
108
|
+
#: allowing reStructuredText too would mean two syntaxes for the same job — plus
|
|
109
|
+
#: `.ipynb` for the tutorial.
|
|
110
|
+
#:
|
|
111
|
+
#: Both map to `myst-nb`, which is the only parser name `myst_nb` 1.4 registers:
|
|
112
|
+
#: it does not re-register `myst_parser`'s `markdown`, so leaving `.md` pointing
|
|
113
|
+
#: at that fails the build outright with "Source parser for markdown not
|
|
114
|
+
#: registered". The `myst-nb` parser is a superset and reads the prose pages
|
|
115
|
+
#: identically.
|
|
116
|
+
source_suffix = {".md": "myst-nb", ".ipynb": "myst-nb"}
|
|
63
117
|
|
|
64
118
|
#: `linkify` is deliberately absent: it needs `linkify-it-py` and every link in
|
|
65
119
|
#: these pages is already explicit.
|
|
@@ -195,8 +195,11 @@ pages can link to each other's sections.
|
|
|
195
195
|
those work; without it MyST does not read `$` at all.
|
|
196
196
|
- `amsmath` is **not** enabled — nothing here uses a bare `\begin{align}`
|
|
197
197
|
outside `$` delimiters. A `\begin{cases}` inside `$$` renders without it.
|
|
198
|
-
- Markdown
|
|
199
|
-
`docs/`, so there is one
|
|
198
|
+
- Markdown and notebooks. `source_suffix` maps `.md` and `.ipynb`, both to
|
|
199
|
+
`myst-nb` — there is no reStructuredText in `docs/`, so there is one prose
|
|
200
|
+
syntax rather than two. Both suffixes name `myst-nb` because that is the only
|
|
201
|
+
parser `myst_nb` registers; pointing `.md` at `myst_parser`'s `markdown`
|
|
202
|
+
fails the build with "Source parser for markdown not registered".
|
|
200
203
|
- For a Sphinx directive that has no MyST spelling, drop into rST:
|
|
201
204
|
|
|
202
205
|
````markdown
|
|
@@ -225,6 +228,40 @@ Type hints come from the annotations via `autodoc_typehints = "description"`.
|
|
|
225
228
|
`sphinx-autodoc-typehints` is deliberately **not** used: measured, it produced
|
|
226
229
|
the same 367 documented objects while calling an API Sphinx 10 removes.
|
|
227
230
|
|
|
231
|
+
### The tutorial notebook
|
|
232
|
+
|
|
233
|
+
`tutorial/SpecModTutorial.ipynb` is published as part of the site and
|
|
234
|
+
**executed on every build** (`nb_execution_mode = "force"`). Every figure and
|
|
235
|
+
number on the page came from running that code against the code being
|
|
236
|
+
documented, and a notebook that raises fails the build
|
|
237
|
+
(`nb_execution_raise_on_error = True`). That is the whole point: a tutorial
|
|
238
|
+
nobody runs is the first thing to rot, and this one broke three times before
|
|
239
|
+
anything executed it.
|
|
240
|
+
|
|
241
|
+
Three things about the arrangement are worth knowing before changing it.
|
|
242
|
+
|
|
243
|
+
**It is copied into `docs/tutorial/` by `conf.py`, not moved.** Sphinx builds
|
|
244
|
+
only what is under `docs/`, and the notebook reads its 1 MB of waveforms
|
|
245
|
+
through paths relative to itself — so the data has to travel with it. The copy
|
|
246
|
+
is gitignored. `tutorial/` stays canonical because eight other files name
|
|
247
|
+
`tutorial/data/events/`, and a renamed data directory has broken this before.
|
|
248
|
+
|
|
249
|
+
**The copy is also what the notebook writes into.** It saves an HDF5 file and
|
|
250
|
+
two flatfiles as part of the lesson. Executed where it lives, a docs build
|
|
251
|
+
would leave those in your working tree; `tests/test_tutorial.py` copies to
|
|
252
|
+
`tmp_path` for exactly the same reason.
|
|
253
|
+
|
|
254
|
+
**Outputs are stripped in git**, by the `nbstripout` pre-commit hook, and
|
|
255
|
+
regenerated at build time. Do not commit them back: `force` ignores them, so a
|
|
256
|
+
committed output is never what a reader sees — only a stale diff.
|
|
257
|
+
|
|
258
|
+
The kernel comes from the `tutorial` extra. Both `.readthedocs.yaml` and
|
|
259
|
+
`.github/workflows/docs.yml` install `[docs,io,tutorial]`; keep them in step or
|
|
260
|
+
one of the two builds fails on a missing kernel. This does mean the notebook
|
|
261
|
+
executes twice per pull request — once here and once in the `notebook` CI job,
|
|
262
|
+
which also checks imports and that deleted modules stay unmentioned. Roughly
|
|
263
|
+
40 seconds, paid twice, for two genuinely different failures.
|
|
264
|
+
|
|
228
265
|
### Numbers in prose
|
|
229
266
|
|
|
230
267
|
Any table that came from a measurement is generated, not typed. Edit
|
|
@@ -24,8 +24,8 @@ treat everything here as provisional until the API settles at 1.0:
|
|
|
24
24
|
|
|
25
25
|
What will *not* change silently: the units conventions and the Parseval
|
|
26
26
|
contract are pinned by tests, and the golden references fail loudly rather
|
|
27
|
-
than drifting. The [roadmap](roadmap.md) says
|
|
28
|
-
1.0 will mean.
|
|
27
|
+
than drifting. The [roadmap](roadmap.md) says what has shipped, in which
|
|
28
|
+
version, and what 1.0 will mean.
|
|
29
29
|
:::
|
|
30
30
|
|
|
31
31
|
```python
|
|
@@ -45,6 +45,11 @@ print(fits.table[["id", "llpsp", "fc", "ts"]])
|
|
|
45
45
|
|
|
46
46
|
## Where to start
|
|
47
47
|
|
|
48
|
+
[Tutorial](tutorial/SpecModTutorial.ipynb)
|
|
49
|
+
: One event end to end — waveforms and picks in, source parameters out. Every
|
|
50
|
+
figure and number on the page is produced by running the notebook at build
|
|
51
|
+
time, so it cannot describe an API that no longer exists.
|
|
52
|
+
|
|
48
53
|
[Processing](processing.md)
|
|
49
54
|
: Every step of the pipeline with the equation it implements — what a window
|
|
50
55
|
is, how the noise is compared against it, and what the bandwidth selector
|
|
@@ -67,8 +72,8 @@ print(fits.table[["id", "llpsp", "fc", "ts"]])
|
|
|
67
72
|
settings that have to be turned on once.
|
|
68
73
|
|
|
69
74
|
[Roadmap](roadmap.md)
|
|
70
|
-
: What
|
|
71
|
-
dates.
|
|
75
|
+
: What has shipped and in which version, what is being worked on, and what 1.0
|
|
76
|
+
will mean. Milestones, not dates.
|
|
72
77
|
|
|
73
78
|
## Working on SpecMod
|
|
74
79
|
|
|
@@ -97,6 +102,7 @@ one either way.
|
|
|
97
102
|
:maxdepth: 2
|
|
98
103
|
:hidden:
|
|
99
104
|
|
|
105
|
+
tutorial/SpecModTutorial
|
|
100
106
|
processing
|
|
101
107
|
choosing-a-transform
|
|
102
108
|
pick-formats
|