gmprocess 2.6.0__tar.gz → 2.7.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.
- {gmprocess-2.6.0 → gmprocess-2.7.0}/.gitignore +1 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/.vscode/settings.json +1 -1
- {gmprocess-2.6.0 → gmprocess-2.7.0}/CHANGELOG.md +19 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/PKG-INFO +1 -1
- {gmprocess-2.6.0 → gmprocess-2.7.0}/code.json +41 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/pyproject.toml +2 -0
- gmprocess-2.7.0/src/gmprocess/bin/export_ff_sac.py +315 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/core/stationstream.py +38 -26
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/core/streamcollection.py +7 -1
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/flatfile.py +18 -3
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/flatfile_constants.py +3 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/cosmos/cesmd_fetcher.py +14 -1
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/cosmos/cosmos_writer.py +5 -5
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/global_fetcher.py +6 -4
- gmprocess-2.7.0/src/gmprocess/io/knet/knet_fetcher.py +420 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/waveform_metric_collection.py +5 -2
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/compute_station_metrics.py +10 -6
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/export_gmpacket_utils.py +12 -2
- gmprocess-2.7.0/src/gmprocess/waveform_processing/count_stats.py +14 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/detrend.py +2 -1
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/instrument_response.py +21 -11
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess.egg-info/PKG-INFO +1 -1
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess.egg-info/SOURCES.txt +2 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess.egg-info/entry_points.txt +1 -0
- gmprocess-2.6.0/src/gmprocess/io/knet/knet_fetcher.py +0 -441
- {gmprocess-2.6.0 → gmprocess-2.7.0}/.coveragerc +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/.gitlab-ci.yml +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/CODE_OF_CONDUCT.md +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/CONTRIBUTING.md +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/DISCLAIMER.md +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/LICENSE.md +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/MANIFEST.in +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/README.md +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/pytest.ini +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/setup.cfg +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/setup.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/setup_env.sh +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/apps/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/apps/gmrecords.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/bundle_datarelease.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/cwa_gather.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/fetch_orfeus.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/fix_inventory.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/get_cali_cloud.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/gmconvert.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/gminfo.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/gmprocess_config.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/gmrecords.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/gmworkspace.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/bin/update_event_json.sh +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/core/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/core/provenance.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/core/scalar_event.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/core/stationtrace.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/core/streamarray.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/CESMD_NGA_ids.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/config_production.yml +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/config_production_v1.yml +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/config_test.yml +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/config_test_download.yml +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/cosmos_table10.xls +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/cosmos_table4.xls +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/demo/ci38457511/raw/CICCC.RAW +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/demo/ci38457511/raw/CICLC.v1 +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/demo/ci38457511/raw/CITOW2.RAW +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/demo/nc72282711/workspace.h5 +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/fdsn_codes.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/lme/SA_rotd50.0_2020.03.31.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/modules.yml +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nga_w2_selected.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_clipping/bias_1.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_clipping/bias_output.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_clipping/masterF.txt +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_clipping/weight_1.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_clipping/weight_output.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/M.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/bias_1.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/bias_2.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/bias_output.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/final_training.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/masterF.txt +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/model_3.txt +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/model_5.txt +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/mu_sigma.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/weight_1.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/weight_2.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/Cant/weight_output.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/M.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/bias_1.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/bias_2.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/bias_output.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/final_training.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/masterF.txt +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/model_0.txt +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/mu_sigma.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/weight_1.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/weight_2.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/nn_qa/CantWell/weight_output.csv +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/picker.yml +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/station_coordinates.xlsx +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/data/usgs_ids_nga_and_srcmod_cross_reference.xlsx +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/gui/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/gui/gui_ucla/Documentation.md +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/gui/gui_ucla/GUI_human_review.ipynb +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/gui/gui_ucla/HumanReviewGUI.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/gui/gui_ucla/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/base_metrics_xml.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/path_utils.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/rupture.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/station_metrics_xml.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/stream_workspace.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/utils.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/waveform_metrics_xml.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/asdf/workspace_constants.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/bhrc/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/bhrc/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/cosmos/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/cosmos/cesmd_search.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/cosmos/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/cosmos/data_structures.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/cwb/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/cwb/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/dmg/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/dmg/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/dynamic_search_parameters.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/esm/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/esm/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/fetcher.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/geonet/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/geonet/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/knet/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/knet/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/nga.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/nsmn/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/nsmn/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/obspy/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/obspy/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/obspy/fdsn_fetcher.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/read.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/read_directory.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/renadic/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/renadic/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/report.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/seedname.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/smc/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/smc/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/unam/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/unam/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/usc/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/usc/core.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/io/utils.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/combine.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/containers.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/metric_collection_base.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/oscillator.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/reduce.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/rotate.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/station_metric.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/station_metric_collection.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/transform.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/utils.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/waveform_metric_calculator.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/waveform_metric_calculator_component_base.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/waveform_metric_component.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/waveform_metric_list.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/metrics/waveform_metric_type.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/arg_dicts.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/assemble.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/autoprocess.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/autoshakemap.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/base.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/clean.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/compute_waveform_metrics.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/download.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/export_cosmos.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/export_failure_tables.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/export_gmpacket.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/export_metric_tables.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/export_provenance_tables.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/generate_regression_plot.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/generate_report.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/generate_station_maps.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/import_data.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/init.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/lazy_loader.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/process_waveforms.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/processing_steps.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/subcommands/projects.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/args.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/assemble_utils.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/config.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/config_versioning.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/constants.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/download_utils.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/ground_motion_models.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/logging.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/memory.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/misc.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/misc_plots.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/prompt.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/report_utils.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/rupture_utils.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/strec.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/summary_plots.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/tables.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/utils/tests_utils.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/__init__.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/adjust_highpass.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/adjust_highpass_ridder.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/baseline_correction.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/clipping/clip_detection.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/clipping/clipping_ann.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/clipping/clipping_check.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/clipping/histogram.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/clipping/jerk.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/clipping/max_amp.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/clipping/ping.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/clipping/std_dev.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/convert_units.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/corner_frequencies.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/fft.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/filtering.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/integrate.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/nn_quality_assurance.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/phase.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/pretesting.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/prism_adaptive_baseline.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/processing.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/processing_step.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/resample.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/sanity_checks.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/snr.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/spectrum.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/taper.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/windows.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/zero_crossings.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess/waveform_processing/zero_pad.py +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess.egg-info/dependency_links.txt +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess.egg-info/requires.txt +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/src/gmprocess.egg-info/top_level.txt +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/tools/matlab/README.md +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/tools/matlab/get_all_waveforms.m +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/tools/matlab/get_events.m +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/tools/matlab/get_waveform_metrics.m +0 -0
- {gmprocess-2.6.0 → gmprocess-2.7.0}/tools/matlab/waveform_plot.png +0 -0
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
## main
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
## 2.7.0 / 2026-06-04
|
|
5
|
+
|
|
6
|
+
- Enhancements
|
|
7
|
+
- Support PSA metric for gmpacket files
|
|
8
|
+
- Add export_ff_sac script for selecting SAC files for finite fault inversion
|
|
9
|
+
- Add unit test for export_ff_sac script
|
|
10
|
+
- Treat an empty location code as the same as "--" when checking for duplicate records
|
|
11
|
+
- Updated KNET fetcher to use NIED http directory interface
|
|
12
|
+
- Added unit tests to test V3 cosmos writer (and updated workspace.h5)
|
|
13
|
+
- Add "count_mean", "count_min", and "count_max" as trace parameters.
|
|
14
|
+
- Add logging to show query for CESMD fetcher if a timeout occurs
|
|
15
|
+
- Bugfix
|
|
16
|
+
- Fixed cosmos v3 writer where damping_values was assigned in wrong scope
|
|
17
|
+
- Fixed cosmos v3 bug with concatenate_channels=False (only one trace got periods)
|
|
18
|
+
- Set trace warnings and failures for instrument response mismatches between total sensitivity and stages.
|
|
19
|
+
- Fix station metric bug in imc_sort by forcing waveform metric to match station metric before writing
|
|
20
|
+
- Fix compute_station_metrics.py to write to station metrics if any stream passed
|
|
21
|
+
|
|
3
22
|
## 2.6.0 / 2026-04-20
|
|
4
23
|
|
|
5
24
|
- Enhancements
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gmprocess
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: USGS Automated Ground Motion Processing Software
|
|
5
5
|
Author-email: Eric Thompson <emthompsone@usgs.gov>, Mike Hearne <mhearne@usgs.gov>, Brad Aagaard <baagaard@usgs.gov>, Bruce Worden <cbworden@contractor.usgs.gov>, John Rekoske <jrekoske@ucsd.edu>, Heather Hunsinger <hhunsinger@usgs.gov>, Gabe Ferragut <gferragut@usgs.gov>
|
|
6
6
|
License: License
|
|
@@ -1,4 +1,45 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"name": "groundmotion-processing",
|
|
4
|
+
"description": "Read and process ground motion waveform data",
|
|
5
|
+
"version": "v2.7.0",
|
|
6
|
+
"status": "Production",
|
|
7
|
+
"organization": "U.S. Geological Survey",
|
|
8
|
+
"vcs": "git",
|
|
9
|
+
"repositoryURL": "https://code.usgs.gov/ghsc/esi/groundmotion-processing.git",
|
|
10
|
+
"homepageURL": "https://code.usgs.gov/ghsc/esi/groundmotion-processing",
|
|
11
|
+
"downloadURL": "https://code.usgs.gov/ghsc/esi/groundmotion-processing/-/archive/v2.7.0/groundmotion-processing-v2.7.0.zip",
|
|
12
|
+
"disclaimerURL": "https://code.usgs.gov/ghsc/esi/groundmotion-processing/-/raw/v2.7.0/DISCLAIMER.md",
|
|
13
|
+
"permissions": {
|
|
14
|
+
"licenses": [
|
|
15
|
+
{
|
|
16
|
+
"name": "Public Domain, CC0-1.0",
|
|
17
|
+
"URL": "https://code.usgs.gov/ghsc/esi/groundmotion-processing/-/raw/v2.7.0/LICENSE.md"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"usageType": "openSource",
|
|
21
|
+
"exemptionText": null
|
|
22
|
+
},
|
|
23
|
+
"laborHours": 1,
|
|
24
|
+
"languages": [
|
|
25
|
+
"python"
|
|
26
|
+
],
|
|
27
|
+
"tags": [
|
|
28
|
+
"earthquake",
|
|
29
|
+
"impact",
|
|
30
|
+
"strong motion",
|
|
31
|
+
"amplitudes",
|
|
32
|
+
"ground motion",
|
|
33
|
+
"usg-artificial-intelligence"
|
|
34
|
+
],
|
|
35
|
+
"contact": {
|
|
36
|
+
"name": "Eric Thompson",
|
|
37
|
+
"email": "emthompson@usgs.gov"
|
|
38
|
+
},
|
|
39
|
+
"date": {
|
|
40
|
+
"metadataLastUpdated": "2026-06-04"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
2
43
|
{
|
|
3
44
|
"name": "groundmotion-processing",
|
|
4
45
|
"description": "Read and process ground motion waveform data",
|
|
@@ -98,6 +98,8 @@ cwa_gather = "gmprocess.bin.cwa_gather:cli"
|
|
|
98
98
|
fix_inventory = "gmprocess.bin.fix_inventory:main"
|
|
99
99
|
fetch_orfeus = "gmprocess.bin.fetch_orfeus:cli"
|
|
100
100
|
get_cali_cloud = "gmprocess.bin.get_cali_cloud:main"
|
|
101
|
+
export_ff_sac = "gmprocess.bin.export_ff_sac:main"
|
|
102
|
+
|
|
101
103
|
|
|
102
104
|
[build-system]
|
|
103
105
|
requires = [
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"""Export SAC files for finite fault inversion from a gmprocess workspace.h5"""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
import numpy as np
|
|
8
|
+
from gmprocess.io.asdf.stream_workspace import StreamWorkspace
|
|
9
|
+
from obspy.geodetics import gps2dist_azimuth
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_parser():
|
|
13
|
+
parser = argparse.ArgumentParser(
|
|
14
|
+
description=(
|
|
15
|
+
"Select a set of stations from a gmprocess workspace"
|
|
16
|
+
" and export SAC files for finite fault inversion."
|
|
17
|
+
)
|
|
18
|
+
)
|
|
19
|
+
parser.add_argument(
|
|
20
|
+
"workspace",
|
|
21
|
+
type=Path,
|
|
22
|
+
help="Path to the gmprocess workspace HDF5 file (e.g. workspace.h5).",
|
|
23
|
+
)
|
|
24
|
+
parser.add_argument(
|
|
25
|
+
"event_id",
|
|
26
|
+
help="Event ID as stored in the workspace (e.g. us6000sri7).",
|
|
27
|
+
)
|
|
28
|
+
parser.add_argument(
|
|
29
|
+
"--max-dist",
|
|
30
|
+
type=float,
|
|
31
|
+
default=300.0,
|
|
32
|
+
help="Maximum epicentral distance in km for station inclusion (default: 300).",
|
|
33
|
+
)
|
|
34
|
+
parser.add_argument(
|
|
35
|
+
"--n-max",
|
|
36
|
+
type=int,
|
|
37
|
+
default=20,
|
|
38
|
+
help="Maximum number of stations to select (default: 20).",
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
"--n-lat",
|
|
42
|
+
type=int,
|
|
43
|
+
default=5,
|
|
44
|
+
help="Number of latitude grid rows for spatial sampling (default: 5).",
|
|
45
|
+
)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--n-lon",
|
|
48
|
+
type=int,
|
|
49
|
+
default=4,
|
|
50
|
+
help="Number of longitude grid columns for spatial sampling (default: 4).",
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
"--out-dir",
|
|
54
|
+
type=Path,
|
|
55
|
+
default=None,
|
|
56
|
+
help="Output directory for SAC files (default: <event_id>/).",
|
|
57
|
+
)
|
|
58
|
+
parser.add_argument(
|
|
59
|
+
"--supp-stations",
|
|
60
|
+
nargs="+",
|
|
61
|
+
default=[],
|
|
62
|
+
metavar="STA",
|
|
63
|
+
help="Additional station IDs to include.",
|
|
64
|
+
)
|
|
65
|
+
return parser
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def collect_stream_data(sc, event):
|
|
69
|
+
"""Extract per-stream arrays of lat, lon, dist, pgv for passing streams.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
sc (StreamCollection): Streams from the workspace.
|
|
73
|
+
event (ScalarEvent): Event object with latitude and longitude attributes.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
tuple: lat, lon, dist, pgv (np.ndarray) and passing_indices (list of int).
|
|
77
|
+
"""
|
|
78
|
+
lat, lon, dist, pgv, passing_indices = [], [], [], [], []
|
|
79
|
+
|
|
80
|
+
for i, stream in enumerate(sc):
|
|
81
|
+
if not stream.passed:
|
|
82
|
+
continue
|
|
83
|
+
passing_indices.append(i)
|
|
84
|
+
trace = stream[0]
|
|
85
|
+
slat = trace.stats.coordinates.latitude
|
|
86
|
+
slon = trace.stats.coordinates.longitude
|
|
87
|
+
lat.append(slat)
|
|
88
|
+
lon.append(slon)
|
|
89
|
+
dist.append(
|
|
90
|
+
gps2dist_azimuth(slat, slon, event.latitude, event.longitude)[0]
|
|
91
|
+
/ 1000.0
|
|
92
|
+
)
|
|
93
|
+
pgvs = [
|
|
94
|
+
np.max(np.abs(tr.copy().integrate().data))
|
|
95
|
+
for tr in stream
|
|
96
|
+
if tr.stats.channel[2] != "Z"
|
|
97
|
+
]
|
|
98
|
+
pgv.append(np.max(pgvs) if pgvs else 0.0)
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
np.array(lat),
|
|
102
|
+
np.array(lon),
|
|
103
|
+
np.array(dist),
|
|
104
|
+
np.array(pgv),
|
|
105
|
+
passing_indices,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def select_stations(lat, lon, dist, pgv, max_dist, n_max, n_lat, n_lon):
|
|
110
|
+
"""Select a spatially distributed subset of stations ranked by PGV.
|
|
111
|
+
|
|
112
|
+
Divides the region into an n_lat x n_lon grid and picks the highest-PGV
|
|
113
|
+
station from each occupied cell, then fills remaining slots by global PGV
|
|
114
|
+
rank up to n_max.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
lat (np.ndarray): Station latitudes.
|
|
118
|
+
lon (np.ndarray): Station longitudes.
|
|
119
|
+
dist (np.ndarray): Epicentral distances in km.
|
|
120
|
+
pgv (np.ndarray): Peak ground velocity (horizontal) in m/s.
|
|
121
|
+
max_dist (float): Distance cutoff in km.
|
|
122
|
+
n_max (int): Maximum total stations to select.
|
|
123
|
+
n_lat (int): Number of latitude grid rows.
|
|
124
|
+
n_lon (int): Number of longitude grid columns.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
tuple: id_selected (list of int), idx (np.ndarray), lat_bks
|
|
128
|
+
(np.ndarray), lon_bks (np.ndarray).
|
|
129
|
+
"""
|
|
130
|
+
idx = np.where(dist < max_dist)[0]
|
|
131
|
+
|
|
132
|
+
eps = 1e-6
|
|
133
|
+
lat_bks = np.linspace(
|
|
134
|
+
lat[idx].min() - eps, lat[idx].max() + eps, n_lat + 1
|
|
135
|
+
)
|
|
136
|
+
lon_bks = np.linspace(
|
|
137
|
+
lon[idx].min() - eps, lon[idx].max() + eps, n_lon + 1
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
quad_id = np.full(len(dist), -1, dtype=int)
|
|
141
|
+
for i, (qx, qy) in enumerate(
|
|
142
|
+
[(x, y) for x in range(n_lon) for y in range(n_lat)]
|
|
143
|
+
):
|
|
144
|
+
q_idx = np.where(
|
|
145
|
+
(lat[idx] > lat_bks[qy])
|
|
146
|
+
& (lat[idx] < lat_bks[qy + 1])
|
|
147
|
+
& (lon[idx] > lon_bks[qx])
|
|
148
|
+
& (lon[idx] < lon_bks[qx + 1])
|
|
149
|
+
)[0]
|
|
150
|
+
if len(q_idx):
|
|
151
|
+
quad_id[idx[q_idx]] = i
|
|
152
|
+
|
|
153
|
+
# Pick highest PGV from each occupied grid cell
|
|
154
|
+
id_selected = []
|
|
155
|
+
for qid in range(n_lat * n_lon):
|
|
156
|
+
idx_quad = np.where(qid == quad_id)[0]
|
|
157
|
+
if len(idx_quad):
|
|
158
|
+
id_selected.append(idx_quad[np.argmax(pgv[idx_quad])])
|
|
159
|
+
|
|
160
|
+
# Fill remaining slots by global PGV rank
|
|
161
|
+
if n_max > len(id_selected):
|
|
162
|
+
n_add = n_max - len(id_selected)
|
|
163
|
+
idx_rem = np.setdiff1d(idx, id_selected)
|
|
164
|
+
id_selected.extend(idx_rem[np.flip(np.argsort(pgv[idx_rem]))][:n_add])
|
|
165
|
+
|
|
166
|
+
return id_selected, idx, lat_bks, lon_bks
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def make_sac_headers(channel_code, slat, slon):
|
|
170
|
+
"""Return SAC header dict with cmpaz/cmpinc set for the given channel.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
channel_code (str): Channel code (e.g. HNN, HNE, HNZ).
|
|
174
|
+
slat (float): Station latitude.
|
|
175
|
+
slon (float): Station longitude.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
dict: SAC header dict suitable for assignment to ``trace.stats.sac``.
|
|
179
|
+
"""
|
|
180
|
+
component = channel_code[2]
|
|
181
|
+
if component == "Z":
|
|
182
|
+
cmpinc, cmpaz = 90.0, 0.0
|
|
183
|
+
else:
|
|
184
|
+
cmpinc = 0.0
|
|
185
|
+
cmpaz = 0.0 if component in ("N", "1") else 90.0
|
|
186
|
+
return {"stla": slat, "stlo": slon, "cmpaz": cmpaz, "cmpinc": cmpinc}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def write_sac_files(streams, passing_indices, id_selected, out_dir):
|
|
190
|
+
"""Write SAC files for selected streams to out_dir.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
streams (StreamCollection): Streams from the workspace.
|
|
194
|
+
passing_indices (list of int): Indices of passing stations.
|
|
195
|
+
id_selected (list of int): Indices of selected stations.
|
|
196
|
+
out_dir (Path): Output directory (created if absent).
|
|
197
|
+
"""
|
|
198
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
199
|
+
for id_sel in id_selected:
|
|
200
|
+
stream = streams[passing_indices[id_sel]]
|
|
201
|
+
for trace in stream:
|
|
202
|
+
trace.stats.sac = make_sac_headers(
|
|
203
|
+
trace.stats.channel,
|
|
204
|
+
trace.stats.coordinates.latitude,
|
|
205
|
+
trace.stats.coordinates.longitude,
|
|
206
|
+
)
|
|
207
|
+
trace.write(
|
|
208
|
+
filename=str(out_dir / (trace.id + ".SAC")), format="SAC"
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def write_supp_sac_files(sc, sta_ids, supp_dir):
|
|
213
|
+
"""Write SAC files for supplemental stations to supp_dir.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
sc (StreamCollection): Streams from the workspace.
|
|
217
|
+
sta_ids (list of str): Station IDs to include.
|
|
218
|
+
supp_dir (Path): Output directory for supplemental files (created if absent).
|
|
219
|
+
"""
|
|
220
|
+
if not sta_ids:
|
|
221
|
+
return
|
|
222
|
+
supp_dir.mkdir(parents=True, exist_ok=True)
|
|
223
|
+
for stream in sc:
|
|
224
|
+
if stream.passed and stream[0].stats.station in sta_ids:
|
|
225
|
+
for trace in stream:
|
|
226
|
+
trace.stats.sac = make_sac_headers(
|
|
227
|
+
trace.stats.channel,
|
|
228
|
+
trace.stats.coordinates.latitude,
|
|
229
|
+
trace.stats.coordinates.longitude,
|
|
230
|
+
)
|
|
231
|
+
trace.write(
|
|
232
|
+
filename=str(supp_dir / (trace.id + ".SAC")), format="SAC"
|
|
233
|
+
)
|
|
234
|
+
print(f"Wrote supplemental stations to {supp_dir}/")
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def save_summary_plot(
|
|
238
|
+
lat, lon, idx, id_selected, lat_bks, lon_bks, event, eqid, outdir
|
|
239
|
+
):
|
|
240
|
+
"""Save a map of candidate and selected stations.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
lat (np.ndarray): Station latitudes for all passing streams.
|
|
244
|
+
lon (np.ndarray): Station longitudes for all passing streams.
|
|
245
|
+
idx (np.ndarray): Indices of candidate stations within the distance cutoff.
|
|
246
|
+
id_selected (list of int): Indices of the selected stations.
|
|
247
|
+
lat_bks (np.ndarray): Latitude grid breakpoints.
|
|
248
|
+
lon_bks (np.ndarray): Longitude grid breakpoints.
|
|
249
|
+
event (ScalarEvent): Event object providing epicenter coordinates.
|
|
250
|
+
eqid (str): Event ID used to construct the output filename.
|
|
251
|
+
"""
|
|
252
|
+
fig, ax = plt.subplots()
|
|
253
|
+
ax.plot(lon[idx], lat[idx], "vk", label="Candidate")
|
|
254
|
+
for lb in lon_bks:
|
|
255
|
+
ax.axvline(x=lb, color="gray", linewidth=0.5)
|
|
256
|
+
for lb in lat_bks:
|
|
257
|
+
ax.axhline(y=lb, color="gray", linewidth=0.5)
|
|
258
|
+
ax.plot(lon[id_selected], lat[id_selected], "vg", label="Selected")
|
|
259
|
+
ax.plot(
|
|
260
|
+
event.longitude, event.latitude, "*r", markersize=12, label="Epicenter"
|
|
261
|
+
)
|
|
262
|
+
ax.set_xlabel("Longitude")
|
|
263
|
+
ax.set_ylabel("Latitude")
|
|
264
|
+
ax.legend()
|
|
265
|
+
fname = Path(outdir) / f"{eqid}_select_summary.png"
|
|
266
|
+
fig.savefig(fname, dpi=300)
|
|
267
|
+
plt.close(fig)
|
|
268
|
+
print(f"Wrote summary plot: {fname}")
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def main():
|
|
272
|
+
parser = get_parser()
|
|
273
|
+
args = parser.parse_args()
|
|
274
|
+
|
|
275
|
+
sw = StreamWorkspace.open(args.workspace)
|
|
276
|
+
sc = sw.get_streams(args.event_id, labels=["default"])
|
|
277
|
+
event = sw.get_event(args.event_id)
|
|
278
|
+
|
|
279
|
+
lat, lon, dist, pgv, passing_indices = collect_stream_data(sc, event)
|
|
280
|
+
|
|
281
|
+
if len(lat) == 0:
|
|
282
|
+
print("No passing streams found in workspace. Exiting.")
|
|
283
|
+
return
|
|
284
|
+
|
|
285
|
+
id_selected, idx, lat_bks, lon_bks = select_stations(
|
|
286
|
+
lat,
|
|
287
|
+
lon,
|
|
288
|
+
dist,
|
|
289
|
+
pgv,
|
|
290
|
+
max_dist=args.max_dist,
|
|
291
|
+
n_max=args.n_max,
|
|
292
|
+
n_lat=args.n_lat,
|
|
293
|
+
n_lon=args.n_lon,
|
|
294
|
+
)
|
|
295
|
+
out_dir = args.out_dir if args.out_dir is not None else Path(event.id)
|
|
296
|
+
save_summary_plot(
|
|
297
|
+
lat,
|
|
298
|
+
lon,
|
|
299
|
+
idx,
|
|
300
|
+
id_selected,
|
|
301
|
+
lat_bks,
|
|
302
|
+
lon_bks,
|
|
303
|
+
event,
|
|
304
|
+
args.event_id,
|
|
305
|
+
out_dir,
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
write_sac_files(sc, passing_indices, id_selected, out_dir)
|
|
309
|
+
print(f"Wrote {len(id_selected)} stations to {out_dir}/")
|
|
310
|
+
|
|
311
|
+
write_supp_sac_files(sc, args.supp_stations, out_dir / "supp")
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
if __name__ == "__main__":
|
|
315
|
+
main()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Module for the StationStream
|
|
1
|
+
"""Module for the StationStream class."""
|
|
2
2
|
|
|
3
3
|
# stdlib imports
|
|
4
4
|
import logging
|
|
@@ -225,7 +225,9 @@ class StationStream(Stream):
|
|
|
225
225
|
all_codes = []
|
|
226
226
|
for tr in self:
|
|
227
227
|
stats = tr.stats
|
|
228
|
-
all_codes.append(
|
|
228
|
+
all_codes.append(
|
|
229
|
+
f"{stats.network}.{stats.station}.{stats.location}.{stats.channel}"
|
|
230
|
+
)
|
|
229
231
|
if len(set(all_codes)) != len(all_codes):
|
|
230
232
|
for tr in self:
|
|
231
233
|
tr.fail("Nonunique channel code in StationStream.")
|
|
@@ -236,40 +238,50 @@ class StationStream(Stream):
|
|
|
236
238
|
use_array = hasattr(self, "use_array") and self.use_array
|
|
237
239
|
stats = self[0].stats
|
|
238
240
|
if use_array:
|
|
239
|
-
id_str = ".".join(
|
|
240
|
-
|
|
241
|
-
stats.station,
|
|
242
|
-
stats.location,
|
|
243
|
-
stats.channel,
|
|
244
|
-
])
|
|
245
|
-
else:
|
|
246
|
-
id_str = ".".join([
|
|
247
|
-
stats.network,
|
|
248
|
-
stats.station,
|
|
249
|
-
stats.location,
|
|
250
|
-
stats.channel[0:2],
|
|
251
|
-
])
|
|
252
|
-
|
|
253
|
-
# Check that the id would be the same for all traces
|
|
254
|
-
for tr in self: # Use self to avoid creating temporary object
|
|
255
|
-
stats = tr.stats
|
|
256
|
-
if use_array:
|
|
257
|
-
test_str = ".".join([
|
|
241
|
+
id_str = ".".join(
|
|
242
|
+
[
|
|
258
243
|
stats.network,
|
|
259
244
|
stats.station,
|
|
260
245
|
stats.location,
|
|
261
246
|
stats.channel,
|
|
262
|
-
]
|
|
263
|
-
|
|
264
|
-
|
|
247
|
+
]
|
|
248
|
+
)
|
|
249
|
+
else:
|
|
250
|
+
id_str = ".".join(
|
|
251
|
+
[
|
|
265
252
|
stats.network,
|
|
266
253
|
stats.station,
|
|
267
254
|
stats.location,
|
|
268
255
|
stats.channel[0:2],
|
|
269
|
-
]
|
|
256
|
+
]
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
# Check that the id would be the same for all traces
|
|
260
|
+
for tr in self: # Use self to avoid creating temporary object
|
|
261
|
+
stats = tr.stats
|
|
262
|
+
if use_array:
|
|
263
|
+
test_str = ".".join(
|
|
264
|
+
[
|
|
265
|
+
stats.network,
|
|
266
|
+
stats.station,
|
|
267
|
+
stats.location,
|
|
268
|
+
stats.channel,
|
|
269
|
+
]
|
|
270
|
+
)
|
|
271
|
+
else:
|
|
272
|
+
test_str = ".".join(
|
|
273
|
+
[
|
|
274
|
+
stats.network,
|
|
275
|
+
stats.station,
|
|
276
|
+
stats.location,
|
|
277
|
+
stats.channel[0:2],
|
|
278
|
+
]
|
|
279
|
+
)
|
|
270
280
|
|
|
271
281
|
if id_str != test_str:
|
|
272
|
-
raise ValueError(
|
|
282
|
+
raise ValueError(
|
|
283
|
+
f"Inconsistent stream IDs {id_str} and {test_str} for different traces."
|
|
284
|
+
)
|
|
273
285
|
self.id = id_str
|
|
274
286
|
|
|
275
287
|
def get_id(self):
|
|
@@ -636,6 +636,7 @@ def are_duplicates(tr1, tr2, max_dist_tolerance):
|
|
|
636
636
|
Returns:
|
|
637
637
|
bool. True if traces are duplicates, False otherwise.
|
|
638
638
|
"""
|
|
639
|
+
# Need to simplify the use of 1/2 vs N/E
|
|
639
640
|
orientation_codes = set()
|
|
640
641
|
for tr in [tr1, tr2]:
|
|
641
642
|
if tr.stats.channel[2] in ["1", "N"]:
|
|
@@ -645,9 +646,14 @@ def are_duplicates(tr1, tr2, max_dist_tolerance):
|
|
|
645
646
|
else:
|
|
646
647
|
orientation_codes.add("Z")
|
|
647
648
|
|
|
649
|
+
# Replace "--" with "" due to inconsistent use despite meaning the same thing
|
|
650
|
+
loc_codes = [tr1.stats.location, tr2.stats.location]
|
|
651
|
+
loc_codes = set([c.replace("--", "") for c in loc_codes])
|
|
652
|
+
|
|
648
653
|
# First, check if the ids match (net.sta.loc.cha)
|
|
649
654
|
if tr1.id[:-1] == tr2.id[:-1] and len(orientation_codes) == 1:
|
|
650
655
|
return True
|
|
656
|
+
|
|
651
657
|
# If not matching IDs, check the station, instrument code, and distance
|
|
652
658
|
else:
|
|
653
659
|
distance = gps2dist_azimuth(
|
|
@@ -659,7 +665,7 @@ def are_duplicates(tr1, tr2, max_dist_tolerance):
|
|
|
659
665
|
if (
|
|
660
666
|
tr1.stats.station == tr2.stats.station
|
|
661
667
|
and tr1.stats.channel[:2] == tr2.stats.channel[:2]
|
|
662
|
-
and
|
|
668
|
+
and len(loc_codes) == 1
|
|
663
669
|
and len(orientation_codes) == 1
|
|
664
670
|
and distance < max_dist_tolerance
|
|
665
671
|
):
|
|
@@ -81,12 +81,24 @@ class Flatfile(object):
|
|
|
81
81
|
|
|
82
82
|
wmc = WaveformMetricCollection.from_workspace(self.workspace, self.label)
|
|
83
83
|
smc = StationMetricCollection.from_workspace(self.workspace)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
|
|
85
|
+
# Use dictionary to ensure each waveform metric has associated station metric
|
|
86
|
+
sm_dict = {}
|
|
87
|
+
for sm_path, sm in zip(smc.stream_paths, smc.station_metrics):
|
|
88
|
+
net_sta = ".".join(sm_path.split(".")[:3])
|
|
89
|
+
sm_dict[net_sta] = sm
|
|
90
|
+
|
|
91
|
+
for wml, stream_meta in zip(wmc.waveform_metrics, wmc.stream_metadata):
|
|
87
92
|
if not wml.metric_list:
|
|
88
93
|
continue
|
|
89
94
|
|
|
95
|
+
tr_met = stream_meta[0]
|
|
96
|
+
sta_id = f"{tr_met['network']}.{tr_met['station']}.{tr_met['location']}"
|
|
97
|
+
station_metrics = sm_dict.get(sta_id)
|
|
98
|
+
if station_metrics is None:
|
|
99
|
+
logging.warning("No station metrics found for %s; skipping.", sta_id)
|
|
100
|
+
continue
|
|
101
|
+
|
|
90
102
|
self._station_metrics = station_metrics
|
|
91
103
|
passed_traces = [tr_met for tr_met in stream_meta if tr_met["passed"]]
|
|
92
104
|
n_total = len(stream_meta)
|
|
@@ -177,6 +189,9 @@ class Flatfile(object):
|
|
|
177
189
|
"StationElevation": trace_meta["elevation"],
|
|
178
190
|
"SamplingRate": trace_meta["sampling_rate"],
|
|
179
191
|
"SourceFile": source_file,
|
|
192
|
+
"CountMean": trace_meta.get("count_mean", None),
|
|
193
|
+
"CountMin": trace_meta.get("count_min", None),
|
|
194
|
+
"CountMax": trace_meta.get("count_max", None),
|
|
180
195
|
}
|
|
181
196
|
|
|
182
197
|
def get_sta_dict(self):
|
|
@@ -66,6 +66,9 @@ FLATFILE_COLUMNS = {
|
|
|
66
66
|
"ZLowpass": "Vertical channel lowpass frequency (Hz)",
|
|
67
67
|
"ZHighpass": "Vertical channel highpass frequency (Hz)",
|
|
68
68
|
"SourceFile": "Source file",
|
|
69
|
+
"CountMean": "Mean of raw counts (if available)",
|
|
70
|
+
"CountMin": "Minimum of raw counts (if available)",
|
|
71
|
+
"CountMax": "Maximum of raw counts (if available)",
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
FLATFILE_IMT_COLUMNS = {
|
|
@@ -148,6 +148,10 @@ class CESMDFetcher(DataFetcher):
|
|
|
148
148
|
raise Exception(fmt)
|
|
149
149
|
|
|
150
150
|
if email == "EMAIL":
|
|
151
|
+
logging.warning(
|
|
152
|
+
"CESMDFetcher: email is still the placeholder 'EMAIL'; "
|
|
153
|
+
"CESMD will be skipped."
|
|
154
|
+
)
|
|
151
155
|
fmt = (
|
|
152
156
|
"Email address is required to retrieve CESMD\n"
|
|
153
157
|
"data. This tool can download data from the CESMD\n"
|
|
@@ -197,6 +201,13 @@ class CESMDFetcher(DataFetcher):
|
|
|
197
201
|
- depth Event depth
|
|
198
202
|
- mag Event magnitude
|
|
199
203
|
"""
|
|
204
|
+
logging.info(
|
|
205
|
+
"CESMDFetcher: querying metadata (lat=%s, lon=%s, time=%s, "
|
|
206
|
+
"eq_radius=%s km, eq_dt=%s s, station_radius=%s km, "
|
|
207
|
+
"station_type=%s)",
|
|
208
|
+
self.lat, self.lon, self.time, self.radius, self.dt,
|
|
209
|
+
self.station_radius, self.station_type,
|
|
210
|
+
)
|
|
200
211
|
try:
|
|
201
212
|
metadata = get_metadata(
|
|
202
213
|
eqlat=self.lat,
|
|
@@ -208,7 +219,9 @@ class CESMDFetcher(DataFetcher):
|
|
|
208
219
|
eqradius=self.radius, # km
|
|
209
220
|
station_radius=self.station_radius,
|
|
210
221
|
)
|
|
211
|
-
except BaseException:
|
|
222
|
+
except BaseException as ex:
|
|
223
|
+
logging.warning("CESMDFetcher: metadata query failed: %r", ex)
|
|
224
|
+
logging.debug("CESMDFetcher metadata traceback:", exc_info=True)
|
|
212
225
|
return []
|
|
213
226
|
|
|
214
227
|
tmp_events = metadata["results"]["events"]
|
|
@@ -886,7 +886,7 @@ class CosmosWriter(object):
|
|
|
886
886
|
elif self.volume == Volume.SPECTRA:
|
|
887
887
|
extension = "v3"
|
|
888
888
|
self.wmc = WaveformMetricCollection.from_workspace(
|
|
889
|
-
self._workspace,
|
|
889
|
+
self._workspace, self._label
|
|
890
890
|
)
|
|
891
891
|
for station_id in station_list:
|
|
892
892
|
streams = self._workspace.get_streams(
|
|
@@ -1042,11 +1042,11 @@ class CosmosWriter(object):
|
|
|
1042
1042
|
return (files, nevents, nstreams, ntraces)
|
|
1043
1043
|
|
|
1044
1044
|
def _write_spectra(self):
|
|
1045
|
-
|
|
1045
|
+
mconf = self._workspace.config["metrics"]
|
|
1046
|
+
damping_values = mconf["type_parameters"]["sa"]["damping"]
|
|
1047
|
+
self.periods = mconf["type_parameters"]["sa"]["periods"]
|
|
1048
|
+
if self.trace_idx == 0 or not self._concatenate_channels:
|
|
1046
1049
|
self._write_data(self.cosmos_file, self.trace)
|
|
1047
|
-
mconf = self._workspace.config["metrics"]
|
|
1048
|
-
damping_values = mconf["type_parameters"]["sa"]["damping"]
|
|
1049
|
-
self.periods = mconf["type_parameters"]["sa"]["periods"]
|
|
1050
1050
|
self.cosmos_file.write(
|
|
1051
1051
|
f"{len(damping_values)} damping values for which spectra are "
|
|
1052
1052
|
f"computed:{damping_values}\n"
|
|
@@ -5,14 +5,14 @@ import logging
|
|
|
5
5
|
import pathlib
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
|
+
from gmprocess.io.dynamic_search_parameters import SearchParameters
|
|
9
|
+
from gmprocess.io.utils import _walk
|
|
10
|
+
from gmprocess.utils.config import get_config
|
|
8
11
|
|
|
9
12
|
from obspy.geodetics import kilometers2degrees
|
|
10
13
|
|
|
11
14
|
# local imports
|
|
12
15
|
from .fetcher import DataFetcher
|
|
13
|
-
from gmprocess.utils.config import get_config
|
|
14
|
-
from gmprocess.io.utils import _walk
|
|
15
|
-
from gmprocess.io.dynamic_search_parameters import SearchParameters
|
|
16
16
|
|
|
17
17
|
FETCHER_DIRS = [
|
|
18
18
|
"cosmos",
|
|
@@ -172,7 +172,9 @@ def find_fetchers(lat, lon):
|
|
|
172
172
|
fetcher_mod = cfile
|
|
173
173
|
break
|
|
174
174
|
idx = max(
|
|
175
|
-
loc
|
|
175
|
+
loc
|
|
176
|
+
for loc, val in enumerate(fetcher_mod.parts)
|
|
177
|
+
if val == "gmprocess"
|
|
176
178
|
)
|
|
177
179
|
mod_tuple = fetcher_mod.parts[idx:]
|
|
178
180
|
mod_name = ".".join(mod_tuple)
|