gea-program 0.5.0__tar.gz → 0.6.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.
- {gea_program-0.5.0 → gea_program-0.6.0}/PKG-INFO +70 -6
- {gea_program-0.5.0 → gea_program-0.6.0}/README.md +69 -5
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/__init__.py +3 -1
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/__main__.py +177 -5
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/acceptance_tests.py +344 -1
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/client_reports.py +100 -0
- gea_program-0.6.0/gea/help/seismic.md +13 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/helplib.py +1 -1
- gea_program-0.6.0/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +122 -0
- gea_program-0.6.0/gea/reference/IU_ANMO_10_BHZ_response.xml +188 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/seismic.py +175 -89
- gea_program-0.6.0/gea/seismic_array.py +592 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/seismic_detect.py +1 -1
- gea_program-0.6.0/gea/seismic_response.py +358 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/service.py +74 -1
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/web/app.html +54 -1
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/workspace.py +189 -1
- {gea_program-0.5.0 → gea_program-0.6.0}/gea_program.egg-info/PKG-INFO +70 -6
- {gea_program-0.5.0 → gea_program-0.6.0}/gea_program.egg-info/SOURCES.txt +4 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/pyproject.toml +1 -1
- gea_program-0.5.0/gea/help/seismic.md +0 -13
- {gea_program-0.5.0 → gea_program-0.6.0}/LICENSE +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/accuracy_statement.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/alarm_engine.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/bench.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/blind_harness.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/med_160_sapropels.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/certificates.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/cli.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/config_versioning.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/correlation.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/dashboard.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/deviation.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/doctor.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/downhole_engine.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/drift_monitor.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/earth_model.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/example_register_map.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/fat_sat.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/files.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/follower.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/forward_model.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/gamma.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/gauge_aging.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/gauge_specs.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/gravity_reference.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/TESTER_GUIDE.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/alarms.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/data-in.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/doctor.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/drift.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/files.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/instruments.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/notifications.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/patches.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/quality.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/site.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/start.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/transients.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/upkeep.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/help/well-tests.md +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/housekeeping.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/inverse_engine.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/jobs.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/live_ports.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/loadtest.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/matplotlib_demo.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/modbus.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/model_card.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/mqtt_port.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/notify.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/opcua_port.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/operator_app.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/patches.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/ports.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/profile_catalog.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/project.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/qt6_downhole_app.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/reconciler.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/reference/libmseed_steim.provenance.json +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/rock_inventory.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/sample_record.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/sample_well_profile.csv +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/sbom.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/segy.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/sensor_swap.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/service_life.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/shell.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/shut_in.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/sla_report.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/store_forward.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/strata_join.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/survey_cmd.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/survey_view.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/telemetry.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/tool_library.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/transient.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/well_assembler.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/well_test_validation.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/wits0.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea/witsml.py +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea_program.egg-info/dependency_links.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea_program.egg-info/entry_points.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea_program.egg-info/requires.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/gea_program.egg-info/top_level.txt +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/setup.cfg +0 -0
- {gea_program-0.5.0 → gea_program-0.6.0}/tests/test_acceptance.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gea-program
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: GEA-Program: downhole gauge monitoring - canonical measurement records, quality rules, drift evaluation with a re-fit change log, well-test validation, alarm management, model cards, store-and-forward, monthly SLA measurement, FAT/SAT protocols and a dashboard, generated from live objects in the client's reporting outline.
|
|
5
5
|
Author: Daniel T. Murphy
|
|
6
6
|
License: MPL-2.0
|
|
@@ -98,8 +98,19 @@ reaches a client document. Nothing unmeasured is ever reported as met.
|
|
|
98
98
|
lines above the local floor out, and the detectability test: one station's
|
|
99
99
|
record against a list of known rigs with positions and working windows,
|
|
100
100
|
verdict per rig, the detection radius bracketed between the farthest rig
|
|
101
|
-
heard and the nearest not heard. The
|
|
102
|
-
|
|
101
|
+
heard and the nearest not heard. The instrument response (`seismic_response.py`):
|
|
102
|
+
the station's StationXML read into its stages, evaluated as evalresp does,
|
|
103
|
+
removed with a water level - counts to m/s, m or m/s^2. The decoder is proven
|
|
104
|
+
against libmseed on a corpus of real-station files; the response against
|
|
105
|
+
evalresp on a real IRIS channel. The array step (`seismic_array.py`):
|
|
106
|
+
beamforming over a slowness grid with the array response function's width
|
|
107
|
+
beside every bearing, the crossing of bearings from several arrays with its
|
|
108
|
+
ellipse, location from lags with the velocity named as an input, and the
|
|
109
|
+
array's detectability test - did it point at each known rig. On a site the
|
|
110
|
+
leg lives on the dashboard: a Seismic page where a station or an array is
|
|
111
|
+
added by upload with its rigs list and station file, refreshed as a job,
|
|
112
|
+
and read - spectrum, lines, verdicts, bearing - with its Seismic Station
|
|
113
|
+
Report under Reports. See *The second leg*.
|
|
103
114
|
|
|
104
115
|
## Quick start
|
|
105
116
|
|
|
@@ -111,7 +122,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
|
|
|
111
122
|
gea client-report --report accuracy --out client_report
|
|
112
123
|
gea model-cards --out model_cards
|
|
113
124
|
gea sbom --out sbom
|
|
114
|
-
gea accept # the product gate (
|
|
125
|
+
gea accept # the product gate (258 checks)
|
|
115
126
|
gea help drift # the help library, by the job (15 pages; the same text is on every dashboard page)
|
|
116
127
|
gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
|
|
117
128
|
gea gui # the desktop window (pip install "gea-program[desktop]")
|
|
@@ -309,7 +320,60 @@ produces the standard spectral products: the Welch PSD, a spectrogram, and
|
|
|
309
320
|
the lines that persist above a running-median floor in the band where rig
|
|
310
321
|
machinery sits (1-50 Hz by default). The decoder is proven in the acceptance
|
|
311
322
|
suite against records written by libmseed, the format's reference
|
|
312
|
-
implementation (`gea/reference/`).
|
|
323
|
+
implementation (`gea/reference/`), and `tools/seismic_reader_check.py` runs it
|
|
324
|
+
against libmseed on about ninety real-station files of every encoding and
|
|
325
|
+
byte order (the obspy test corpus, fetched with pip, never redistributed):
|
|
326
|
+
every time-series file sample-exact.
|
|
327
|
+
|
|
328
|
+
Physical units come from the station's own response file. `gea seismic
|
|
329
|
+
--action remove-response --stationxml station.xml` reads the FDSN StationXML
|
|
330
|
+
the archives serve beside the data (`fetch --with-response` fetches it),
|
|
331
|
+
builds the response from its stages - the poles and zeros of the sensor, the
|
|
332
|
+
gain of each stage, the FIR and IIR coefficients of the digitizer with their
|
|
333
|
+
delay corrections - the way evalresp builds it, and removes it in the
|
|
334
|
+
frequency domain with a water level and a pre-filter, giving velocity,
|
|
335
|
+
displacement or acceleration in SI units. The acceptance suite holds the
|
|
336
|
+
evaluation to evalresp's numbers on a real IRIS channel (IU.ANMO.10.BHZ,
|
|
337
|
+
`gea/reference/`) to one part in a hundred thousand. A station file whose
|
|
338
|
+
stages disagree with their own declared sensitivity, a polynomial stage, a
|
|
339
|
+
channel the file does not cover: refused with the reason, never patched, and
|
|
340
|
+
the record stays in counts, labelled.
|
|
341
|
+
|
|
342
|
+
One station detects; an array gives a direction. `gea seismic --action beam`
|
|
343
|
+
takes three or more sensors' records with their positions and returns the
|
|
344
|
+
back-azimuth and slowness the band's energy crossed the array with, by
|
|
345
|
+
frequency-domain beamforming over a slowness grid (the conventional Bartlett
|
|
346
|
+
beam, or Capon), refined around its maximum - and, beside the bearing, the
|
|
347
|
+
array response function's half-power width, which is the resolution the
|
|
348
|
+
geometry allows at that band, and whether the geometry has aliasing lobes
|
|
349
|
+
there, so a lone peak is not mistaken for a source. `--action array-detect`
|
|
350
|
+
is the array's form of the detectability test: for each rig on the
|
|
351
|
+
ground-truth list, in the windows it worked alone, did the array point at it
|
|
352
|
+
within its own tolerance (POINTED, NOT_POINTED, INCOHERENT). `--action
|
|
353
|
+
locate` crosses the bearings of two or more arrays, weighted by their
|
|
354
|
+
uncertainties, and returns the point with its 1-sigma ellipse, the crossing
|
|
355
|
+
angle and the residual of each bearing; a location from station-pair lags is
|
|
356
|
+
there too, with the medium velocity it needs named as the input it is. On
|
|
357
|
+
the labelled synthetic scene (`--action array-selftest`) a 1.2 km,
|
|
358
|
+
nine-sensor array points at rigs from 6 to 45 km within 0.3 degrees against
|
|
359
|
+
a 7-degree tolerance, and three arrays' bearings cross within a kilometre of
|
|
360
|
+
the rig. What none of it claims: a position from one array, a bearing to a
|
|
361
|
+
source nearer than five apertures, a direction finer than the array response
|
|
362
|
+
function, or a velocity that was not measured.
|
|
363
|
+
|
|
364
|
+
On a site the leg is a page. Seismic, beside Wells: a station (one record)
|
|
365
|
+
or an array (one record per sensor and a sensors CSV) is added by upload with
|
|
366
|
+
its position, its rigs list and, when there is one, its StationXML, and lives
|
|
367
|
+
under `seismic/<station>/` in the workspace with its files copied in verbatim
|
|
368
|
+
and hashed. Refresh - a button, or `gea workspace --action refresh-seismic`,
|
|
369
|
+
and like every other action a job with its log - reads the record, removes
|
|
370
|
+
the response when the station file is there, writes the spectrum, the
|
|
371
|
+
persistent lines, the detectability verdicts and, for an array, the beam and
|
|
372
|
+
the array verdicts under `reports/seismic/<station>/`, and the Seismic
|
|
373
|
+
Station Report beside them; the station page draws the spectrum and shows
|
|
374
|
+
the tables with the limits printed under each. The home page counts the
|
|
375
|
+
stations and the listed rigs heard. The sample report is in
|
|
376
|
+
`docs/report_samples/`.
|
|
313
377
|
|
|
314
378
|
The first number is the detectability test (`--action detect`): one station's
|
|
315
379
|
continuous record, the station's position, and a CSV of known rigs - position
|
|
@@ -377,7 +441,7 @@ attaches the zips to the GitHub release of that tag.
|
|
|
377
441
|
gea/ the package: engines, record layer, reports, monitor, dashboard, cli, shell, acceptance suite,
|
|
378
442
|
workspace, jobs, service, patches and web/app.html (the served dashboard)
|
|
379
443
|
gea/catalog/ 52 public archive entries, each with a provenance file
|
|
380
|
-
gea/reference/ miniSEED records written by libmseed, with
|
|
444
|
+
gea/reference/ miniSEED records written by libmseed and an IRIS StationXML with evalresp's numbers, with provenance: the independent references
|
|
381
445
|
docs/report_samples/ one rendered example of every client report, from this build (tools/render_report_samples.py; SAMPLES.md names each command)
|
|
382
446
|
docs/ TESTER_GUIDE.md, REQUIREMENTS_MATRIX.md (the scope-of-work mirror that shaped the reports), examples/ (port configs),
|
|
383
447
|
SESSION_LOG.md (the working record, session by session),
|
|
@@ -59,8 +59,19 @@ reaches a client document. Nothing unmeasured is ever reported as met.
|
|
|
59
59
|
lines above the local floor out, and the detectability test: one station's
|
|
60
60
|
record against a list of known rigs with positions and working windows,
|
|
61
61
|
verdict per rig, the detection radius bracketed between the farthest rig
|
|
62
|
-
heard and the nearest not heard. The
|
|
63
|
-
|
|
62
|
+
heard and the nearest not heard. The instrument response (`seismic_response.py`):
|
|
63
|
+
the station's StationXML read into its stages, evaluated as evalresp does,
|
|
64
|
+
removed with a water level - counts to m/s, m or m/s^2. The decoder is proven
|
|
65
|
+
against libmseed on a corpus of real-station files; the response against
|
|
66
|
+
evalresp on a real IRIS channel. The array step (`seismic_array.py`):
|
|
67
|
+
beamforming over a slowness grid with the array response function's width
|
|
68
|
+
beside every bearing, the crossing of bearings from several arrays with its
|
|
69
|
+
ellipse, location from lags with the velocity named as an input, and the
|
|
70
|
+
array's detectability test - did it point at each known rig. On a site the
|
|
71
|
+
leg lives on the dashboard: a Seismic page where a station or an array is
|
|
72
|
+
added by upload with its rigs list and station file, refreshed as a job,
|
|
73
|
+
and read - spectrum, lines, verdicts, bearing - with its Seismic Station
|
|
74
|
+
Report under Reports. See *The second leg*.
|
|
64
75
|
|
|
65
76
|
## Quick start
|
|
66
77
|
|
|
@@ -72,7 +83,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
|
|
|
72
83
|
gea client-report --report accuracy --out client_report
|
|
73
84
|
gea model-cards --out model_cards
|
|
74
85
|
gea sbom --out sbom
|
|
75
|
-
gea accept # the product gate (
|
|
86
|
+
gea accept # the product gate (258 checks)
|
|
76
87
|
gea help drift # the help library, by the job (15 pages; the same text is on every dashboard page)
|
|
77
88
|
gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
|
|
78
89
|
gea gui # the desktop window (pip install "gea-program[desktop]")
|
|
@@ -270,7 +281,60 @@ produces the standard spectral products: the Welch PSD, a spectrogram, and
|
|
|
270
281
|
the lines that persist above a running-median floor in the band where rig
|
|
271
282
|
machinery sits (1-50 Hz by default). The decoder is proven in the acceptance
|
|
272
283
|
suite against records written by libmseed, the format's reference
|
|
273
|
-
implementation (`gea/reference/`).
|
|
284
|
+
implementation (`gea/reference/`), and `tools/seismic_reader_check.py` runs it
|
|
285
|
+
against libmseed on about ninety real-station files of every encoding and
|
|
286
|
+
byte order (the obspy test corpus, fetched with pip, never redistributed):
|
|
287
|
+
every time-series file sample-exact.
|
|
288
|
+
|
|
289
|
+
Physical units come from the station's own response file. `gea seismic
|
|
290
|
+
--action remove-response --stationxml station.xml` reads the FDSN StationXML
|
|
291
|
+
the archives serve beside the data (`fetch --with-response` fetches it),
|
|
292
|
+
builds the response from its stages - the poles and zeros of the sensor, the
|
|
293
|
+
gain of each stage, the FIR and IIR coefficients of the digitizer with their
|
|
294
|
+
delay corrections - the way evalresp builds it, and removes it in the
|
|
295
|
+
frequency domain with a water level and a pre-filter, giving velocity,
|
|
296
|
+
displacement or acceleration in SI units. The acceptance suite holds the
|
|
297
|
+
evaluation to evalresp's numbers on a real IRIS channel (IU.ANMO.10.BHZ,
|
|
298
|
+
`gea/reference/`) to one part in a hundred thousand. A station file whose
|
|
299
|
+
stages disagree with their own declared sensitivity, a polynomial stage, a
|
|
300
|
+
channel the file does not cover: refused with the reason, never patched, and
|
|
301
|
+
the record stays in counts, labelled.
|
|
302
|
+
|
|
303
|
+
One station detects; an array gives a direction. `gea seismic --action beam`
|
|
304
|
+
takes three or more sensors' records with their positions and returns the
|
|
305
|
+
back-azimuth and slowness the band's energy crossed the array with, by
|
|
306
|
+
frequency-domain beamforming over a slowness grid (the conventional Bartlett
|
|
307
|
+
beam, or Capon), refined around its maximum - and, beside the bearing, the
|
|
308
|
+
array response function's half-power width, which is the resolution the
|
|
309
|
+
geometry allows at that band, and whether the geometry has aliasing lobes
|
|
310
|
+
there, so a lone peak is not mistaken for a source. `--action array-detect`
|
|
311
|
+
is the array's form of the detectability test: for each rig on the
|
|
312
|
+
ground-truth list, in the windows it worked alone, did the array point at it
|
|
313
|
+
within its own tolerance (POINTED, NOT_POINTED, INCOHERENT). `--action
|
|
314
|
+
locate` crosses the bearings of two or more arrays, weighted by their
|
|
315
|
+
uncertainties, and returns the point with its 1-sigma ellipse, the crossing
|
|
316
|
+
angle and the residual of each bearing; a location from station-pair lags is
|
|
317
|
+
there too, with the medium velocity it needs named as the input it is. On
|
|
318
|
+
the labelled synthetic scene (`--action array-selftest`) a 1.2 km,
|
|
319
|
+
nine-sensor array points at rigs from 6 to 45 km within 0.3 degrees against
|
|
320
|
+
a 7-degree tolerance, and three arrays' bearings cross within a kilometre of
|
|
321
|
+
the rig. What none of it claims: a position from one array, a bearing to a
|
|
322
|
+
source nearer than five apertures, a direction finer than the array response
|
|
323
|
+
function, or a velocity that was not measured.
|
|
324
|
+
|
|
325
|
+
On a site the leg is a page. Seismic, beside Wells: a station (one record)
|
|
326
|
+
or an array (one record per sensor and a sensors CSV) is added by upload with
|
|
327
|
+
its position, its rigs list and, when there is one, its StationXML, and lives
|
|
328
|
+
under `seismic/<station>/` in the workspace with its files copied in verbatim
|
|
329
|
+
and hashed. Refresh - a button, or `gea workspace --action refresh-seismic`,
|
|
330
|
+
and like every other action a job with its log - reads the record, removes
|
|
331
|
+
the response when the station file is there, writes the spectrum, the
|
|
332
|
+
persistent lines, the detectability verdicts and, for an array, the beam and
|
|
333
|
+
the array verdicts under `reports/seismic/<station>/`, and the Seismic
|
|
334
|
+
Station Report beside them; the station page draws the spectrum and shows
|
|
335
|
+
the tables with the limits printed under each. The home page counts the
|
|
336
|
+
stations and the listed rigs heard. The sample report is in
|
|
337
|
+
`docs/report_samples/`.
|
|
274
338
|
|
|
275
339
|
The first number is the detectability test (`--action detect`): one station's
|
|
276
340
|
continuous record, the station's position, and a CSV of known rigs - position
|
|
@@ -338,7 +402,7 @@ attaches the zips to the GitHub release of that tag.
|
|
|
338
402
|
gea/ the package: engines, record layer, reports, monitor, dashboard, cli, shell, acceptance suite,
|
|
339
403
|
workspace, jobs, service, patches and web/app.html (the served dashboard)
|
|
340
404
|
gea/catalog/ 52 public archive entries, each with a provenance file
|
|
341
|
-
gea/reference/ miniSEED records written by libmseed, with
|
|
405
|
+
gea/reference/ miniSEED records written by libmseed and an IRIS StationXML with evalresp's numbers, with provenance: the independent references
|
|
342
406
|
docs/report_samples/ one rendered example of every client report, from this build (tools/render_report_samples.py; SAMPLES.md names each command)
|
|
343
407
|
docs/ TESTER_GUIDE.md, REQUIREMENTS_MATRIX.md (the scope-of-work mirror that shaped the reports), examples/ (port configs),
|
|
344
408
|
SESSION_LOG.md (the working record, session by session),
|
|
@@ -100,6 +100,8 @@ from .seismic import (
|
|
|
100
100
|
welch_psd, spectrogram, persistent_lines, band_power,
|
|
101
101
|
)
|
|
102
102
|
from .seismic_detect import Source as SeismicSource, detectability_test, load_sources_csv, haversine_km, DRILLING_BAND_HZ
|
|
103
|
+
from .seismic_response import read_stationxml, remove_response, transfer as response_transfer, fdsn_stationxml
|
|
104
|
+
from .seismic_array import Sensor as SeismicSensor, load_sensors_csv, beam as array_beam, array_detectability, intersect_backazimuths, locate_from_lags
|
|
103
105
|
from .bench import (
|
|
104
106
|
bench_analysis, bench_selftest,
|
|
105
107
|
)
|
|
@@ -120,7 +122,7 @@ from .profile_catalog import (
|
|
|
120
122
|
read_pangaea_txt,
|
|
121
123
|
)
|
|
122
124
|
|
|
123
|
-
__version__ = "0.
|
|
125
|
+
__version__ = "0.6.0"
|
|
124
126
|
__all__ = [
|
|
125
127
|
"aging_rate", "rate_psi_yr", "accuracy_psi",
|
|
126
128
|
"Sensor", "SimulatorConfig", "DownholeEngine",
|
|
@@ -279,7 +279,16 @@ def main(argv=None) -> int:
|
|
|
279
279
|
p_ws = sub.add_parser("workspace", help="the client site folder: init, add wells (file | catalogue | live), list, migrate a --out folder, refresh the dashboard, audit log")
|
|
280
280
|
p_ws.add_argument("--path", type=str, required=True, help="the workspace folder")
|
|
281
281
|
p_ws.add_argument("--action", type=str, default="list",
|
|
282
|
-
choices=["init", "add-file", "add-catalog", "add-live", "remove", "list", "migrate", "refresh", "audit"
|
|
282
|
+
choices=["init", "add-file", "add-catalog", "add-live", "remove", "list", "migrate", "refresh", "audit",
|
|
283
|
+
"add-seismic", "refresh-seismic", "remove-seismic"])
|
|
284
|
+
p_ws.add_argument("--files", type=str, nargs="+", default=None, help="add-seismic: the station's record (or one record per sensor of an array, in the sensors CSV's order)")
|
|
285
|
+
p_ws.add_argument("--lat", type=float, default=None, help="add-seismic: the station's latitude")
|
|
286
|
+
p_ws.add_argument("--lon", type=float, default=None, help="add-seismic: the station's longitude")
|
|
287
|
+
p_ws.add_argument("--stationxml", type=str, default=None, help="add-seismic: the station's FDSN StationXML (the response is removed at every refresh)")
|
|
288
|
+
p_ws.add_argument("--sensors", type=str, default=None, help="add-seismic: sensors CSV (sensor_id, lat, lon) - makes the station an array")
|
|
289
|
+
p_ws.add_argument("--sources", type=str, default=None, help="add-seismic: the rigs CSV (source_id, lat, lon, start_utc, end_utc[, kind, note])")
|
|
290
|
+
p_ws.add_argument("--band", type=float, nargs=2, default=None, metavar=("LO", "HI"), help="add-seismic: the band, Hz (default 1 50)")
|
|
291
|
+
p_ws.add_argument("--station", type=str, default=None, help="refresh-seismic / remove-seismic: the station id")
|
|
283
292
|
p_ws.add_argument("--name", type=str, default=None, help="init: site name; add-*: display name")
|
|
284
293
|
p_ws.add_argument("--file", type=str, default=None, help="add-file: the client's data file; add-live: the port configuration JSON")
|
|
285
294
|
p_ws.add_argument("--entry", type=str, default=None, help="add-catalog: catalogue entry")
|
|
@@ -347,7 +356,19 @@ def main(argv=None) -> int:
|
|
|
347
356
|
p_nt.add_argument("--actor", type=str, default="cli")
|
|
348
357
|
|
|
349
358
|
p_se = sub.add_parser("seismic", help="the second leg's ingest: miniSEED/SAC in, spectra and persistent lines out, an FDSN fetch, and the detectability test against known rigs")
|
|
350
|
-
p_se.add_argument("--action", choices=["info", "spectrum", "lines", "fetch", "stations", "detect", "selftest", "convert"
|
|
359
|
+
p_se.add_argument("--action", choices=["info", "spectrum", "lines", "fetch", "stations", "detect", "selftest", "convert", "response", "remove-response",
|
|
360
|
+
"beam", "array-detect", "locate", "array-selftest"], default="info")
|
|
361
|
+
p_se.add_argument("--files", type=str, nargs="+", default=None, help="beam/array-detect: one record per sensor, in the order of --sensors")
|
|
362
|
+
p_se.add_argument("--sensors", type=str, default=None, help="beam/array-detect: CSV of the array's sensors (sensor_id, lat, lon[, elevation_m])")
|
|
363
|
+
p_se.add_argument("--bearings", type=str, default=None, help="locate: CSV of arrays' bearings (lat, lon, back_azimuth_deg, sigma_deg)")
|
|
364
|
+
p_se.add_argument("--method", type=str, default="bartlett", choices=["bartlett", "capon"], help="beam: the beamformer")
|
|
365
|
+
p_se.add_argument("--seg", type=float, default=10.0, help="beam: Welch segment length, s (default 10)")
|
|
366
|
+
p_se.add_argument("--smax", type=float, default=3.0, help="beam: slowness grid half-width, s/km (default 3: apparent velocities down to 0.33 km/s)")
|
|
367
|
+
p_se.add_argument("--stationxml", type=str, default=None, help="the station's FDSN StationXML (level=response); with spectrum/lines/detect the response is removed first")
|
|
368
|
+
p_se.add_argument("--output", type=str, default="VEL", choices=["VEL", "DISP", "ACC"], help="ground-motion unit after response removal (default VEL, m/s)")
|
|
369
|
+
p_se.add_argument("--water-level", type=float, default=60.0, help="water level for the deconvolution, dB (default 60)")
|
|
370
|
+
p_se.add_argument("--pre-filt", type=float, nargs=4, default=None, metavar=("F1", "F2", "F3", "F4"), help="cosine band window applied before the deconvolution, Hz")
|
|
371
|
+
p_se.add_argument("--with-response", action="store_true", help="fetch: also fetch the StationXML with responses, beside the record")
|
|
351
372
|
p_se.add_argument("--file", type=str, default=None, help="a miniSEED or SAC file (decided by content)")
|
|
352
373
|
p_se.add_argument("--trace", type=int, default=0, help="which trace of the file when it holds several (default the first)")
|
|
353
374
|
p_se.add_argument("--band", type=float, nargs=2, default=[1.0, 50.0], metavar=("LO", "HI"), help="frequency band, Hz (default 1 50: rig machinery)")
|
|
@@ -720,7 +741,7 @@ def main(argv=None) -> int:
|
|
|
720
741
|
from . import seismic as S
|
|
721
742
|
from . import seismic_detect as D
|
|
722
743
|
|
|
723
|
-
def _trace():
|
|
744
|
+
def _trace(apply_response=True):
|
|
724
745
|
if not a.file:
|
|
725
746
|
raise SystemExit("seismic: --file is needed for this action")
|
|
726
747
|
trs = S.read_any(a.file)
|
|
@@ -728,8 +749,133 @@ def main(argv=None) -> int:
|
|
|
728
749
|
raise SystemExit(f"seismic: {a.file} holds no samples")
|
|
729
750
|
if a.trace >= len(trs):
|
|
730
751
|
raise SystemExit(f"seismic: {a.file} holds {len(trs)} trace(s); --trace {a.trace} is out of range")
|
|
731
|
-
|
|
752
|
+
tr = trs[a.trace]
|
|
753
|
+
if a.stationxml and apply_response:
|
|
754
|
+
from . import seismic_response as R
|
|
755
|
+
try:
|
|
756
|
+
chan = R.select(R.read_stationxml(a.stationxml), tr)
|
|
757
|
+
tr, note = R.remove_response(tr, chan, a.output, a.water_level, tuple(a.pre_filt) if a.pre_filt else None)
|
|
758
|
+
except (LookupError, ValueError) as e:
|
|
759
|
+
raise SystemExit(f"seismic: response not removed - {e}")
|
|
760
|
+
print(f"seismic: response of {chan.id} removed ({chan.sensor or 'sensor unnamed'}); the record is now in {note['unit']}", file=sys.stderr)
|
|
761
|
+
return trs, tr
|
|
732
762
|
band = (float(a.band[0]), float(a.band[1]))
|
|
763
|
+
if a.action == "array-selftest":
|
|
764
|
+
from . import seismic_array as AR
|
|
765
|
+
r = AR.selftest()
|
|
766
|
+
if a.json:
|
|
767
|
+
print(_json.dumps({k: v for k, v in r.items() if k != "detectability"} | {"detectability": {kk: vv for kk, vv in r["detectability"].items()}}, indent=1, default=str))
|
|
768
|
+
else:
|
|
769
|
+
print(f"seismic array-selftest: {r['status']} ok={r['ok']}")
|
|
770
|
+
print(AR.report_text(r["detectability"]))
|
|
771
|
+
c = r["crossing"]
|
|
772
|
+
print(f" three arrays' bearings cross {c['miss_km']:.2f} km from the rig; 1-sigma ellipse {c['ellipse_1sigma']['major_km']} x {c['ellipse_1sigma']['minor_km']} km; "
|
|
773
|
+
f"crossing angle {c['crossing_angle_deg']} deg; in front of every array: {c['in_front_of_every_array']}")
|
|
774
|
+
return 0 if r["ok"] else 1
|
|
775
|
+
if a.action in ("beam", "array-detect"):
|
|
776
|
+
from . import seismic_array as AR
|
|
777
|
+
if not a.files or not a.sensors:
|
|
778
|
+
raise SystemExit(f"seismic {a.action} needs --files (one per sensor) and --sensors CSV")
|
|
779
|
+
sensors = AR.load_sensors_csv(a.sensors)
|
|
780
|
+
if len(a.files) != len(sensors):
|
|
781
|
+
raise SystemExit(f"seismic {a.action}: {len(a.files)} files for {len(sensors)} sensors")
|
|
782
|
+
trs = []
|
|
783
|
+
for f in a.files:
|
|
784
|
+
t = S.read_any(f)
|
|
785
|
+
if not t:
|
|
786
|
+
raise SystemExit(f"seismic: {f} holds no samples")
|
|
787
|
+
tr = t[0]
|
|
788
|
+
if a.start or a.end:
|
|
789
|
+
tr = tr.slice(S.parse_time(a.start) if a.start else tr.starttime, S.parse_time(a.end) if a.end else tr.endtime)
|
|
790
|
+
trs.append(tr)
|
|
791
|
+
if a.action == "beam":
|
|
792
|
+
b = AR.beam(trs, sensors, band, a.seg, a.smax, 61, a.method)
|
|
793
|
+
b = {k: v for k, v in b.items() if not k.startswith("_")}
|
|
794
|
+
if a.out:
|
|
795
|
+
with open(a.out, "w", encoding="utf-8") as fh:
|
|
796
|
+
_json.dump(b, fh, indent=1)
|
|
797
|
+
if a.json:
|
|
798
|
+
print(_json.dumps(b, indent=1))
|
|
799
|
+
else:
|
|
800
|
+
print(f"seismic beam: {b['n_sensors']} sensors, aperture {b['aperture_km']} km, {b['window']['start']} to {b['window']['end']}, band {band[0]:g}-{band[1]:g} Hz ({b['method']})")
|
|
801
|
+
print(f" back-azimuth {b['back_azimuth_deg']} deg +/- {b['resolution']['azimuth_half_width_deg']} (array response), slowness {b['slowness_s_km']} s/km "
|
|
802
|
+
f"(apparent velocity {b['apparent_velocity_km_s']} km/s), best-bin coherence {b['coherence_max_bin']} with {b['coherent_bins']} coherent bins"
|
|
803
|
+
+ (f" at {', '.join(f'{x:g}' for x in b['coherent_frequencies_hz'][:6])} Hz" if b['coherent_frequencies_hz'] else ''))
|
|
804
|
+
if b["resolution"]["aliasing_lobes"]:
|
|
805
|
+
print(" the array response has aliasing lobes at this band: a lone peak may be a lobe of the geometry")
|
|
806
|
+
for pk in b["peaks"][1:4]:
|
|
807
|
+
print(f" also: {pk['back_azimuth_deg']} deg at {pk['slowness_s_km']} s/km (power {pk['power']})")
|
|
808
|
+
print(f" plane-wave limit: sources nearer than {b['plane_wave_limit_km']} km are not plane waves here")
|
|
809
|
+
print(" not a measurement: " + "; ".join(b["not_a_measurement"]))
|
|
810
|
+
return 0
|
|
811
|
+
if not a.sources:
|
|
812
|
+
raise SystemExit("seismic array-detect needs --sources CSV")
|
|
813
|
+
res = AR.array_detectability(trs, sensors, D.load_sources_csv(a.sources), band, a.win or 600.0, a.seg, a.smax, 61, a.method)
|
|
814
|
+
if a.out:
|
|
815
|
+
with open(a.out, "w", encoding="utf-8") as fh:
|
|
816
|
+
_json.dump(res, fh, indent=1, default=str)
|
|
817
|
+
if a.json:
|
|
818
|
+
print(_json.dumps(res, indent=1, default=str))
|
|
819
|
+
else:
|
|
820
|
+
print(AR.report_text(res))
|
|
821
|
+
return 0
|
|
822
|
+
if a.action == "locate":
|
|
823
|
+
from . import seismic_array as AR
|
|
824
|
+
import csv as _csv
|
|
825
|
+
if not a.bearings:
|
|
826
|
+
raise SystemExit("seismic locate needs --bearings CSV (lat, lon, back_azimuth_deg, sigma_deg)")
|
|
827
|
+
with open(a.bearings, newline="", encoding="utf-8") as fh:
|
|
828
|
+
rows = [{k.strip(): float(v) for k, v in r.items() if k} for r in _csv.DictReader(fh)]
|
|
829
|
+
c = AR.intersect_backazimuths(rows)
|
|
830
|
+
if a.out:
|
|
831
|
+
with open(a.out, "w", encoding="utf-8") as fh:
|
|
832
|
+
_json.dump(c, fh, indent=1)
|
|
833
|
+
if a.json:
|
|
834
|
+
print(_json.dumps(c, indent=1))
|
|
835
|
+
else:
|
|
836
|
+
e = c["ellipse_1sigma"]
|
|
837
|
+
print(f"seismic locate: {len(rows)} bearings cross at ({c['lat']:.5f}, {c['lon']:.5f}); 1-sigma ellipse {e['major_km']} x {e['minor_km']} km "
|
|
838
|
+
f"(major axis at {e['major_azimuth_deg']} deg); crossing angle {c['crossing_angle_deg']} deg; residuals {c['residual_deg']} deg; "
|
|
839
|
+
f"in front of every array: {c['in_front_of_every_array']}")
|
|
840
|
+
print(" not a measurement: " + "; ".join(c["not_a_measurement"]))
|
|
841
|
+
return 0
|
|
842
|
+
if a.action == "response":
|
|
843
|
+
from . import seismic_response as R
|
|
844
|
+
if not a.stationxml:
|
|
845
|
+
raise SystemExit("seismic response needs --stationxml")
|
|
846
|
+
chans = R.read_stationxml(a.stationxml)
|
|
847
|
+
if a.json:
|
|
848
|
+
print(_json.dumps([c.summary() for c in chans], indent=1))
|
|
849
|
+
else:
|
|
850
|
+
for c in chans:
|
|
851
|
+
sm = c.summary()
|
|
852
|
+
print(f"{c.id:18s} {sm['start'] or '..'} to {sm['end'] or '..'} ({sm['latitude']}, {sm['longitude']}) {sm['sample_rate_hz']} Hz "
|
|
853
|
+
f"{sm['sensor']} sensitivity {sm['sensitivity']} {sm['output_units']}/({sm['input_units']}) at {sm['sensitivity_frequency_hz']} Hz stages {', '.join(sm['stages'])}")
|
|
854
|
+
print(f"seismic: {len(chans)} channel(s) in {a.stationxml}")
|
|
855
|
+
return 0
|
|
856
|
+
if a.action == "remove-response":
|
|
857
|
+
from . import seismic_response as R
|
|
858
|
+
if not a.stationxml or not a.out:
|
|
859
|
+
raise SystemExit("seismic remove-response needs --stationxml and --out")
|
|
860
|
+
trs, _ = _trace(apply_response=False)
|
|
861
|
+
resp = R.read_stationxml(a.stationxml)
|
|
862
|
+
done, notes = [], []
|
|
863
|
+
for tr in trs:
|
|
864
|
+
try:
|
|
865
|
+
chan = R.select(resp, tr)
|
|
866
|
+
out_tr, note = R.remove_response(tr, chan, a.output, a.water_level, tuple(a.pre_filt) if a.pre_filt else None)
|
|
867
|
+
except (LookupError, ValueError) as e:
|
|
868
|
+
print(f" {tr.id}: left in counts - {e}", file=sys.stderr)
|
|
869
|
+
continue
|
|
870
|
+
done.append(out_tr)
|
|
871
|
+
notes.append({"id": tr.id, **note})
|
|
872
|
+
if not done:
|
|
873
|
+
raise SystemExit("seismic remove-response: no trace had a usable response")
|
|
874
|
+
S.write_mseed(done, a.out, "FLOAT64")
|
|
875
|
+
with open(a.out + ".units.json", "w", encoding="utf-8") as fh:
|
|
876
|
+
_json.dump({"unit": done[0].unit, "traces": notes}, fh, indent=1)
|
|
877
|
+
print(f"seismic: {len(done)} trace(s) in {done[0].unit} -> {a.out} (FLOAT64 miniSEED; the unit and the response record are in {a.out}.units.json)")
|
|
878
|
+
return 0
|
|
733
879
|
if a.action == "selftest":
|
|
734
880
|
r = D.selftest()
|
|
735
881
|
if a.json:
|
|
@@ -763,7 +909,7 @@ def main(argv=None) -> int:
|
|
|
763
909
|
m = (f >= band[0]) & (f <= band[1])
|
|
764
910
|
if a.out:
|
|
765
911
|
S.spectrum_csv(f[m], p[m], a.out, tr)
|
|
766
|
-
print(f"seismic: Welch PSD of {tr.id} ({tr.duration_s:.0f} s) in {band[0]:g}-{band[1]:g} Hz -> {a.out} [counts^2/Hz, response not removed]")
|
|
912
|
+
print(f"seismic: Welch PSD of {tr.id} ({tr.duration_s:.0f} s) in {band[0]:g}-{band[1]:g} Hz -> {a.out} [{'counts^2/Hz, response not removed' if tr.unit == 'counts' else '(' + tr.unit + ')^2/Hz, response removed'}]")
|
|
767
913
|
else:
|
|
768
914
|
top = sorted(zip(f[m], p[m]), key=lambda z: -z[1])[:10]
|
|
769
915
|
print(f"seismic: Welch PSD of {tr.id}, {int(m.sum())} bins in {band[0]:g}-{band[1]:g} Hz (df {f[1] - f[0]:.4f} Hz); the ten strongest bins:")
|
|
@@ -801,6 +947,11 @@ def main(argv=None) -> int:
|
|
|
801
947
|
raise SystemExit(f"seismic fetch needs --{' --'.join(miss)}")
|
|
802
948
|
rec = S.fdsn_fetch(a.base, a.network, a.station, a.channel, a.start, a.end, a.out, a.location)
|
|
803
949
|
print(f"seismic: {rec['bytes']} bytes -> {a.out} ({rec['unit']}); request written to {a.out}.request.json")
|
|
950
|
+
if a.with_response:
|
|
951
|
+
from . import seismic_response as R
|
|
952
|
+
xml_out = os.path.splitext(a.out)[0] + ".stationxml"
|
|
953
|
+
rx = R.fdsn_stationxml(a.base, a.network, a.station, a.channel, a.start, a.end, xml_out, a.location)
|
|
954
|
+
print(f"seismic: station file with responses -> {xml_out} ({', '.join(rx['channels']) or 'no channels'})")
|
|
804
955
|
return 0
|
|
805
956
|
if a.action == "detect":
|
|
806
957
|
_, tr = _trace()
|
|
@@ -935,6 +1086,27 @@ def main(argv=None) -> int:
|
|
|
935
1086
|
for row in ws.audit_log(limit=50):
|
|
936
1087
|
print(row["utc"], row["actor"], row["action"], _json.dumps(row["detail"]))
|
|
937
1088
|
return 0
|
|
1089
|
+
elif a.action == "add-seismic":
|
|
1090
|
+
if not (a.name and a.files):
|
|
1091
|
+
raise SystemExit("add-seismic needs --name and --files (one record, or one per sensor with --sensors)")
|
|
1092
|
+
st = ws.add_seismic_station(a.name, a.files, a.lat, a.lon, actor=a.actor, stationxml=a.stationxml, sensors_csv=a.sensors,
|
|
1093
|
+
sources_csv=a.sources, band=a.band)
|
|
1094
|
+
print("seismic station:", st["id"], f"({st['kind']}, {len(st['files'])} record(s))"); return 0
|
|
1095
|
+
elif a.action == "refresh-seismic":
|
|
1096
|
+
ids = [a.station] if a.station else [x["id"] for x in ws.seismic_stations()]
|
|
1097
|
+
if not ids:
|
|
1098
|
+
raise SystemExit("refresh-seismic: no seismic station in the workspace")
|
|
1099
|
+
for sid in ids:
|
|
1100
|
+
r = ws.refresh_seismic(sid, actor=a.actor)
|
|
1101
|
+
print(f"seismic {sid}: {r['records']} record(s), {r['hours']} h, {r['unit']}; {r['lines']} line(s)"
|
|
1102
|
+
+ (f"; detectability {r['detect_status']}: {r['detected']} of {r['n_sources']} detected - {r['radius']}" if r["detect_status"] else "; no detectability test (needs --sources and a position)")
|
|
1103
|
+
+ (f"; beam {r['beam_back_azimuth_deg']} deg, pointed at {r['pointed']}" if r["beam_back_azimuth_deg"] is not None else "")
|
|
1104
|
+
+ f"\n report: {r['report']}")
|
|
1105
|
+
return 0
|
|
1106
|
+
elif a.action == "remove-seismic":
|
|
1107
|
+
if not a.station:
|
|
1108
|
+
raise SystemExit("remove-seismic needs --station <id>")
|
|
1109
|
+
ws.remove_seismic_station(a.station, actor=a.actor); print("removed (folder kept):", a.station); return 0
|
|
938
1110
|
else:
|
|
939
1111
|
print(_json.dumps(ws.summary(), indent=1)); return 0
|
|
940
1112
|
print("well:", w["id"], f"({w['kind']})"); return 0
|