specmod 0.3.0__tar.gz → 0.5.0__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.5.0/.release-please-manifest.json +3 -0
- {specmod-0.3.0 → specmod-0.5.0}/CHANGELOG.md +61 -0
- {specmod-0.3.0 → specmod-0.5.0}/PKG-INFO +1 -1
- {specmod-0.3.0 → specmod-0.5.0}/datasets/magna_2020.toml +6 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/REFACTOR_PLAN.md +108 -20
- {specmod-0.3.0 → specmod-0.5.0}/docs/choosing-a-transform.md +84 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/development.md +2 -1
- {specmod-0.3.0 → specmod-0.5.0}/docs/releasing-data.md +47 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/roadmap.md +89 -8
- {specmod-0.3.0 → specmod-0.5.0}/docs/upgrading.md +42 -3
- specmod-0.5.0/src/specmod/acquire.py +643 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/config/sections.py +32 -4
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/core/collection.py +103 -17
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/pipeline.py +41 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/smoothing/__init__.py +14 -2
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/smoothing/base.py +16 -1
- specmod-0.5.0/src/specmod/smoothing/log_window.py +215 -0
- specmod-0.5.0/src/specmod/smoothing/savitzky_golay.py +127 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/golden/motion_reference.json +140 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/golden/pipeline_reference.json +140 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/golden/window_reference.json +140 -0
- specmod-0.5.0/tests/test_acquire.py +865 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_config.py +99 -1
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_golden_reference.py +70 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_pipeline.py +123 -1
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_release_config.py +88 -0
- specmod-0.5.0/tests/test_smoothing.py +431 -0
- specmod-0.5.0/tests/test_tools_track_the_api.py +125 -0
- {specmod-0.3.0 → specmod-0.5.0}/tools/make_golden.py +34 -4
- {specmod-0.3.0 → specmod-0.5.0}/tools/measure_docs.py +106 -6
- specmod-0.3.0/.release-please-manifest.json +0 -3
- specmod-0.3.0/src/specmod/acquire.py +0 -358
- specmod-0.3.0/tests/test_acquire.py +0 -375
- specmod-0.3.0/tests/test_smoothing.py +0 -226
- {specmod-0.3.0 → specmod-0.5.0}/.git-blame-ignore-revs +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/.github/workflows/build.yml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/.github/workflows/docs.yml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/.github/workflows/release.yml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/.github/workflows/test.yml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/.gitignore +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/.pre-commit-config.yaml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/.readthedocs.yaml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/AGENTS.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/CITATION.cff +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/CLAUDE.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/CONTRIBUTING.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/LICENSE +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/README.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/datasets/pnr_2019.toml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_builders/_notebook.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_builders/choosing_a_transform.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_builders/specmod_tutorial.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/academic.css +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/OFL-fira-code.txt +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/OFL-merriweather.txt +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/OFL-open-sans.txt +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/README.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/fira-code-400-greek.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/fira-code-400-latin-ext.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/fira-code-400-latin.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/merriweather-latin-ext.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/merriweather-latin.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/open-sans-greek.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/open-sans-latin-ext.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts/open-sans-latin.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/fonts.css +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/LICENSE +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/README.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/katex/katex.min.css +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/specmod-logo-academic-dark-mark.svg +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/specmod-logo-academic-dark.svg +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/specmod-logo-academic-mark.svg +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/_static/specmod-logo-academic.svg +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/api.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/branding.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/conf.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/contributing.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/documentation.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/getting-started.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/guides.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/index.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/notebooks/choosing-a-transform.ipynb +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/notes/api-audit.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/notes/window-position.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/pick-formats.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/processing.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/docs/releasing.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/pyproject.toml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/release-please-config.json +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/requirements.txt +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/_vendor/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/_vendor/qiinv.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/api.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/cli.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/config/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/config/layers.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/config/provenance.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/config/serialize.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/core/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/core/bandwidth.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/core/noise.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/core/scalogram.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/core/spectrum.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/core/units.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/datasets.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/distance.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/exceptions.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/fitting/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/fitting/base.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/fitting/event.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/fitting/guess.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/fitting/spectrum.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/io/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/io/backend.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/io/hdf5.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/io/layout.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/magnitude.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/picks/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/picks/base.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/picks/delimited.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/picks/events.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/picks/resolution.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/picks/snuffler.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/plotting/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/plotting/grid.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/plotting/pair.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/plotting/style.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/preprocess.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/smoothing/konno_ohmachi.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/smoothing/log_bins.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/sources/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/sources/attenuation.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/sources/composite.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/sources/motion.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/sources/source.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/spreading.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/staged.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/tables.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/transforms/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/transforms/base.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/transforms/cwt.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/transforms/fft.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/transforms/multitaper.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/transforms/prieto.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/transforms/quadratic.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/src/specmod/utils.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/README.md +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/lmfit/__init__.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/lmfit/model.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/lmfit/parameter.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/__init__.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/clients/__init__.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/clients/fdsn/__init__.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/core/__init__.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/core/event.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/core/inventory.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/core/stream.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/core/trace.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/core/utcdatetime.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/core/util/__init__.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/core/util/base.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/geodetics/__init__.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/signal/__init__.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/stubs/obspy/signal/konnoohmachismoothing.pyi +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/studies/magna_2020_paper.toml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/__init__.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/conftest.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_ambient_state.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_api_surface.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_collection.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_cwt.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_datasets.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_docs_are_current.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_end_to_end.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_fitting_defaults.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_import.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_io_and_plotting.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_legacy_fixes.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_magnitude.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_make_golden.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_pick_plugins.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_pick_readers.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_picks.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_pipeline_smoke.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_preprocess.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_prieto.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_quadratic.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_sources.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_spectral_wiring.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_staged.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_stubs.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_transforms.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_tutorial.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_typing_backlog.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_utils.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tests/test_versioning.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tools/check_built_version.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tools/check_floors.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tools/make_logo.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tools/vendor_fonts.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tools/vendor_katex.py +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/picks/2019-08-26T07:30:47.000000Z.picks +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/picks/2019-08-26T07:30:47.000000Z.xml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/stations/inventory.xml +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L001..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L001..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L001..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L002..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L002..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L002..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L006..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L006..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L006..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L007..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L007..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L007..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L008..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L008..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L008..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L009..HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L009..HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.L009..HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.LD06..HH1_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.LD06..HH2_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/LV.LD06..HH3_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ01.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ01.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ01.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ02.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ03.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ03.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ03.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ04.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ04.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ04.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ05.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ05.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ05.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ06.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ06.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ06.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ07.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ07.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ07.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ09.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ09.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ09.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ10.00.HHE_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ10.00.HHN_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/data/events/2019-08-26T07:30:47.000000Z/waveforms/UR.AQ10.00.HHZ_2019-08-26T07:30:47.000000Z +0 -0
- {specmod-0.3.0 → specmod-0.5.0}/tutorial/specmod-tutorial.ipynb +0 -0
|
@@ -9,6 +9,67 @@ release could have this problem — every later one has a real predecessor tag
|
|
|
9
9
|
so leave subsequent headings as generated. release-please only prepends to this
|
|
10
10
|
file, so this edit survives. -->
|
|
11
11
|
|
|
12
|
+
## [0.5.0](https://github.com/sgjholt/SpecMod/compare/v0.4.0...v0.5.0) (2026-09-19)
|
|
13
|
+
|
|
14
|
+
<!-- The `acquire` entries below are edited by hand, and are the second entry
|
|
15
|
+
in this file that is. The work shipped in 2af57e8, the squash merge of #45,
|
|
16
|
+
whose subject is not a Conventional Commit — release-please could not parse it
|
|
17
|
+
("unexpected token ' ' at 1:5") and generated nothing for it. What it did
|
|
18
|
+
generate was the later commit that restored the record, which is documentation
|
|
19
|
+
describing the change rather than the change. These name the change and point
|
|
20
|
+
at the commit that carries it. release-please only prepends to this file, so
|
|
21
|
+
the edit survives. -->
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* **acquire:** rank co-sited instruments with `channel_priorities` and
|
|
26
|
+
`location_priorities`, so a station carrying a broadband and an
|
|
27
|
+
accelerometer contributes one record rather than two
|
|
28
|
+
([2af57e8](https://github.com/sgjholt/SpecMod/commit/2af57e8e958d474a25e34b9065f9e54d1a1a42fa))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### Bug Fixes
|
|
32
|
+
|
|
33
|
+
* **acquire:** ask for waveforms by name, so `max_radius_km` applies to the
|
|
34
|
+
download and not only to the station query — FDSN dataselect takes no
|
|
35
|
+
geographic parameters, so a wildcard request was unbounded
|
|
36
|
+
([2af57e8](https://github.com/sgjholt/SpecMod/commit/2af57e8e958d474a25e34b9065f9e54d1a1a42fa))
|
|
37
|
+
* **acquire:** cut the radius against true WGS84 distance rather than a fixed
|
|
38
|
+
111.195 km per degree, which moved the boundary by up to half a percent with
|
|
39
|
+
latitude; `min_radius_km` now applies on its own, and a non-positive radius
|
|
40
|
+
or an inverted annulus is refused
|
|
41
|
+
([2af57e8](https://github.com/sgjholt/SpecMod/commit/2af57e8e958d474a25e34b9065f9e54d1a1a42fa))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
### Documentation
|
|
45
|
+
|
|
46
|
+
* **acquire:** upgrading notes for the station selection, and for the
|
|
47
|
+
`[smoothing] method` behaviour change in 0.4.0 ([b460d19](https://github.com/sgjholt/SpecMod/commit/b460d1922c21822a81b6aeb06aa6d5f7193d92e1))
|
|
48
|
+
* **roadmap:** file v0.4.0 as shipped, and the acquire work as merged ([e113abb](https://github.com/sgjholt/SpecMod/commit/e113abb97d80737a2c4a791a6543d945bdb7ba9c))
|
|
49
|
+
|
|
50
|
+
## [0.4.0](https://github.com/sgjholt/SpecMod/compare/v0.3.0...v0.4.0) (2026-09-16)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Features
|
|
54
|
+
|
|
55
|
+
* **smoothing:** wire [smoothing] method up, and add three more methods ([fff3ab1](https://github.com/sgjholt/SpecMod/commit/fff3ab1ef01a7f4d942fd776821d0418a0642a55))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
### Bug Fixes
|
|
59
|
+
|
|
60
|
+
* **config:** refuse a [smoothing] method the pipeline does not apply ([1f18c68](https://github.com/sgjholt/SpecMod/commit/1f18c68a71794c2b1612a7cf0feedcfef39b625b))
|
|
61
|
+
* **test:** compare the roadmap against the published minor, not the proposed one ([1e34b4e](https://github.com/sgjholt/SpecMod/commit/1e34b4e5ab2bdef5d65f6fc0d620a42b9c3891eb))
|
|
62
|
+
* **tools:** call the preprocess API that 0.3.0 left behind ([8501c8e](https://github.com/sgjholt/SpecMod/commit/8501c8ed618e5d652b9eeffc36893115a58fd7d5))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### Documentation
|
|
66
|
+
|
|
67
|
+
* keep the reasoning out of the docstrings, in comments where it belongs ([2684ec9](https://github.com/sgjholt/SpecMod/commit/2684ec923c8dcf59e882b2d11e9dc11ccbcf3766))
|
|
68
|
+
* say what tagging the frozen commit does and does not trigger ([2273219](https://github.com/sgjholt/SpecMod/commit/2273219e2a78ac1c1562118c2a1b3bce4df597dd))
|
|
69
|
+
* state what the smoothers are, not how they were arrived at ([4c97491](https://github.com/sgjholt/SpecMod/commit/4c97491d50aba5a1468304072ab3c6ed2904f2e0))
|
|
70
|
+
* the 0.3.0 work shipped a week ago, so stop calling it unreleased ([e2aaced](https://github.com/sgjholt/SpecMod/commit/e2aaced546a247b2c5967f01586c19928bcfe297))
|
|
71
|
+
* v0.1.1 is master's tip, which is what freezing it was for ([db50972](https://github.com/sgjholt/SpecMod/commit/db509729f3b7877a20b5691dddec8a6e139fb466))
|
|
72
|
+
|
|
12
73
|
## [0.3.0](https://github.com/sgjholt/SpecMod/compare/v0.2.3...v0.3.0) (2026-09-06)
|
|
13
74
|
|
|
14
75
|
|
|
@@ -35,6 +35,12 @@ location = "*"
|
|
|
35
35
|
# fetched too: the workflow rotates horizontals to R/T, and rotation is not a
|
|
36
36
|
# reason to discard Z from the archive.
|
|
37
37
|
channel = "HH*,BH*,HN*,EN*"
|
|
38
|
+
# Deliberately unranked. `channel_priorities` would keep one instrument per
|
|
39
|
+
# station — the right default for a regional dataset, and what silences the
|
|
40
|
+
# co-sited warning this fetch prints — but here the near-source broadbands are
|
|
41
|
+
# the records most likely to clip, and the accelerometer beside them is the
|
|
42
|
+
# reason the paper covers that distance range at all. Both are kept and the
|
|
43
|
+
# choice is made at processing time.
|
|
38
44
|
max_radius_km = 400.0
|
|
39
45
|
|
|
40
46
|
[window]
|
|
@@ -1087,7 +1087,7 @@ and there are presumably more in your working directories.
|
|
|
1087
1087
|
Two ways out, and the first is much better:
|
|
1088
1088
|
|
|
1089
1089
|
1. **Convert in the old environment.** Phase 0 is already building a Docker image
|
|
1090
|
-
where the 0.1.
|
|
1090
|
+
where the 0.1.1 code runs (§6.7). Add a small
|
|
1091
1091
|
`scripts/convert_legacy_spec.py` to it that loads `.spec` files with the old
|
|
1092
1092
|
classes present and writes the new HDF5 format. This is a one-shot migration
|
|
1093
1093
|
with no lasting cost to the codebase.
|
|
@@ -2434,6 +2434,15 @@ Two design constraints worth fixing now:
|
|
|
2434
2434
|
reimplementation of `MassDownloader`, which is built for large restricted-data
|
|
2435
2435
|
campaigns and is more machinery than this needs.
|
|
2436
2436
|
|
|
2437
|
+
What that choice costs, recorded as it is paid: `MassDownloader` supplies
|
|
2438
|
+
`CircularDomain`, `sanitize=True` and `channel_priorities` for free, and each
|
|
2439
|
+
has had to be built by hand here after its absence showed up in a live fetch.
|
|
2440
|
+
The radius reaching only the station query, an archive holding waveforms with
|
|
2441
|
+
no metadata beside them, and 507 channels for 88 stations were all one
|
|
2442
|
+
property of `Restrictions` each. The wrapper stays thin, but "ObsPy already
|
|
2443
|
+
does it" is an argument for reading what ObsPy does before writing the thin
|
|
2444
|
+
version.
|
|
2445
|
+
|
|
2437
2446
|
TOML is suggested for the config, read by stdlib `tomllib` on 3.11+ and
|
|
2438
2447
|
consistent with `pyproject.toml`. YAML is equally fine if it reads better for
|
|
2439
2448
|
nested station rules; it costs one small dependency.
|
|
@@ -2742,13 +2751,30 @@ Two further problems with reproducing the published run from this repository:
|
|
|
2742
2751
|
manuscript filename (`...SRL3`) suggests a third revision, which would also
|
|
2743
2752
|
explain a 2021 code state behind a 2020 access date.
|
|
2744
2753
|
|
|
2745
|
-
|
|
2754
|
+
The evidence narrows it: **the candidate is `ba3f7ec` or later, not the
|
|
2746
2755
|
pre-November-2020 commits**, because the earlier code cannot perform the
|
|
2747
2756
|
workflow the paper describes. Only `09f57b9` (removed cython) changes
|
|
2748
2757
|
`specmod/` after that, so the realistic candidates are `ba3f7ec` and
|
|
2749
|
-
`453c77c`.
|
|
2750
|
-
|
|
2751
|
-
|
|
2758
|
+
`453c77c`.
|
|
2759
|
+
|
|
2760
|
+
**Answered: `453c77c`** — the tip of `master`, 2021-08-12. On the author's
|
|
2761
|
+
word, and it is why `master` was frozen at that commit rather than at any
|
|
2762
|
+
other: the branch *is* the v0.1.1 record (§6.7). Which of the two the
|
|
2763
|
+
evidence above prefers was never the question it looked like.
|
|
2764
|
+
|
|
2765
|
+
What that settles and what it does not: the code is identified, so §5.2.6
|
|
2766
|
+
step 2 can be run against a known commit. The dating oddity is unchanged —
|
|
2767
|
+
the manuscript's access date still precedes the commit it cites, which the
|
|
2768
|
+
third revision (`...SRL3`) explains without needing the code to have moved.
|
|
2769
|
+
It is recorded rather than resolved, because nothing in the repository can
|
|
2770
|
+
resolve it.
|
|
2771
|
+
|
|
2772
|
+
This is still the strongest possible argument for tagging that commit (§6.7)
|
|
2773
|
+
and for `hatch-vcs` (§6.4): a version that takes a page of archaeology to
|
|
2774
|
+
identify must never happen again. **No `v0.1.1` tag exists yet.** Creating
|
|
2775
|
+
one is safe — `453c77c` is an ancestor of `main`, and every later release
|
|
2776
|
+
tag outranks it for `hatch-vcs`, so nothing derives a version from it — but
|
|
2777
|
+
it is repository state, not something a commit here can carry.
|
|
2752
2778
|
2. **The full published pipeline is not in this repository.** The two-stage
|
|
2753
2779
|
inversion (fit Ω/`f_c`/`t*` free, then fix event `f_c` to the
|
|
2754
2780
|
inverse-hypocentral-distance-weighted mean of station `f_c` and refit) and the
|
|
@@ -3414,6 +3440,31 @@ been audited once is worth more than one that reads confidently throughout.
|
|
|
3414
3440
|
| "`commitlint`-enforced" again, in §6.4 | The §7 instance was corrected and this one was left standing, in the same document. §6.4 corrected. |
|
|
3415
3441
|
| `publish.yml` "GitHub Release published → PyPI" | It would never have run. release-please creates the release with the default `GITHUB_TOKEN`, and events triggered by that token do not start a workflow. The publish job moved into `release.yml`, gated on `release_created`. §6.5 corrected. |
|
|
3416
3442
|
|
|
3443
|
+
**A fourth of the same shape, found later** — the three above were corrected in
|
|
3444
|
+
the prose; this one was a live setting:
|
|
3445
|
+
|
|
3446
|
+
> `[smoothing] method` — "Name -> smoother, for resolving `SmoothingConfig.method`"
|
|
3447
|
+
|
|
3448
|
+
`SMOOTHERS` existed, `method` validated against its `Literal`, and **no code
|
|
3449
|
+
anywhere read it**. The comparison binned with `log_bin` unconditionally.
|
|
3450
|
+
Measured on the 28 PNR windows, `log_bins`, `konno_ohmachi` and `none` produced
|
|
3451
|
+
bit-identical output — `none` included, which reads as "leave my spectra
|
|
3452
|
+
unsmoothed" while every spectrum went on being binned exactly as before.
|
|
3453
|
+
|
|
3454
|
+
**Fixed rather than documented.** `SpectrumPair.compare` now takes a `smoother`,
|
|
3455
|
+
`[smoothing] method` resolves to one, and the registry gained `log_window`
|
|
3456
|
+
(constant-relative-bandwidth smoothing with a selectable window shape, and a
|
|
3457
|
+
median option) and `savitzky_golay` beside the two that were there.
|
|
3458
|
+
`tests/test_config.py::TestEverySmoothingMethodIsWiredUp` and
|
|
3459
|
+
`tests/test_pipeline.py::TestTheConfiguredSmootherReachesTheComparison` are the
|
|
3460
|
+
mechanism the comment claimed: each accepted value resolves, carries its
|
|
3461
|
+
section's parameters, and survives the whole path on real windows.
|
|
3462
|
+
|
|
3463
|
+
`log_bins` stays `core.collection.log_bin` rather than `smoothing.LogBinner` —
|
|
3464
|
+
the two differ in clamping and in what `n_bins` counts, and the difference is
|
|
3465
|
+
every committed golden number. The default path is unchanged, which the golden
|
|
3466
|
+
suite asserts and which is why this could land without moving a number.
|
|
3467
|
+
|
|
3417
3468
|
**A claim whose mechanism is absent but whose property holds — for a different
|
|
3418
3469
|
reason, which matters:**
|
|
3419
3470
|
|
|
@@ -3460,7 +3511,8 @@ of §5.2, and the two-stage fit API of §5.2.5.
|
|
|
3460
3511
|
**`master` is frozen; `main` is the trunk.** `main` was branched from `master` at
|
|
3461
3512
|
`453c77c` and is where all refactor work lands. `master` is never committed to
|
|
3462
3513
|
again — it becomes the permanent, named record of the pre-refactor code, doing
|
|
3463
|
-
the job a `v0.1.
|
|
3514
|
+
the job a `v0.1.1` tag would have done. Its tip, `453c77c`, **is** the v0.1.1
|
|
3515
|
+
the Magna paper cites (§5.2.5, §8).
|
|
3464
3516
|
|
|
3465
3517
|
**Every pull request must target `sgjholt/SpecMod`, never `uofuseismo/SpecMod`.**
|
|
3466
3518
|
This is not a matter of care — it is a GitHub default working against you.
|
|
@@ -3498,7 +3550,7 @@ Two consequences worth acting on:
|
|
|
3498
3550
|
- [ ] Settings → Actions → confirm workflows are enabled
|
|
3499
3551
|
- [ ] Settings → Branches → protect `master` (no pushes, no deletion) so the
|
|
3500
3552
|
frozen record stays frozen
|
|
3501
|
-
- [ ] `git tag -a v0.1.
|
|
3553
|
+
- [ ] `git tag -a v0.1.1 453c77c -m "the version the Magna paper cites" && git push origin v0.1.1`
|
|
3502
3554
|
|
|
3503
3555
|
**No Claude session URLs in commit messages, PR bodies, or any other published
|
|
3504
3556
|
artifact.** The repository is public and those links are private session state. A
|
|
@@ -3516,12 +3568,20 @@ needed and neither can be made from a git client:
|
|
|
3516
3568
|
convention rather than a guarantee — one absent-minded `git push origin
|
|
3517
3569
|
master` and the record is gone.
|
|
3518
3570
|
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3571
|
+
Also tag `453c77c` as `v0.1.1` — no longer optional now that §8 records it as
|
|
3572
|
+
the commit the paper cites. A branch is discoverable and a tag is immutable,
|
|
3573
|
+
and a citation should resolve to the immutable one.
|
|
3574
|
+
|
|
3575
|
+
Tagging it publishes nothing. No workflow triggers on tags; the PyPI upload is
|
|
3576
|
+
gated on release-please's `release_created`, which only a merged release PR on
|
|
3577
|
+
`main` can set; and `git describe` takes the nearest tag, which is a release
|
|
3578
|
+
far ahead of this one. **Do not create a GitHub Release from the tag**, which
|
|
3579
|
+
is the one action that would publish: Zenodo listens to the release webhook and
|
|
3580
|
+
would mint a DOI for the pre-refactor code. The commit has no `pyproject.toml`
|
|
3581
|
+
and is not packageable.
|
|
3522
3582
|
|
|
3523
3583
|
> Note on tooling limits: tag pushes are blocked in the automation environment
|
|
3524
|
-
> this plan was written in (HTTP 403 on `push origin v0.1.
|
|
3584
|
+
> this plan was written in (HTTP 403 on `push origin v0.1.1`, while branch
|
|
3525
3585
|
> pushes to the same remote succeed), which is why `main` exists as a branch
|
|
3526
3586
|
> rather than the state being pinned by a tag. **This does not affect the release
|
|
3527
3587
|
> automation in §6.4** — release-please creates tags from inside GitHub Actions
|
|
@@ -3531,10 +3591,10 @@ The two are complementary — the tag is immutable, the branch is discoverable.
|
|
|
3531
3591
|
|
|
3532
3592
|
Worth being precise about what any of this does and does not preserve: it
|
|
3533
3593
|
preserves the **code**, but the code is not **runnable** — `mtspec` no longer
|
|
3534
|
-
builds on any current toolchain (§2.1). Reproducing a 0.1.
|
|
3594
|
+
builds on any current toolchain (§2.1). Reproducing a 0.1.1 result needs three
|
|
3535
3595
|
things, which is what Phase 0 delivers:
|
|
3536
3596
|
|
|
3537
|
-
1. `master` (and
|
|
3597
|
+
1. `master` (and the `v0.1.1` tag on its tip) — the source.
|
|
3538
3598
|
2. A `Dockerfile` pinning `gfortran`, `python 3.9`, `numpy<2` — the environment
|
|
3539
3599
|
that can still build `mtspec`. Also the only place existing `.spec` pickles
|
|
3540
3600
|
can be read (§4.6).
|
|
@@ -3565,7 +3625,7 @@ Each phase ends green on CI and is independently mergeable.
|
|
|
3565
3625
|
|
|
3566
3626
|
| Phase | Work | Depends on | Rough size |
|
|
3567
3627
|
|---|---|---|---|
|
|
3568
|
-
| **0. Safety net** | Freeze `master`, default branch → `main`, optional `v0.1.
|
|
3628
|
+
| **0. Safety net** | Freeze `master`, default branch → `main`, optional `v0.1.1` tag (§6.7); reproducible legacy env (`Dockerfile`: gfortran + ObsPy 1.2.0 / SciPy 1.4.1 / NumPy 1.18 / pandas 1.0.0 (§5.2.6)); write `datasets/magna_2020.toml` and a first cut of `specmod.acquire`, publish the artifact as a `data-v1` release asset (§5.2); capture golden outputs for PNR **and** Magna; reproduce Table S2 / Figure 2 with 0.1.1 (§5.2.6 step 2); convert any `.spec` files (§4.6) | — | 1.5–2 days |
|
|
3569
3629
|
| **1. Make it installable** | `pyproject.toml` + hatch-vcs, `src/` layout, `__init__.py`; ruff config, one-shot `ruff format` + `.git-blame-ignore-revs`, module renames to snake_case; mypy skeleton; pre-commit; `test`/`build` CI; `.gitignore`, `CITATION.cff`; fix the three hard breakages (§1) and the four `F821` bugs ruff finds (§2.5); delete `Tests/Tutorial/`, strip notebook outputs, subset the inventory (§5.1) | 0 | 3–4 days |
|
|
3570
3630
|
| **2. De-globalise** | `config/` package per §4.8 — semantic groups, layer resolution, `config show`/`freeze`, provenance stamping; remove all module-level config reads (tracked by `PLW0603`); `Motion`/`AmplitudeKind` enums; `Spectrum` as a frozen dataclass with `duration`; mutable class attrs (`RUF012`); `isinstance` checks; `logging`. **Tag `v0.2.0`** | 1 | 3–4 days |
|
|
3571
3631
|
| **2b. Release plumbing** ✅ | ~~Sphinx skeleton + `pydata-sphinx-theme` + autodoc/napoleon/intersphinx~~ ✅; ~~`docs.yml` → a published site~~ ✅ — Read the Docs rather than GH Pages, for versions (§6.3); ~~release-please + PyPI Trusted Publishing~~ ✅ — one `release.yml`, not two workflows (§6.5); ~~Zenodo webhook~~ ✅ documented. Five repository settings have to be turned on by hand: `docs/releasing.md` lists them. The `ci/` mirror that staged workflow files for hand-copying is gone — it existed because an agent token could not push `.github/workflows/`, and that permission is now granted. Parallel with 2 | 1 | 1–2 days |
|
|
@@ -3658,20 +3718,48 @@ changes anything shipped.
|
|
|
3658
3718
|
### Still open
|
|
3659
3719
|
|
|
3660
3720
|
1. **Default estimator.** Multitaper (matching current behaviour) or FFT +
|
|
3661
|
-
Konno–Ohmachi (
|
|
3721
|
+
Konno–Ohmachi (more conventional in engineering seismology)? **No longer
|
|
3722
|
+
blocked** — §6.6's dead `[smoothing] method` is wired up, so the second
|
|
3723
|
+
option is selectable — and now measured, on the 28 PNR windows with each
|
|
3724
|
+
station fitted freely:
|
|
3725
|
+
|
|
3726
|
+
| Against the shipped multitaper + `log_bins` | Median ΔMw | Per-station range | `fc` ratio |
|
|
3727
|
+
|---|---|---|---|
|
|
3728
|
+
| `fft` + `log_bins` | −0.039 | −0.85 to +1.90 | 0.003 to 5.0 |
|
|
3729
|
+
| `fft` + `konno_ohmachi` | +0.027 | −0.52 to +0.51 | 0.038 to 3.2 |
|
|
3730
|
+
|
|
3731
|
+
**The smoothing is what makes the switch defensible, not the estimator.**
|
|
3732
|
+
FFT with the shipped binner moves a station by up to 1.9 magnitude units,
|
|
3733
|
+
because `log_bins` reduces the axis without reducing the variance — 151 log
|
|
3734
|
+
bins over a few hundred Fourier samples is roughly one sample per bin.
|
|
3735
|
+
Pairing it with a real smoother halves the worst excursion and pulls the
|
|
3736
|
+
`fc` range in by a third. The median station barely moves either way.
|
|
3737
|
+
|
|
3738
|
+
What this event cannot settle: the *event* corner is unconstrained under all
|
|
3739
|
+
three (stage-one spread 895% to 1042% of the event value), so the ensemble
|
|
3740
|
+
number is not evidence. Deciding on the ensemble needs an event where it is
|
|
3741
|
+
constrained.
|
|
3742
|
+
|
|
3743
|
+
Speed, measured rather than assumed and far too small to decide on: the
|
|
3744
|
+
transform is 0.209 s against 0.323 s for the 28 windows, and the smoothing
|
|
3745
|
+
adds 0.14 s (`log_bins`) to 0.83 s (`konno_ohmachi`) on top.
|
|
3746
|
+
|
|
3662
3747
|
2. **Python floor.** 3.11 is proposed. Any users stuck on 3.9/3.10?
|
|
3663
3748
|
3. **History rewrite.** Deleting the 9.9 MB catalog and stripping the notebook
|
|
3664
3749
|
(§5.1) shrinks the *working tree* but leaves both in history, so a fresh clone
|
|
3665
3750
|
still pulls ~15 MiB. Rewriting history with `git-filter-repo` would recover it
|
|
3666
3751
|
— but it rewrites every SHA, which moves what `master` and `main` currently
|
|
3667
|
-
point at and invalidates any `v0.1.
|
|
3752
|
+
point at and invalidates any `v0.1.1` tag. Given the end state is a ~1 MB repo
|
|
3668
3753
|
either way, **the recommendation is to leave history alone**: a one-time 15 MiB
|
|
3669
3754
|
clone is a much smaller cost than an unrecoverable pre-refactor record. Only
|
|
3670
3755
|
worth revisiting if the history genuinely becomes a burden.
|
|
3671
|
-
4.
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3756
|
+
4. ~~**Which commit is "v0.1.1"?**~~ **Resolved: `453c77c`**, the tip of
|
|
3757
|
+
`master`, 2021-08-12 — which is what freezing `master` at that commit was
|
|
3758
|
+
for (§6.7). The archaeology in §5.2.5 narrowed it to two candidates and
|
|
3759
|
+
could not choose between them; the answer did not come from the repository
|
|
3760
|
+
and was never going to. §5.2.6 step 2 now has a known commit to run. No
|
|
3761
|
+
`v0.1.1` tag exists yet, and creating one is repository state rather than
|
|
3762
|
+
something a commit can carry.
|
|
3675
3763
|
5. ~~**Was noise rotation on for the published run?**~~ **Assumed on.** Not
|
|
3676
3764
|
recalled, so `studies/magna_2020_paper.toml` starts from the shipped values —
|
|
3677
3765
|
`ROTATE_NOISE = true`, `ROT_METHOD = 2`, `ROT_PARS = {inc = 0.05, space =
|
|
@@ -582,6 +582,90 @@ narrow at low frequency, wide at high. It preserves the frequency axis, which is
|
|
|
582
582
|
what you want before fitting on the original grid. Bandwidth `b` is inverse:
|
|
583
583
|
smaller smooths harder; 40 is conventional.
|
|
584
584
|
|
|
585
|
+
**`LogWindow`** is the same idea with the window shape exposed: a fixed width in
|
|
586
|
+
octaves, and `boxcar`, `bartlett` (triangular), `hann`, `hamming`, `blackman` or
|
|
587
|
+
`gaussian` across it. Use it when you want the constant-relative-bandwidth
|
|
588
|
+
behaviour of Konno–Ohmachi and a say in how hard the taper is — or simply
|
|
589
|
+
because it is faster, being a sliding window rather than a full weight matrix.
|
|
590
|
+
|
|
591
|
+
Which shape matters less than it looks. On an exact `f**-2` power law, which
|
|
592
|
+
every one of them has to return unchanged, the median residual runs from
|
|
593
|
+
`1.3e-8` dex (`blackman`) to `3.4e-4` dex (`boxcar`) — an ordering that tracks
|
|
594
|
+
the taper's smoothness and a spread far below anything a fit would notice.
|
|
595
|
+
**Pick the width first and the shape second.**
|
|
596
|
+
|
|
597
|
+
`statistic="median"` is the one option that is not an average: the window
|
|
598
|
+
selects the samples and the median decides, so the shape is ignored. It is
|
|
599
|
+
there for spectra carrying spikes — a power-line tone, a dropout, a telemetry
|
|
600
|
+
glitch — which an average spreads across the whole window. With a single 60×
|
|
601
|
+
spike dropped into that power law, the worst residual across the axis is
|
|
602
|
+
`1.7e-2` dex for the median against `3.8e-2` for the geometric mean and
|
|
603
|
+
`3.6e-1` for the arithmetic one. It will discard a genuine narrow peak just as
|
|
604
|
+
happily, which is the trade.
|
|
605
|
+
|
|
606
|
+
One detail in it is worth knowing about, because it is not what the textbook
|
|
607
|
+
description of fractional-octave smoothing gives you. A window symmetric in log
|
|
608
|
+
frequency is **not** a symmetric average over samples: a Fourier grid is uniform
|
|
609
|
+
in Hz, so every window holds more samples above its centre than below in log
|
|
610
|
+
terms, and a plain per-sample mean tilts. Weighting each sample by its share of
|
|
611
|
+
the log axis removes it. Smoothing an exact `f**-2` power law, which has to come
|
|
612
|
+
back unchanged, the median residual is `1.5e-3` dex per-sample against `3.2e-8`
|
|
613
|
+
dex weighted for `hann`. It is on by default; `log_measure=False` gives the
|
|
614
|
+
per-sample behaviour, which is what Konno–Ohmachi does.
|
|
615
|
+
|
|
616
|
+
**`SavitzkyGolay`** fits a sliding polynomial rather than averaging, so it
|
|
617
|
+
flattens a peak far less. It is fitted to `log10(amp)` against `log10(f)` on a
|
|
618
|
+
uniform log-frequency grid — a polynomial in raw amplitude against raw frequency
|
|
619
|
+
spends its degrees of freedom on the falloff and can return a negative
|
|
620
|
+
amplitude. Ringing near the corner and the Nyquist roll-off is what it costs.
|
|
621
|
+
|
|
622
|
+
### What the choice actually changes
|
|
623
|
+
|
|
624
|
+
Less than it looks, and not where you would expect. **`[fitting] fit_bins` is
|
|
625
|
+
`false` by default, so the fit reads the unsmoothed spectrum.** The smoother's
|
|
626
|
+
whole influence on `Omega` is therefore indirect: it changes the signal-to-noise
|
|
627
|
+
ratio, which changes the band that passes the gate, which changes where the
|
|
628
|
+
plateau is read. The scatter column below is what the choice buys when
|
|
629
|
+
`fit_bins` is on, or when the reduced arrays are what you plot.
|
|
630
|
+
|
|
631
|
+
Measured on the 28 PNR windows, everything relative to the shipped default:
|
|
632
|
+
|
|
633
|
+
<!-- measured: smoothing_table -->
|
|
634
|
+
| Method | Banded | Band low (Hz) | Band (decades) | Δ plateau (dex) | Scatter (dex) |
|
|
635
|
+
|---|---|---|---|---|---|
|
|
636
|
+
| `log_bins` (default) | 28/28 | 0.94 | 1.55 | +0.000 | 0.317 |
|
|
637
|
+
| `konno_ohmachi`, b=40 | 28/28 | 0.93 | 1.68 | +0.067 | 0.093 |
|
|
638
|
+
| `log_window`, hann | 28/28 | 0.93 | 1.66 | +0.067 | 0.111 |
|
|
639
|
+
| `log_window`, bartlett | 28/28 | 0.93 | 1.66 | +0.067 | 0.102 |
|
|
640
|
+
| `log_window`, boxcar | 28/28 | 0.93 | 1.68 | +0.067 | 0.086 |
|
|
641
|
+
| `log_window`, gaussian | 28/28 | 0.93 | 1.65 | +0.067 | 0.147 |
|
|
642
|
+
| `log_window`, median | 28/28 | 0.93 | 1.69 | +0.067 | 0.091 |
|
|
643
|
+
| `savitzky_golay` | 28/28 | 0.93 | 1.67 | +0.067 | 0.063 |
|
|
644
|
+
| `none` | 28/28 | 0.94 | 1.51 | +0.000 | 0.318 |
|
|
645
|
+
<!-- /measured -->
|
|
646
|
+
|
|
647
|
+
Three things in that table are worth reading twice.
|
|
648
|
+
|
|
649
|
+
**The default barely smooths.** `log_bins` leaves the same scatter as `none`,
|
|
650
|
+
because 151 log bins over a window holding a few hundred Fourier samples puts
|
|
651
|
+
roughly one sample in most bins. It reduces the *axis*, not the noise.
|
|
652
|
+
|
|
653
|
+
**Every real smoother widens the band** by about a tenth of a decade. A smoothed
|
|
654
|
+
ratio crosses the threshold later, so more of the high-frequency tail survives
|
|
655
|
+
the gate — which is a gain if the tail is signal and a risk if it is not.
|
|
656
|
+
|
|
657
|
+
**The plateau moves by the same 0.067 dex under every one of them**, which is
|
|
658
|
+
0.045 in magnitude. That is not seven methods agreeing about amplitudes; it is
|
|
659
|
+
the low band edge moving from 0.94 Hz to 0.93 Hz under all of them, and the
|
|
660
|
+
plateau being read from there. The amplitudes the fit sees never changed.
|
|
661
|
+
|
|
662
|
+
Cost, measured once at best of three for the whole comparison over the 28
|
|
663
|
+
windows: `none` 63 ms,
|
|
664
|
+
`savitzky_golay` 140 ms, `log_bins` 143 ms, `log_window` 313 ms,
|
|
665
|
+
`log_window` with `statistic="median"` 688 ms, `konno_ohmachi` 830 ms. The
|
|
666
|
+
spread is one machine's, and the shape of it — Konno–Ohmachi building a full
|
|
667
|
+
weight matrix where `LogWindow` slides a window — is what generalises.
|
|
668
|
+
|
|
585
669
|
---
|
|
586
670
|
|
|
587
671
|
## Reproducing the published Magna configuration
|
|
@@ -114,7 +114,8 @@ with `specmod[multitaper]` installed passes tests that CI, which installs only
|
|
|
114
114
|
|
|
115
115
|
- **`main`** is the trunk. Everything lands here, and it is the default branch.
|
|
116
116
|
- **`master`** is frozen: the permanent record of the pre-refactor code, doing
|
|
117
|
-
the job a `v0.1.
|
|
117
|
+
the job a `v0.1.1` tag would have done: its tip, `453c77c`, is the commit the
|
|
118
|
+
Magna paper cites. Never commit to it.
|
|
118
119
|
- Feature branches are short-lived and merge into `main` via pull request.
|
|
119
120
|
|
|
120
121
|
Every pull request must target **`sgjholt/SpecMod`**. See §6.7 of the plan for
|
|
@@ -46,6 +46,10 @@ python -m json.tool build/magna_2020/manifest.json | head -40
|
|
|
46
46
|
- `channels` — the list *after* wildcard expansion. `HH*` does not tell you
|
|
47
47
|
what you got; this does. A much shorter list than expected usually means a
|
|
48
48
|
network was not open at that time, not that the request was malformed.
|
|
49
|
+
- `channels_available`, `channels_requested` — what the station query offered,
|
|
50
|
+
and what was asked for after the priority lists narrowed it. A large gap
|
|
51
|
+
between `channels_requested` and `channels` means the archive did not serve
|
|
52
|
+
what its own metadata advertises.
|
|
49
53
|
- `data_centre`, `obspy_version`, `specmod_version`, `fetched_at` — the
|
|
50
54
|
provenance that makes the response reproducible-ish. It cannot be fully
|
|
51
55
|
reproducible: FDSN is not content-addressed, archives get backfilled and
|
|
@@ -54,6 +58,49 @@ python -m json.tool build/magna_2020/manifest.json | head -40
|
|
|
54
58
|
If any of that is wrong, fix the config and re-fetch. The artefact is about to
|
|
55
59
|
become immutable.
|
|
56
60
|
|
|
61
|
+
### Picking one instrument per station
|
|
62
|
+
|
|
63
|
+
A `channel` pattern that names several instruments — `HH*,BH*,HN*,EN*` — returns
|
|
64
|
+
every one of them at every station that has them. Magna's 88 stations return 507
|
|
65
|
+
channels that way, and a station with both a broadband and an accelerometer
|
|
66
|
+
contributes the same ground motion twice: two entries in a `SpectrumSet`,
|
|
67
|
+
weighted as two stations by anything that averages over them.
|
|
68
|
+
|
|
69
|
+
`channel_priorities` ranks them instead. The first pattern that matches anything
|
|
70
|
+
at a station wins, so the list is read as "a broadband if there is one,
|
|
71
|
+
otherwise an accelerometer":
|
|
72
|
+
|
|
73
|
+
```toml
|
|
74
|
+
[stations]
|
|
75
|
+
channel = "HH*,BH*,HN*,EN*"
|
|
76
|
+
channel_priorities = ["HH[ZNE]", "BH[ZNE]", "HN[ZNE]", "EN[ZNE]"]
|
|
77
|
+
location_priorities = ["", "00", "10"]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`channel` still says what the data centre may offer; the priorities say which of
|
|
81
|
+
what it offers to keep. A station matching no pattern at all is dropped — the
|
|
82
|
+
list is a restriction as well as a ranking — and the written `inventory.xml` is
|
|
83
|
+
pruned to match, so the archive keeps describing exactly what it holds.
|
|
84
|
+
|
|
85
|
+
Patterns are matched case-sensitively against SEED codes, which are upper case.
|
|
86
|
+
`["*"]` keeps everything, which is how a config says it wants both instruments
|
|
87
|
+
and means it; with no list at all, `fetch` warns that it is fetching co-sited
|
|
88
|
+
instruments and names the stations.
|
|
89
|
+
|
|
90
|
+
### What the radius means
|
|
91
|
+
|
|
92
|
+
`max_radius_km` is cut against the true WGS84 distance from the epicentre, not
|
|
93
|
+
against the degrees FDSN takes. A degree of arc is 110.574 km at the equator and
|
|
94
|
+
111.691 km at the poles, so converting with a single constant moves the boundary
|
|
95
|
+
by up to half a percent — ±0.3 km on a 50 km radius, ±2 km on 400 km. The
|
|
96
|
+
station query is sent deliberately wide and the exact cut is made locally, which
|
|
97
|
+
costs a few extra stations in the query and makes the radius mean kilometres
|
|
98
|
+
wherever the event is.
|
|
99
|
+
|
|
100
|
+
The radii are epicentral. For a local array the depth is usually the larger
|
|
101
|
+
term: every station of a 500 m array over a 2 km-deep event is at 2 km
|
|
102
|
+
hypocentral distance.
|
|
103
|
+
|
|
57
104
|
## 2. Archive and hash
|
|
58
105
|
|
|
59
106
|
```bash
|
|
@@ -35,7 +35,10 @@ The version before this one, `0.1.1`, is the pre-refactor code that produced
|
|
|
35
35
|
the published Magna results. It is preserved unchanged on the
|
|
36
36
|
[`master`](https://github.com/sgjholt/SpecMod/tree/master) branch, which is
|
|
37
37
|
protected and frozen — it was never tagged or published to PyPI, so that
|
|
38
|
-
branch is the only reference to it.
|
|
38
|
+
branch is the only reference to it. Its tip,
|
|
39
|
+
[`453c77c`](https://github.com/sgjholt/SpecMod/commit/453c77c), is the commit
|
|
40
|
+
the paper cites as v0.1.1; cite that rather than the branch name, which is a
|
|
41
|
+
moving target in principle even though this one will not move. Everything below is the delta between it
|
|
39
42
|
and v0.2.0, which is why the first changelog is enormous and correctly so.
|
|
40
43
|
|
|
41
44
|
### An installable package
|
|
@@ -106,11 +109,11 @@ build**, so every figure and number on the page came from running the code
|
|
|
106
109
|
being documented. A notebook that stops working fails the build rather than
|
|
107
110
|
going quietly stale, which is why it was a 1.0 requirement.
|
|
108
111
|
|
|
109
|
-
##
|
|
112
|
+
## Shipped in v0.3.0
|
|
110
113
|
|
|
111
|
-
###
|
|
114
|
+
### The decomposition, finished
|
|
112
115
|
|
|
113
|
-
|
|
116
|
+
This was the last item 1.0 was waiting on.
|
|
114
117
|
|
|
115
118
|
`io.py` and `plotting.py` are now packages, alongside the spectral core, the
|
|
116
119
|
fitting layer and the pick readers; the type-checking backlog is empty. The
|
|
@@ -136,13 +139,67 @@ signposted from [Guides](guides.md) rather than split onto a page of their own.
|
|
|
136
139
|
[Upgrading](upgrading.md) covers moving code off the pre-refactor
|
|
137
140
|
`master`.
|
|
138
141
|
|
|
142
|
+
## Shipped in v0.4.0
|
|
143
|
+
|
|
144
|
+
### Smoothing became a choice, and the choice is applied
|
|
145
|
+
|
|
146
|
+
`[smoothing] method` selected nothing. The registry mapped the names, the config
|
|
147
|
+
validated against them, and no code read the result: every spectrum was
|
|
148
|
+
log-binned whatever the setting said. Measured on the 28 PNR windows,
|
|
149
|
+
`log_bins`, `konno_ohmachi` and `none` produced bit-identical output — `none`
|
|
150
|
+
included, which reads as "leave my spectra unsmoothed".
|
|
151
|
+
|
|
152
|
+
It is wired now, with three methods beside the two:
|
|
153
|
+
|
|
154
|
+
- **`log_window`** — constant relative bandwidth over a window you name:
|
|
155
|
+
boxcar, Bartlett, Hann, Hamming, Blackman or Gaussian, a fraction of an
|
|
156
|
+
octave wide everywhere. Konno–Ohmachi is this family with its own window.
|
|
157
|
+
`statistic="median"` discards a spike rather than averaging it in, and
|
|
158
|
+
discards a genuine narrow peak with it.
|
|
159
|
+
- **`savitzky_golay`** — a local polynomial fit in log–log, which keeps peak
|
|
160
|
+
amplitude and width where a running mean flattens both.
|
|
161
|
+
- **`none`** — no smoothing, which now means it.
|
|
162
|
+
|
|
163
|
+
Log-binning replaces the frequency axis; the others preserve it. That is the
|
|
164
|
+
distinction the setting had no way to express, and the reason wiring it up was
|
|
165
|
+
a design change rather than a patch.
|
|
166
|
+
|
|
167
|
+
One detail that is easy to get wrong and is worth knowing about: a window
|
|
168
|
+
symmetric in log frequency is not a symmetric average over samples, because a
|
|
169
|
+
Fourier grid is uniform in Hz. Weighting samples equally tilts the result by
|
|
170
|
+
1.5e-3 dex on an `f**-2` power law; weighting each by its share of the log
|
|
171
|
+
axis brings that to 3.2e-8 dex. The latter is the default. Konno–Ohmachi
|
|
172
|
+
applies the former, by definition, and keeps it.
|
|
173
|
+
|
|
174
|
+
## In progress — not yet released
|
|
175
|
+
|
|
176
|
+
Merged on `main`, and it will name its version when a release goes out.
|
|
177
|
+
|
|
178
|
+
### The station selection means what the config says
|
|
179
|
+
|
|
180
|
+
Three ways a fetched dataset did not match the config that asked for it, all
|
|
181
|
+
found by a live fetch rather than by the suite:
|
|
182
|
+
|
|
183
|
+
- `max_radius_km` reached the station query and never the waveform request,
|
|
184
|
+
because FDSN dataselect has no geographic parameters. A 50 km fetch returned
|
|
185
|
+
channels from 225 km out, with no metadata beside them. Waveforms are now
|
|
186
|
+
asked for by name, from the inventory the station query returned.
|
|
187
|
+
- The radius was converted at 111.195 km per degree. A degree of arc is
|
|
188
|
+
110.574 km at the equator and 111.691 km at the poles, so the boundary moved
|
|
189
|
+
with latitude — ±0.3 km at 50 km, ±2 km at 400 km. The query is now sent
|
|
190
|
+
deliberately wide and the cut made against the true WGS84 distance.
|
|
191
|
+
- A `channel` pattern naming several instruments returned all of them at every
|
|
192
|
+
station, so a broadband and the accelerometer beside it entered the pipeline
|
|
193
|
+
as two independent records of one ground motion. `channel_priorities` and
|
|
194
|
+
`location_priorities` rank them, first match wins per station.
|
|
195
|
+
|
|
139
196
|
## Planned
|
|
140
197
|
|
|
141
198
|
### 1.0 — the API stops moving
|
|
142
199
|
|
|
143
|
-
**Everything this was waiting on
|
|
144
|
-
decomposition above with the signature changes it implied. What remains is
|
|
145
|
-
release itself, which says that names and signatures stop moving without a
|
|
200
|
+
**Everything this was waiting on shipped in v0.3.0** — the documentation, and
|
|
201
|
+
the decomposition above with the signature changes it implied. What remains is
|
|
202
|
+
the release itself, which says that names and signatures stop moving without a
|
|
146
203
|
deprecation cycle.
|
|
147
204
|
|
|
148
205
|
That promise is the whole content of the number, which is why it has to be a
|
|
@@ -151,6 +208,21 @@ is made, breaking changes bump the minor. The honest test before making it is
|
|
|
151
208
|
whether a release goes by without one — the API is not settled because the
|
|
152
209
|
backlog is empty, it is settled when it stops moving.
|
|
153
210
|
|
|
211
|
+
**By that test, 1.0 is not ready.** v0.3.0 is the release that emptied the
|
|
212
|
+
backlog and it carried two breaking changes itself: the ten renamed
|
|
213
|
+
`preprocess` functions, and the tutorial's page moving. So what 1.0 now waits
|
|
214
|
+
on is a release going out without one — which is a thing that has to be
|
|
215
|
+
observed rather than declared, and cannot be brought forward by finishing
|
|
216
|
+
anything.
|
|
217
|
+
|
|
218
|
+
**v0.4.0 is the first observation, and it is not clean.** No name or signature
|
|
219
|
+
moved: the smoothing work was additive, and the `SpectrumPair.compare`
|
|
220
|
+
parameter it added is optional. But `[smoothing] method` changed what it does,
|
|
221
|
+
so a config that set `konno_ohmachi` or `none` gets different numbers out of
|
|
222
|
+
the same code path. Nothing breaks at import or at the call; results move. That
|
|
223
|
+
is a weaker promise than the one 1.0 makes and a real one to have broken, so
|
|
224
|
+
the count starts again rather than standing at one.
|
|
225
|
+
|
|
154
226
|
## After 1.0
|
|
155
227
|
|
|
156
228
|
Designed but deliberately not on the path to 1.0, because each is blocked on
|
|
@@ -175,7 +247,16 @@ guess written from documentation cannot substitute for:
|
|
|
175
247
|
Each shipped entry names the version that carries it, so a reader can install
|
|
176
248
|
that version and check the claim. Work that is merged but unreleased sits under
|
|
177
249
|
*In progress* and gets its version when a release goes out — merged is not
|
|
178
|
-
shipped, and this page does not blur the two.
|
|
250
|
+
shipped, and this page does not blur the two. Between releases there is no such
|
|
251
|
+
section at all, which is a state the page should be in rather than a section
|
|
252
|
+
that went missing.
|
|
253
|
+
|
|
254
|
+
The move at release time is the step this page got wrong once. The v0.3.0 work
|
|
255
|
+
sat under *In progress — not yet released* for a week after v0.3.0 was
|
|
256
|
+
released, because `release-please` writes the changelog and the manifest and
|
|
257
|
+
knows nothing about this file. `tests/test_release_config.py` now fails when
|
|
258
|
+
the released minor version is ahead of every version this page names, which is
|
|
259
|
+
the check that was missing rather than a rule that was.
|
|
179
260
|
|
|
180
261
|
Before v0.2.0 this was a list of stages, because there was no released version
|
|
181
262
|
to point at and "done" could only mean merged. The full changelog for every
|