specmod 0.2.0__tar.gz → 0.2.1__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.1}/.github/workflows/release.yml +33 -9
- specmod-0.2.1/.release-please-manifest.json +3 -0
- {specmod-0.2.0 → specmod-0.2.1}/CHANGELOG.md +21 -1
- {specmod-0.2.0 → specmod-0.2.1}/CITATION.cff +7 -0
- {specmod-0.2.0 → specmod-0.2.1}/PKG-INFO +34 -5
- {specmod-0.2.0 → specmod-0.2.1}/README.md +33 -4
- {specmod-0.2.0 → specmod-0.2.1}/docs/index.md +4 -4
- {specmod-0.2.0 → specmod-0.2.1}/docs/releasing.md +80 -23
- specmod-0.2.1/docs/roadmap.md +148 -0
- specmod-0.2.0/.release-please-manifest.json +0 -3
- specmod-0.2.0/docs/roadmap.md +0 -109
- {specmod-0.2.0 → specmod-0.2.1}/.git-blame-ignore-revs +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/.github/workflows/build.yml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/.github/workflows/docs.yml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/.github/workflows/test.yml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/.gitignore +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/.pre-commit-config.yaml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/.readthedocs.yaml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/AGENTS.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/CLAUDE.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/CONTRIBUTING.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/LICENSE +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/datasets/magna_2020.toml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/datasets/pnr_2019.toml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/REFACTOR_PLAN.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/api.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/choosing-a-transform.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/conf.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/development.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/documentation.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/notebooks/_build_notebook.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/notebooks/choosing-a-transform.ipynb +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/notes/api-audit.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/notes/window-position.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/pick-formats.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/processing.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/docs/releasing-data.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/pyproject.toml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/release-please-config.json +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/requirements.txt +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/_vendor/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/_vendor/qiinv.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/acquire.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/api.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/cli.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/config/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/config/layers.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/config/provenance.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/config/sections.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/config/serialize.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/core/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/core/bandwidth.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/core/collection.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/core/noise.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/core/scalogram.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/core/spectrum.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/core/units.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/datasets.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/distance.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/exceptions.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/fitting/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/fitting/base.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/fitting/event.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/fitting/guess.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/fitting/spectrum.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/io.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/magnitude.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/picks/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/picks/base.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/picks/delimited.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/picks/events.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/picks/resolution.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/picks/snuffler.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/pipeline.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/plotting.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/preprocess.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/smoothing/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/smoothing/base.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/smoothing/konno_ohmachi.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/smoothing/log_bins.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/sources/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/sources/attenuation.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/sources/composite.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/sources/motion.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/sources/source.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/spreading.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/staged.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/tables.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/transforms/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/transforms/base.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/transforms/cwt.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/transforms/fft.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/transforms/multitaper.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/transforms/prieto.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/transforms/quadratic.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/src/specmod/utils.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/README.md +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/lmfit/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/lmfit/model.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/lmfit/parameter.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/clients/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/clients/fdsn/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/core/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/core/event.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/core/inventory.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/core/stream.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/core/trace.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/core/utcdatetime.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/core/util/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/core/util/base.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/geodetics/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/signal/__init__.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/stubs/obspy/signal/konnoohmachismoothing.pyi +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/studies/magna_2020_paper.toml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/__init__.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/conftest.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/golden/motion_reference.json +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/golden/pipeline_reference.json +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/golden/window_reference.json +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_acquire.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_ambient_state.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_api_surface.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_collection.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_config.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_cwt.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_datasets.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_docs_are_current.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_end_to_end.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_fitting_defaults.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_golden_reference.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_import.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_io_and_plotting.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_legacy_fixes.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_magnitude.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_make_golden.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_pick_plugins.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_pick_readers.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_picks.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_pipeline.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_pipeline_smoke.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_preprocess.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_prieto.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_quadratic.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_release_config.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_smoothing.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_sources.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_spectral_wiring.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_staged.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_stubs.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_transforms.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_tutorial.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_typing_backlog.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_utils.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tests/test_versioning.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tools/check_built_version.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tools/check_floors.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tools/make_golden.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tools/measure_docs.py +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tutorial/SpecModTutorial.ipynb +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/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.1}/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.1}/tutorial/data/events/2019-08-26T07:30:47.000000Z/spectra/2019-08-26T07:30:47.000000Z.h5 +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/tutorial/data/events/2019-08-26T07:30:47.000000Z/spectra/flatfiles/2019-08-26T07:30:47.000000Z.csv +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/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.1}/tutorial/data/events/2019-08-26T07:30:47.000000Z/stations/inventory.xml +0 -0
- {specmod-0.2.0 → specmod-0.2.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/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.1}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ10.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
|
@@ -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'
|
|
@@ -1,6 +1,26 @@
|
|
|
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.1](https://github.com/sgjholt/SpecMod/compare/v0.2.0...v0.2.1) (2026-08-23)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Documentation
|
|
16
|
+
|
|
17
|
+
* add the Zenodo DOI to the README and the citation metadata ([8a89884](https://github.com/sgjholt/SpecMod/commit/8a89884f654b14bf5eb9ed8a32d10dc22d5e5fb4))
|
|
18
|
+
* PyPI and docs badges, and an install section for people who are not us ([d444397](https://github.com/sgjholt/SpecMod/commit/d44439762214b93fd8eef3f64745570b3b8be2b0))
|
|
19
|
+
* repoint the 0.2.0 changelog link, which 404s ([f1bbe31](https://github.com/sgjholt/SpecMod/commit/f1bbe3143ca3ca6dd58f584546e716d2170a790a))
|
|
20
|
+
* say where the code behind the publication lives ([ae7e906](https://github.com/sgjholt/SpecMod/commit/ae7e906209a87844cf2106a826be5111a6ef2036))
|
|
21
|
+
* turn the roadmap's stages into milestones against versions ([b933e69](https://github.com/sgjholt/SpecMod/commit/b933e69d219a54e4a7db894797a507a3bb24e31c))
|
|
22
|
+
|
|
23
|
+
## [0.2.0](https://github.com/sgjholt/SpecMod/compare/master...v0.2.0) (2026-08-23)
|
|
4
24
|
|
|
5
25
|
|
|
6
26
|
### ⚠ 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.1
|
|
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
|
|
@@ -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
|
|
@@ -67,8 +67,8 @@ print(fits.table[["id", "llpsp", "fc", "ts"]])
|
|
|
67
67
|
settings that have to be turned on once.
|
|
68
68
|
|
|
69
69
|
[Roadmap](roadmap.md)
|
|
70
|
-
: What
|
|
71
|
-
dates.
|
|
70
|
+
: What has shipped and in which version, what is being worked on, and what 1.0
|
|
71
|
+
will mean. Milestones, not dates.
|
|
72
72
|
|
|
73
73
|
## Working on SpecMod
|
|
74
74
|
|
|
@@ -27,19 +27,52 @@ bump.
|
|
|
27
27
|
|
|
28
28
|
## One-time setup
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Six things, none of which can be done from a commit. Until they are done the
|
|
31
31
|
release workflow is inert rather than wrong — it opens a release PR and stops.
|
|
32
32
|
|
|
33
|
-
1. **
|
|
34
|
-
|
|
35
|
-
requests*. Without it release-please fails with `GitHub Actions is not
|
|
36
|
-
permitted to create or approve pull requests`.
|
|
37
|
-
|
|
38
|
-
2. **Create the `pypi` environment.** Settings → Environments → New
|
|
39
|
-
environment → `pypi`. Add required reviewers here if you want a second
|
|
40
|
-
human gate on the upload itself.
|
|
33
|
+
1. **Mint `RELEASE_PLEASE_TOKEN_SPECMOD`.** Settings → Developer settings →
|
|
34
|
+
Personal access tokens → Fine-grained tokens → *Generate new token*.
|
|
41
35
|
|
|
42
|
-
|
|
36
|
+
| Field | Value |
|
|
37
|
+
|---|---|
|
|
38
|
+
| Repository access | Only select repositories → `SpecMod` |
|
|
39
|
+
| Contents | Read and write |
|
|
40
|
+
| Pull requests | Read and write |
|
|
41
|
+
| Expiration | up to 366 days — see the renewal note below |
|
|
42
|
+
|
|
43
|
+
Then Settings → Secrets and variables → Actions → *New repository secret*,
|
|
44
|
+
named exactly `RELEASE_PLEASE_TOKEN_SPECMOD`.
|
|
45
|
+
|
|
46
|
+
This is what makes the release PR run CI. Without it the PR is opened by
|
|
47
|
+
`GITHUB_TOKEN`, which starts no workflow runs at all, so the three required
|
|
48
|
+
checks never report and the PR is blocked with nothing to fix. The token
|
|
49
|
+
never touches PyPI — the upload authenticates by OIDC — so this does not
|
|
50
|
+
reintroduce a publishing secret.
|
|
51
|
+
|
|
52
|
+
**It expires.** When it does, the symptom is the old one returning: a
|
|
53
|
+
release PR with no checks on it. Renew the token and update the secret;
|
|
54
|
+
nothing in the repository changes. A GitHub App token via
|
|
55
|
+
`actions/create-github-app-token` avoids the expiry entirely and is the
|
|
56
|
+
better answer if this becomes annoying.
|
|
57
|
+
|
|
58
|
+
2. **Let Actions open pull requests.** Settings → Actions → General →
|
|
59
|
+
Workflow permissions → tick *Allow GitHub Actions to create and approve pull
|
|
60
|
+
requests*. Only needed as a fallback — with `RELEASE_PLEASE_TOKEN_SPECMOD`
|
|
61
|
+
set, the PR is opened by a user, not by Actions — but leave it on so the
|
|
62
|
+
workflow still works if the token lapses.
|
|
63
|
+
|
|
64
|
+
3. **Create the `pypi` environment.** Settings → Environments → New
|
|
65
|
+
environment → `pypi`.
|
|
66
|
+
|
|
67
|
+
Required reviewers here are optional, and worth thinking about before
|
|
68
|
+
adding: they hold the `publish` job at `waiting` until a human approves the
|
|
69
|
+
deployment, and **that approval cannot be given from the GitHub mobile
|
|
70
|
+
app** — the button exists only on the web UI and the REST API. Merging the
|
|
71
|
+
release PR is already a deliberate human act, and
|
|
72
|
+
`tools/check_built_version.py` is what actually prevents a wrong version
|
|
73
|
+
reaching PyPI, so the reviewer gate buys less than it looks like it does.
|
|
74
|
+
|
|
75
|
+
4. **Register the trusted publisher on PyPI.** On the project page (or, for
|
|
43
76
|
the first ever upload, under *Publishing* → *Add a new pending publisher*):
|
|
44
77
|
|
|
45
78
|
| Field | Value |
|
|
@@ -53,12 +86,12 @@ release workflow is inert rather than wrong — it opens a release PR and stops.
|
|
|
53
86
|
that actually runs. If the workflow is ever renamed, this has to be changed
|
|
54
87
|
in the same sitting or the upload fails authentication.
|
|
55
88
|
|
|
56
|
-
|
|
89
|
+
5. **Turn on the Zenodo webhook.** Log into Zenodo with GitHub, find `SpecMod`
|
|
57
90
|
in the repository list, and flip the switch. It takes effect for releases
|
|
58
91
|
made *after* it is on, so do it before the first release rather than after.
|
|
59
92
|
`CITATION.cff` supplies the metadata.
|
|
60
93
|
|
|
61
|
-
|
|
94
|
+
6. **Require the checks on `main`.** Branch protection → *Require status
|
|
62
95
|
checks to pass* → add exactly three: **`ci`**, **`docs`**, **`build`**.
|
|
63
96
|
|
|
64
97
|
Those are job names, not workflow names, and only these three are stable:
|
|
@@ -68,10 +101,12 @@ release workflow is inert rather than wrong — it opens a release PR and stops.
|
|
|
68
101
|
instead matches nothing, and a required check that never reports blocks
|
|
69
102
|
every merge.
|
|
70
103
|
|
|
71
|
-
The release pull request
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
104
|
+
The release pull request goes through them like any other — but only
|
|
105
|
+
because of step 1. This page previously said GitHub *holds* the runs on a
|
|
106
|
+
`github-actions[bot]` pull request until a maintainer approves them, and
|
|
107
|
+
that is not what happens: no runs are created, there is nothing to approve,
|
|
108
|
+
and the PR sits blocked with an empty check list.
|
|
109
|
+
`RELEASE_PLEASE_TOKEN_SPECMOD` is what makes this paragraph true.
|
|
75
110
|
|
|
76
111
|
## What a version number means while this is 0.x
|
|
77
112
|
|
|
@@ -108,13 +143,20 @@ To skip a release, do not merge the PR. It stays open and keeps accruing.
|
|
|
108
143
|
## Things that are the way they are for a reason
|
|
109
144
|
|
|
110
145
|
**The publish job is in `release.yml`, not a separate `publish.yml`.** The
|
|
111
|
-
obvious design — a workflow keyed on `release: published` —
|
|
112
|
-
release-please
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
146
|
+
obvious design — a workflow keyed on `release: published` — could not fire at
|
|
147
|
+
all when release-please ran on the default `GITHUB_TOKEN`, because "events
|
|
148
|
+
triggered by the `GITHUB_TOKEN` will not create a new workflow run". So the
|
|
149
|
+
publish job gates on release-please's own `release_created` output instead.
|
|
150
|
+
|
|
151
|
+
`RELEASE_PLEASE_TOKEN_SPECMOD` removes that constraint — a release created by
|
|
152
|
+
a PAT *does* start workflow runs — so a separate `publish.yml` would now work.
|
|
153
|
+
It is still not worth splitting: one workflow means one `concurrency` group, one
|
|
154
|
+
place to read, and no dependency on the ordering of two runs that would race
|
|
155
|
+
whenever two merges land together. The `release_created` gate is also exact,
|
|
156
|
+
where an event key would fire on any release including one made by hand.
|
|
157
|
+
|
|
158
|
+
Zenodo was never affected either way: it listens to the release *webhook*,
|
|
159
|
+
which is not subject to the token restriction.
|
|
118
160
|
|
|
119
161
|
**`include-component-in-tag` is `false`.** Left on, the tag is
|
|
120
162
|
`specmod-v0.2.0`, which `pyproject.toml`'s `--match v[0-9]*` does not describe
|
|
@@ -165,3 +207,18 @@ If the `publish` job fails after the release exists — a transient PyPI error,
|
|
|
165
207
|
say — re-run that job from the Actions UI. Do not re-run `release-please`
|
|
166
208
|
expecting a second attempt: `release_created` is only true on the run that
|
|
167
209
|
created the release.
|
|
210
|
+
|
|
211
|
+
## When the release PR has no checks on it
|
|
212
|
+
|
|
213
|
+
Not a red check — *no checks at all*, an empty list, and the PR blocked
|
|
214
|
+
because the three required ones never reported. This means release-please fell
|
|
215
|
+
back to `GITHUB_TOKEN`: either `RELEASE_PLEASE_TOKEN_SPECMOD` is unset, or it
|
|
216
|
+
expired, or its repository access no longer covers `SpecMod`. Renew it
|
|
217
|
+
(one-time setup, step 1); nothing in the repository needs changing.
|
|
218
|
+
|
|
219
|
+
To unblock the release PR that is already open, without waiting for a new
|
|
220
|
+
commit: **close it and immediately reopen it.** That re-fires
|
|
221
|
+
`pull_request.reopened` from your account rather than from the token, and the
|
|
222
|
+
checks run. It is the same trick that got `v0.2.0` out, and it is safe — the
|
|
223
|
+
`autorelease: pending` label survives, so release-please still recognises the
|
|
224
|
+
merge as a release, and no history is touched.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
SpecMod is being rebuilt in stages, each one independently usable. This page
|
|
4
|
+
says what has shipped, in which version, what is being worked on, and what 1.0
|
|
5
|
+
will mean.
|
|
6
|
+
|
|
7
|
+
**No dates.** The order is by dependency, not by calendar, and what comes after
|
|
8
|
+
the current milestone can still change. Shipped work names the version that
|
|
9
|
+
carries it, so it can be installed and checked rather than taken on trust;
|
|
10
|
+
unreleased work says so plainly.
|
|
11
|
+
[`REFACTOR_PLAN.md`](https://github.com/sgjholt/SpecMod/blob/main/docs/REFACTOR_PLAN.md)
|
|
12
|
+
is the working document behind this one and carries the reasoning, the
|
|
13
|
+
measurements and the open questions.
|
|
14
|
+
|
|
15
|
+
## Where it is now
|
|
16
|
+
|
|
17
|
+
**v0.2.0**, the first release of the rebuilt package —
|
|
18
|
+
[on PyPI](https://pypi.org/p/specmod), with a Zenodo DOI and its own
|
|
19
|
+
[documentation version](https://specmod.readthedocs.io/en/stable/). Install it
|
|
20
|
+
with `pip install specmod`.
|
|
21
|
+
|
|
22
|
+
Still alpha, still pre-1.0: names and signatures move between `0.x` releases
|
|
23
|
+
without a deprecation cycle. Everything below marked shipped is released,
|
|
24
|
+
tested against golden references, and usable — but pin an exact version for
|
|
25
|
+
anything you intend to publish. See
|
|
26
|
+
[Releasing the software](releasing.md) for what a version number means here.
|
|
27
|
+
|
|
28
|
+
## Shipped in v0.2.0
|
|
29
|
+
|
|
30
|
+
The version before this one, `0.1.1`, is the pre-refactor code that produced
|
|
31
|
+
the published Magna results. It is preserved unchanged on the
|
|
32
|
+
[`master`](https://github.com/sgjholt/SpecMod/tree/master) branch, which is
|
|
33
|
+
protected and frozen — it was never tagged or published to PyPI, so that
|
|
34
|
+
branch is the only reference to it. Everything below is the delta between it
|
|
35
|
+
and v0.2.0, which is why the first changelog is enormous and correctly so.
|
|
36
|
+
|
|
37
|
+
### An installable package
|
|
38
|
+
|
|
39
|
+
A real `pyproject.toml`, `src/` layout, snake_case modules, linting, type
|
|
40
|
+
checking and a test suite on CI. Before this, the package could not be
|
|
41
|
+
installed or imported without editing paths by hand.
|
|
42
|
+
|
|
43
|
+
### Configuration without globals
|
|
44
|
+
|
|
45
|
+
Settings live in a `config/` package with semantic sections and layered
|
|
46
|
+
overrides, instead of module-level constants read at import time. Every output
|
|
47
|
+
records the configuration that produced it, so a locally-overridden run is
|
|
48
|
+
reproducible from its own outputs.
|
|
49
|
+
|
|
50
|
+
### Publishing: docs, PyPI, DOI
|
|
51
|
+
|
|
52
|
+
This site, built from the repository on every merge; automated changelog and
|
|
53
|
+
version derivation from tags; PyPI upload through Trusted Publishing; a Zenodo
|
|
54
|
+
DOI per release. Deliberately built early, while the package was small enough
|
|
55
|
+
that debugging the pipeline was cheap — and v0.2.0 is the release that proved
|
|
56
|
+
every leg of it end to end.
|
|
57
|
+
|
|
58
|
+
A fresh clone still needs the one-time repository settings listed in
|
|
59
|
+
[Releasing the software](releasing.md); they are account and repository state,
|
|
60
|
+
not something a commit can carry.
|
|
61
|
+
|
|
62
|
+
### The transform layer
|
|
63
|
+
|
|
64
|
+
One `SpectralEstimator` protocol with interchangeable implementations —
|
|
65
|
+
`FFTEstimator`, `WelchEstimator`, `MultitaperEstimator` and Prieto's — plus
|
|
66
|
+
Konno–Ohmachi smoothing and log-binning as separate, composable steps. The
|
|
67
|
+
`mtspec` Fortran dependency, which no longer builds on current toolchains, is
|
|
68
|
+
demoted to an optional legacy backend rather than being the only path.
|
|
69
|
+
|
|
70
|
+
What each estimator does to real data is measured in
|
|
71
|
+
[Choosing a transform](choosing-a-transform.md); the differences are large
|
|
72
|
+
enough to matter to a magnitude.
|
|
73
|
+
|
|
74
|
+
### Wavelets
|
|
75
|
+
|
|
76
|
+
A continuous wavelet transform alongside the Fourier estimators:
|
|
77
|
+
`CWTEstimator`, a `Scalogram` that tracks its cone of influence, quality
|
|
78
|
+
checks over it, and time-averaging back to a spectrum with ground-motion units
|
|
79
|
+
preserved.
|
|
80
|
+
|
|
81
|
+
### Typed, portable persistence
|
|
82
|
+
|
|
83
|
+
HDF5 for arrays and Parquet for tables, replacing pickle everywhere — nothing
|
|
84
|
+
in the package can write a pickle any more, so a saved result is readable
|
|
85
|
+
without the code that wrote it and cannot execute anything on load.
|
|
86
|
+
|
|
87
|
+
### A stable import surface
|
|
88
|
+
|
|
89
|
+
`specmod.api` — a path-free, deterministic, non-mutating import surface with
|
|
90
|
+
typed errors, for downstream packages that need something narrower than the
|
|
91
|
+
whole package and less volatile than its internals.
|
|
92
|
+
|
|
93
|
+
## In progress — not yet released
|
|
94
|
+
|
|
95
|
+
### Finishing the decomposition
|
|
96
|
+
|
|
97
|
+
Breaking the remaining large modules into packages with narrow
|
|
98
|
+
responsibilities. The spectral core, the fitting layer and the pick readers
|
|
99
|
+
are already packages, and the type-checking backlog is empty.
|
|
100
|
+
|
|
101
|
+
What is left: `io.py` and `plotting.py` are still single modules, and the
|
|
102
|
+
operations that mutate in place need to return new objects instead. Neither is
|
|
103
|
+
large — the split is about responsibilities, not line count.
|
|
104
|
+
|
|
105
|
+
## Planned
|
|
106
|
+
|
|
107
|
+
### 1.0 — the API stops moving
|
|
108
|
+
|
|
109
|
+
The theory page that states the normalisation and units conventions
|
|
110
|
+
explicitly, the tutorial rebuilt as an executed notebook so it cannot rot
|
|
111
|
+
silently, and a "what changed since 0.1" guide for anyone upgrading. Then the
|
|
112
|
+
1.0 release, which is the promise that names and signatures stop moving
|
|
113
|
+
without a deprecation cycle.
|
|
114
|
+
|
|
115
|
+
That promise is the whole content of the number, which is why it has to be a
|
|
116
|
+
decision rather than something a breaking commit does on its way past. Until
|
|
117
|
+
it is made, breaking changes bump the minor.
|
|
118
|
+
|
|
119
|
+
## After 1.0
|
|
120
|
+
|
|
121
|
+
Designed but deliberately not on the path to 1.0, because each is blocked on
|
|
122
|
+
an input rather than on effort — mostly a real file from a real tool, which a
|
|
123
|
+
guess written from documentation cannot substitute for:
|
|
124
|
+
|
|
125
|
+
- **Presets for picker output** (PhaseNet, EQTransformer, SeisBench), so those
|
|
126
|
+
users write no column mapping. The configurable reader already exists; a
|
|
127
|
+
preset is a mapping and a test against one real file.
|
|
128
|
+
- **Confirming two more pick formats** (NonLinLoc `.hyp`, IMS/GSE bulletins)
|
|
129
|
+
that cannot be round-tripped through ObsPy and so are listed as unconfirmed
|
|
130
|
+
rather than claimed.
|
|
131
|
+
- **SeisComP picks**, which ObsPy's SCML reader currently discards. A test
|
|
132
|
+
fails when that starts working upstream.
|
|
133
|
+
- **Recording pick-resolution policy in the configuration**, alongside the
|
|
134
|
+
provenance stamp.
|
|
135
|
+
- **A fuller `acquire --verify`** that re-fetches and diffs against the
|
|
136
|
+
manifest, rather than only detecting local tampering.
|
|
137
|
+
|
|
138
|
+
## How this page works
|
|
139
|
+
|
|
140
|
+
Each shipped entry names the version that carries it, so a reader can install
|
|
141
|
+
that version and check the claim. Work that is merged but unreleased sits under
|
|
142
|
+
*In progress* and gets its version when a release goes out — merged is not
|
|
143
|
+
shipped, and this page does not blur the two.
|
|
144
|
+
|
|
145
|
+
Before v0.2.0 this was a list of stages, because there was no released version
|
|
146
|
+
to point at and "done" could only mean merged. The full changelog for every
|
|
147
|
+
release is in
|
|
148
|
+
[`CHANGELOG.md`](https://github.com/sgjholt/SpecMod/blob/main/CHANGELOG.md).
|