gea-program 0.13.0__tar.gz → 0.14.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.13.0/gea_program.egg-info → gea_program-0.14.0}/PKG-INFO +19 -2
- {gea_program-0.13.0 → gea_program-0.14.0}/README.md +18 -1
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/__init__.py +1 -1
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/__main__.py +67 -1
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/acceptance_tests.py +112 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/client_reports.py +58 -0
- gea_program-0.14.0/gea/help/vibration.md +11 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/helplib.py +1 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic.py +16 -4
- gea_program-0.14.0/gea/vibration.py +463 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/workspace.py +31 -0
- {gea_program-0.13.0 → gea_program-0.14.0/gea_program.egg-info}/PKG-INFO +19 -2
- {gea_program-0.13.0 → gea_program-0.14.0}/gea_program.egg-info/SOURCES.txt +2 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/pyproject.toml +1 -1
- {gea_program-0.13.0 → gea_program-0.14.0}/LICENSE +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/accuracy_statement.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/alarm_engine.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/bench.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/blind_harness.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/med_160_sapropels.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/certificates.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/cli.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/config_versioning.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/correlation.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/dashboard.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/deviation.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/doctor.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/downhole_engine.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/drift_monitor.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/earth_model.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/example_register_map.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/fat_sat.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/files.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/follower.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/forward_model.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/gamma.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/gauge_aging.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/gauge_specs.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/geodesy.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/gravity_reference.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/TESTER_GUIDE.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/alarms.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/audit-update.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/data-in.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/doctor.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/drift.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/files.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/instruments.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/notifications.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/osdu.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/patches.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/ppdm.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/quakeml.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/quality.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/seismic.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/site.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/sites.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/sra.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/start.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/transients.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/upkeep.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/help/well-tests.md +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/housekeeping.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/inverse_engine.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/jobs.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/live_ports.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/loadtest.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/matplotlib_demo.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/modbus.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/model_card.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/mqtt_port.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/notify.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/opcua_port.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/operator_app.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/osdu.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/patches.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/permits.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/ports.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/ppdm.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/profile_catalog.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/project.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/qt6_downhole_app.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/quakeml.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/reconciler.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/reference/libmseed_steim.provenance.json +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/rock_inventory.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/sample_record.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/sample_well_profile.csv +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/sbom.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/segy.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_array.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_assoc.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_detect.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_film.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_harmonic.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_qc.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_response.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_signature.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_track.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_uncertainty.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/seismic_unlisted.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/sensor_swap.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/service.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/service_life.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/shell.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/shut_in.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/sla_report.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/sra.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/store_forward.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/strata_join.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/supervisor.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/survey_cmd.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/survey_view.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/telemetry.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/tool_library.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/transient.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/web/app.html +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/well_assembler.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/well_test_validation.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/wits0.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea/witsml.py +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea_program.egg-info/dependency_links.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea_program.egg-info/entry_points.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea_program.egg-info/requires.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/gea_program.egg-info/top_level.txt +0 -0
- {gea_program-0.13.0 → gea_program-0.14.0}/setup.cfg +0 -0
- {gea_program-0.13.0 → gea_program-0.14.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.14.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
|
|
@@ -125,7 +125,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
|
|
|
125
125
|
gea client-report --report accuracy --out client_report
|
|
126
126
|
gea model-cards --out model_cards
|
|
127
127
|
gea sbom --out sbom
|
|
128
|
-
gea accept # the product gate (
|
|
128
|
+
gea accept # the product gate (330 checks)
|
|
129
129
|
gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
|
|
130
130
|
gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
|
|
131
131
|
gea gui # the desktop window (pip install "gea-program[desktop]")
|
|
@@ -602,6 +602,23 @@ It will not assume a sidetrack, invent an injection interval or a
|
|
|
602
602
|
completion, or name a county. `gea ppdm --action parse --number ...` takes a
|
|
603
603
|
number apart from the command line; `gea help ppdm`.
|
|
604
604
|
|
|
605
|
+
### Machine vibration
|
|
606
|
+
|
|
607
|
+
The pump's record read the way an operations engineer expects. `gea
|
|
608
|
+
workspace --action vibration-report --well <id> --record pump.csv --vib-unit
|
|
609
|
+
g --rpm 1780 --group 2 --support rigid --bearing 9,7.94,39.04` writes the
|
|
610
|
+
broadband r.m.s. vibration velocity over 10-1000 Hz (2-1000 Hz below 600
|
|
611
|
+
r/min), the quantity ISO 20816-1 defines, and the ISO 20816-3 zone for the
|
|
612
|
+
declared machine group and support class with the boundaries printed; then
|
|
613
|
+
the envelope spectrum of the most impulsive band (chosen by kurtosis, or
|
|
614
|
+
declared) against the bearing's defect frequencies - BPFO, BPFI, BSF, FTF
|
|
615
|
+
from its geometry and the shaft speed - each MATCHED at its fundamental or
|
|
616
|
+
NOT MATCHED, the inner race with its sidebands. A record in counts needs a
|
|
617
|
+
sensitivity; a rate that cannot carry 1000 Hz is PARTIAL BAND, never
|
|
618
|
+
promoted; the group and the support are declarations; a matched frequency
|
|
619
|
+
is not a fault size. CSV or miniSEED/SAC; `gea vibration` runs the labelled
|
|
620
|
+
pump; `gea help vibration`.
|
|
621
|
+
|
|
605
622
|
### Audit / Update
|
|
606
623
|
|
|
607
624
|
The Audit / Update tab holds three things. The whole audit log
|
|
@@ -86,7 +86,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
|
|
|
86
86
|
gea client-report --report accuracy --out client_report
|
|
87
87
|
gea model-cards --out model_cards
|
|
88
88
|
gea sbom --out sbom
|
|
89
|
-
gea accept # the product gate (
|
|
89
|
+
gea accept # the product gate (330 checks)
|
|
90
90
|
gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
|
|
91
91
|
gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
|
|
92
92
|
gea gui # the desktop window (pip install "gea-program[desktop]")
|
|
@@ -563,6 +563,23 @@ It will not assume a sidetrack, invent an injection interval or a
|
|
|
563
563
|
completion, or name a county. `gea ppdm --action parse --number ...` takes a
|
|
564
564
|
number apart from the command line; `gea help ppdm`.
|
|
565
565
|
|
|
566
|
+
### Machine vibration
|
|
567
|
+
|
|
568
|
+
The pump's record read the way an operations engineer expects. `gea
|
|
569
|
+
workspace --action vibration-report --well <id> --record pump.csv --vib-unit
|
|
570
|
+
g --rpm 1780 --group 2 --support rigid --bearing 9,7.94,39.04` writes the
|
|
571
|
+
broadband r.m.s. vibration velocity over 10-1000 Hz (2-1000 Hz below 600
|
|
572
|
+
r/min), the quantity ISO 20816-1 defines, and the ISO 20816-3 zone for the
|
|
573
|
+
declared machine group and support class with the boundaries printed; then
|
|
574
|
+
the envelope spectrum of the most impulsive band (chosen by kurtosis, or
|
|
575
|
+
declared) against the bearing's defect frequencies - BPFO, BPFI, BSF, FTF
|
|
576
|
+
from its geometry and the shaft speed - each MATCHED at its fundamental or
|
|
577
|
+
NOT MATCHED, the inner race with its sidebands. A record in counts needs a
|
|
578
|
+
sensitivity; a rate that cannot carry 1000 Hz is PARTIAL BAND, never
|
|
579
|
+
promoted; the group and the support are declarations; a matched frequency
|
|
580
|
+
is not a fault size. CSV or miniSEED/SAC; `gea vibration` runs the labelled
|
|
581
|
+
pump; `gea help vibration`.
|
|
582
|
+
|
|
566
583
|
### Audit / Update
|
|
567
584
|
|
|
568
585
|
The Audit / Update tab holds three things. The whole audit log
|
|
@@ -282,7 +282,7 @@ def main(argv=None) -> int:
|
|
|
282
282
|
choices=["init", "add-file", "add-catalog", "add-live", "remove", "list", "migrate", "refresh", "audit",
|
|
283
283
|
"add-seismic", "refresh-seismic", "remove-seismic", "sar-film", "refresh-all", "add-track", "refresh-track", "remove-track",
|
|
284
284
|
"seismic-dataset", "seismic-field", "add-site", "sites", "site-report", "remove-site", "rename",
|
|
285
|
-
"set-well", "sra-define", "sra-report", "associate", "osdu-export", "quakeml-export", "well-identity"])
|
|
285
|
+
"set-well", "sra-define", "sra-report", "associate", "osdu-export", "quakeml-export", "well-identity", "vibration-report"])
|
|
286
286
|
p_ws.add_argument("--stations", type=str, nargs="+", default=None, help="add-track: two or more array station ids of this workspace")
|
|
287
287
|
p_ws.add_argument("--site", type=str, default=None, help="site-report/remove-site: the site id")
|
|
288
288
|
p_ws.add_argument("--api", type=str, default=None, help="set-well: the API number")
|
|
@@ -317,6 +317,15 @@ def main(argv=None) -> int:
|
|
|
317
317
|
p_ws.add_argument("--operator-org", type=str, default="", help="osdu-export: the operator's Organisation record id on the platform")
|
|
318
318
|
p_ws.add_argument("--out", type=str, default=None, help="osdu-export: the folder to write the manifest and files into; quakeml-export: the file to write")
|
|
319
319
|
p_ws.add_argument("--agency", type=str, default="", help="quakeml-export: the agencyID written in creationInfo (default: the site's name)")
|
|
320
|
+
p_ws.add_argument("--record", type=str, default=None, help="vibration-report: the machine record (CSV with a timestamp or elapsed-seconds column, or miniSEED/SAC)")
|
|
321
|
+
p_ws.add_argument("--channel", type=str, default=None, help="vibration-report: the channel to assess (default: the first)")
|
|
322
|
+
p_ws.add_argument("--vib-unit", type=str, default="g", help="vibration-report: the channel's unit - g, m/s2, mm/s, in/s, or counts with --sensitivity")
|
|
323
|
+
p_ws.add_argument("--sensitivity", type=float, default=None, help="vibration-report: units per count, when the record is in counts")
|
|
324
|
+
p_ws.add_argument("--rpm", type=float, default=None, help="vibration-report: the shaft speed, r/min (declared)")
|
|
325
|
+
p_ws.add_argument("--group", type=int, choices=[1, 2], default=None, help="vibration-report: ISO 20816-3 machine group - 1 above 300 kW, 2 from 15 to 300 kW (declared)")
|
|
326
|
+
p_ws.add_argument("--support", type=str, choices=["rigid", "flexible"], default=None, help="vibration-report: the support class (declared)")
|
|
327
|
+
p_ws.add_argument("--bearing", type=str, default=None, help="vibration-report: elements,ball_mm,pitch_mm[,contact_deg] - the bearing geometry (declared)")
|
|
328
|
+
p_ws.add_argument("--demod-band", type=float, nargs=2, default=None, help="vibration-report: the demodulation band in Hz (default: chosen by kurtosis)")
|
|
320
329
|
p_ws.add_argument("--depth-km", type=float, default=6.0, help="associate: the hypocentral depth the location is made under, km (declared)")
|
|
321
330
|
p_ws.add_argument("--rms-tol", type=float, default=0.15, help="associate: the RMS residual an event must fit within, s")
|
|
322
331
|
p_ws.add_argument("--wells", type=str, nargs="+", default=None, help="add-site: well ids of this workspace")
|
|
@@ -400,6 +409,18 @@ def main(argv=None) -> int:
|
|
|
400
409
|
|
|
401
410
|
p_osdu = sub.add_parser("osdu", help="the OSDU-shaped export: the self-test on a labelled site")
|
|
402
411
|
p_osdu.add_argument("--action", choices=["selftest"], default="selftest")
|
|
412
|
+
p_vib = sub.add_parser("vibration", help="machine vibration: ISO 20816-3 zone and bearing envelope analysis on a record, or the self-test")
|
|
413
|
+
p_vib.add_argument("--action", choices=["selftest", "assess"], default="selftest")
|
|
414
|
+
p_vib.add_argument("--record", type=str, default=None, help="assess: the record (CSV with a time column, or miniSEED/SAC)")
|
|
415
|
+
p_vib.add_argument("--channel", type=str, default=None)
|
|
416
|
+
p_vib.add_argument("--unit", type=str, default="g", help="g, m/s2, mm/s, in/s, or counts with --sensitivity")
|
|
417
|
+
p_vib.add_argument("--sensitivity", type=float, default=None)
|
|
418
|
+
p_vib.add_argument("--rpm", type=float, default=None)
|
|
419
|
+
p_vib.add_argument("--group", type=int, choices=[1, 2], default=None)
|
|
420
|
+
p_vib.add_argument("--support", type=str, choices=["rigid", "flexible"], default=None)
|
|
421
|
+
p_vib.add_argument("--bearing", type=str, default=None, help="elements,ball_mm,pitch_mm[,contact_deg]")
|
|
422
|
+
p_vib.add_argument("--demod-band", type=float, nargs=2, default=None)
|
|
423
|
+
p_vib.add_argument("--json", action="store_true")
|
|
403
424
|
p_ppdm = sub.add_parser("ppdm", help="the well named as the US Well Number and PPDM name it: take a number apart, or run the self-test")
|
|
404
425
|
p_ppdm.add_argument("--action", choices=["selftest", "parse"], default="selftest")
|
|
405
426
|
p_ppdm.add_argument("--number", type=str, default=None, help="parse: a US Well Number (10, 12 or 14 digits, dashes optional)")
|
|
@@ -1503,6 +1524,35 @@ def main(argv=None) -> int:
|
|
|
1503
1524
|
return 0
|
|
1504
1525
|
print(f"notifications: {'configured' if n.cfg else 'not configured'}" + (f" - {len(n.cfg['channels'])} channel(s), {len(n.cfg['rules'])} rule(s), quiet {n.cfg['quiet_s']} s" if n.cfg else " (gea notify --example)"))
|
|
1505
1526
|
return 0
|
|
1527
|
+
elif a.cmd == "vibration":
|
|
1528
|
+
from . import vibration as _V
|
|
1529
|
+
if a.action == "assess":
|
|
1530
|
+
if not a.record:
|
|
1531
|
+
raise SystemExit("vibration --action assess needs --record")
|
|
1532
|
+
brg = None
|
|
1533
|
+
if a.bearing:
|
|
1534
|
+
parts = [float(x) for x in a.bearing.split(",")]
|
|
1535
|
+
if len(parts) not in (3, 4):
|
|
1536
|
+
raise SystemExit("--bearing is elements,ball_mm,pitch_mm[,contact_deg]")
|
|
1537
|
+
brg = {"n_elements": int(parts[0]), "d_mm": parts[1], "D_mm": parts[2], "contact_deg": parts[3] if len(parts) == 4 else 0.0}
|
|
1538
|
+
try:
|
|
1539
|
+
rec = _V.read_record(a.record, a.channel)
|
|
1540
|
+
except ValueError as e:
|
|
1541
|
+
raise SystemExit(f"vibration: {e}")
|
|
1542
|
+
r = _V.assess(rec["x"], rec["fs"], a.unit, a.rpm, group=a.group, support=a.support, bearing=brg,
|
|
1543
|
+
band_hz=tuple(a.demod_band) if a.demod_band else None, label=f"{rec['name']}:{rec['channel']}", sensitivity=a.sensitivity)
|
|
1544
|
+
r["gaps"] = list(r["gaps"]) + list(rec["notes"])
|
|
1545
|
+
if a.json:
|
|
1546
|
+
print(json.dumps({k: v for k, v in r.items()}, indent=1, default=str))
|
|
1547
|
+
else:
|
|
1548
|
+
print(_V.report_text(r))
|
|
1549
|
+
return 0 if r["status"] == "ASSESSED" else 1
|
|
1550
|
+
r = _V.selftest()
|
|
1551
|
+
print(f"vibration selftest [{r['label']}]: {r['status']}")
|
|
1552
|
+
for k, v in r["checks"].items():
|
|
1553
|
+
print(f" {'ok ' if v else 'BAD'} {k}")
|
|
1554
|
+
print(_V.report_text(r["assessment"]))
|
|
1555
|
+
return 0 if r["status"] == "OK" else 1
|
|
1506
1556
|
elif a.cmd == "ppdm":
|
|
1507
1557
|
from . import ppdm as _P
|
|
1508
1558
|
if a.action == "parse":
|
|
@@ -1790,6 +1840,22 @@ def main(argv=None) -> int:
|
|
|
1790
1840
|
countries=a.country, operator_org_id=a.operator_org, out_dir=a.out, actor=a.actor)
|
|
1791
1841
|
print(_osdu_text(r)); v = r["validate"]
|
|
1792
1842
|
print(f" structure: {'ok' if v['ok'] else 'PROBLEMS'} ({v['records']} record(s))" + ('' if v['ok'] else '; ' + '; '.join(v['problems'][:5]))); return 0
|
|
1843
|
+
elif a.action == "vibration-report":
|
|
1844
|
+
from .vibration import report_text as _vib_text
|
|
1845
|
+
if not a.well or not a.record:
|
|
1846
|
+
raise SystemExit("vibration-report needs --well <id> and --record <file>")
|
|
1847
|
+
brg = None
|
|
1848
|
+
if a.bearing:
|
|
1849
|
+
parts = [float(x) for x in a.bearing.split(",")]
|
|
1850
|
+
if len(parts) not in (3, 4):
|
|
1851
|
+
raise SystemExit("--bearing is elements,ball_mm,pitch_mm[,contact_deg]")
|
|
1852
|
+
brg = {"n_elements": int(parts[0]), "d_mm": parts[1], "D_mm": parts[2], "contact_deg": parts[3] if len(parts) == 4 else 0.0}
|
|
1853
|
+
try:
|
|
1854
|
+
r = ws.vibration_report(a.well, a.record, channel=a.channel, unit=a.vib_unit, rpm=a.rpm, group=a.group, support=a.support, bearing=brg,
|
|
1855
|
+
band_hz=a.demod_band, sensitivity=a.sensitivity, actor=a.actor)
|
|
1856
|
+
except ValueError as e:
|
|
1857
|
+
raise SystemExit(f"vibration-report: {e}")
|
|
1858
|
+
print(_vib_text(r)); print(" written:", r["paths"].get("md") or r["paths"]); return 0
|
|
1793
1859
|
elif a.action == "well-identity":
|
|
1794
1860
|
from .ppdm import report_text as _ppdm_text
|
|
1795
1861
|
if not a.well:
|
|
@@ -5208,6 +5208,117 @@ def section_bg_ppdm(tmp: str) -> None:
|
|
|
5208
5208
|
"a number from the command line with the exit code saying whether it is valid, and runs the self-test; the help page names the sidetrack "
|
|
5209
5209
|
"it will not assume")
|
|
5210
5210
|
|
|
5211
|
+
|
|
5212
|
+
def section_bh_vibration(tmp: str) -> None:
|
|
5213
|
+
"""Section BH - machine vibration: the ISO 20816-3 zone of the declared machine from the broadband r.m.s.
|
|
5214
|
+
velocity, and the bearing's defect frequencies found or not found in the envelope spectrum of the most
|
|
5215
|
+
impulsive band; the declarations named as declarations, the band's limits named, no fault size claimed."""
|
|
5216
|
+
import csv as _csv
|
|
5217
|
+
import subprocess as _sp
|
|
5218
|
+
import numpy as _np
|
|
5219
|
+
from . import vibration as V
|
|
5220
|
+
from . import seismic as S
|
|
5221
|
+
from . import helplib as H
|
|
5222
|
+
from .client_reports import forbidden_terms
|
|
5223
|
+
from .workspace import Workspace
|
|
5224
|
+
pkg = Path(__file__).parent
|
|
5225
|
+
d = Path(tmp, "bh"); d.mkdir()
|
|
5226
|
+
|
|
5227
|
+
# -- the self-test on the labelled pump ----------------------------------------------------------
|
|
5228
|
+
r = V.selftest()
|
|
5229
|
+
a = r["assessment"]
|
|
5230
|
+
ok(r["status"] == "OK" and all(r["checks"].values()) and r["label"] == "SIMULATION_SELF_TEST"
|
|
5231
|
+
and a["zone"]["zone"] == "C" and abs(a["broadband"]["rms_mm_s"] - r["truth"]["unbalance_rms_mm_s"] * (1 + 0.09) ** 0.5) < 0.3
|
|
5232
|
+
and a["envelope"]["match"]["matched"] == ["BPFO"] and len(a["envelope"]["match"]["rows"]["BPFO"]["harmonics_found"]) == 3
|
|
5233
|
+
and r["inner"]["envelope"]["match"]["matched"] == ["BPFI"] and len(r["inner"]["envelope"]["match"]["rows"]["BPFI"]["sidebands"]["found"]) == 2
|
|
5234
|
+
and V.ZONE_BOUNDARIES == {(1, "rigid"): (2.3, 4.5, 7.1), (1, "flexible"): (3.5, 7.1, 11.0), (2, "rigid"): (1.4, 2.8, 4.5), (2, "flexible"): (2.3, 4.5, 7.1)}
|
|
5235
|
+
and V.BAND_HZ == (10.0, 1000.0) and V.BAND_LOW_SPEED_HZ == (2.0, 1000.0) and V.LOW_SPEED_RPM == 600.0
|
|
5236
|
+
and abs(V.bearing_frequencies(1780, 9, 7.94, 39.04)["BPFI"] - 0.5 * 9 * (1780 / 60) * (1 + 7.94 / 39.04)) < 1e-3
|
|
5237
|
+
and abs(V.bearing_frequencies(1780, 9, 7.94, 39.04)["BSF"] - (39.04 / (2 * 7.94)) * (1780 / 60) * (1 - (7.94 / 39.04) ** 2)) < 1e-3
|
|
5238
|
+
and abs(V.bearing_frequencies(1780, 9, 7.94, 39.04)["FTF"] - 0.5 * (1780 / 60) * (1 - 7.94 / 39.04)) < 1e-3
|
|
5239
|
+
and abs(V.bearing_frequencies(1780, 9, 7.94, 39.04, 30.0)["BPFO"] - 0.5 * 9 * (1780 / 60) * (1 - 7.94 / 39.04 * _np.cos(_np.radians(30)))) < 1e-3,
|
|
5240
|
+
"BH1 the self-test on a labelled pump at 1780 r/min: the broadband r.m.s. velocity recovers the unbalance line put into the record to within "
|
|
5241
|
+
"8% and places a Group 2 rigid machine in zone C as the truth says; the most impulsive band is chosen and the outer-race fault is matched at "
|
|
5242
|
+
"its fundamental and two harmonics with the inner race, the ball and the cage not matched; an inner-race scene is matched at BPFI with both "
|
|
5243
|
+
"sidebands at the shaft speed and the outer race not matched; the zone boundaries are ISO 20816-3's for both groups and both supports, the "
|
|
5244
|
+
"band is ISO 20816-1's, and the four defect frequencies are the kinematic formulas including the contact angle")
|
|
5245
|
+
|
|
5246
|
+
# -- what it will not call a measurement ----------------------------------------------------------
|
|
5247
|
+
sc = V.synthetic_scene(seconds=2.0)
|
|
5248
|
+
slow = V.assess(sc["acc_m_s2"][::10], sc["fs"] / 10.0, "m/s2", sc["rpm"], group=2, support="rigid", bearing=sc["bearing"])
|
|
5249
|
+
short = V.assess(sc["acc_m_s2"][:int(0.5 * sc["fs"])], sc["fs"], "m/s2", sc["rpm"], group=2, support="rigid", bearing=sc["bearing"])
|
|
5250
|
+
nod = V.assess(sc["acc_m_s2"], sc["fs"], "m/s2", None)
|
|
5251
|
+
cnt = V.assess(_np.round(sc["acc_m_s2"] / 9.80665 / 1e-4), sc["fs"], "counts", sc["rpm"], group=2, support="rigid", bearing=sc["bearing"])
|
|
5252
|
+
sens = V.assess(_np.round(sc["acc_m_s2"] / 9.80665 / 1e-4), sc["fs"], "g", sc["rpm"], group=2, support="rigid", bearing=sc["bearing"], sensitivity=1e-4)
|
|
5253
|
+
low = V.assess(sc["acc_m_s2"], sc["fs"], "m/s2", 450.0, group=1, support="flexible")
|
|
5254
|
+
declared_band = V.assess(sc["acc_m_s2"], sc["fs"], "m/s2", sc["rpm"], group=2, support="rigid", bearing=sc["bearing"], band_hz=(2000.0, 4000.0))
|
|
5255
|
+
ok(slow["broadband"]["band_partial"] and slow["broadband"]["band_hz"][1] < 1000 and slow["zone"]["zone_qualified"] == "PARTIAL BAND"
|
|
5256
|
+
and any("PARTIAL BAND" in g for g in slow["gaps"])
|
|
5257
|
+
and any("shorter than one second" in g for g in short["gaps"])
|
|
5258
|
+
and nod["zone"] is None and nod["status"] == "PARTIAL" and any("no shaft speed" in g for g in nod["gaps"]) and any("group" in g for g in nod["gaps"])
|
|
5259
|
+
and any("bearing" in g for g in nod["gaps"]) and nod["envelope"]["match"] is None and len(nod["envelope"]["peaks"]) > 0
|
|
5260
|
+
and cnt["status"] == "NOT ASSESSED" and cnt["broadband"]["status"] == "NOT EVALUATED" and cnt["envelope"]["match"]["matched"] == ["BPFO"]
|
|
5261
|
+
and sens["status"] == "ASSESSED" and abs(sens["broadband"]["rms_mm_s"] - a["broadband"]["rms_mm_s"]) < 0.3 and sens["declared"]["sensitivity"] == 1e-4
|
|
5262
|
+
and low["broadband"]["band_hz"][0] == 2.0 and low["zone"]["boundaries_mm_s"] == {"A/B": 3.5, "B/C": 7.1, "C/D": 11.0}
|
|
5263
|
+
and declared_band["envelope"]["band"]["status"] == "DECLARED" and declared_band["envelope"]["band"]["band_hz"] == [2000.0, 4000.0]
|
|
5264
|
+
and declared_band["envelope"]["match"]["matched"] == ["BPFO"]
|
|
5265
|
+
and "fault size" in " ".join(a["not_a_measurement"]) and "declared" in " ".join(a["not_a_measurement"]),
|
|
5266
|
+
"BH2 a record whose rate cannot carry 1000 Hz is evaluated to its own Nyquist frequency and marked PARTIAL BAND, never promoted; a record "
|
|
5267
|
+
"under a second is named; without a shaft speed, a group or a bearing the broadband value is stated, the zone is not, the envelope peaks "
|
|
5268
|
+
"are listed and nothing is matched; a record in counts gets no mm/s and no zone but its envelope is still read, and with a declared "
|
|
5269
|
+
"sensitivity it agrees with the same record in g; below 600 r/min the band starts at 2 Hz and Group 1 flexible has its own boundaries; a "
|
|
5270
|
+
"declared demodulation band is used as declared; the assessment says it is not a fault size and that the machine is a declaration")
|
|
5271
|
+
|
|
5272
|
+
# -- through the workspace and the command line, from a CSV and from a miniSEED record ------------
|
|
5273
|
+
csvp = d / "pump.csv"
|
|
5274
|
+
with open(csvp, "w", newline="") as f:
|
|
5275
|
+
w = _csv.writer(f); w.writerow(["elapsed_s", "acc_g", "temp_C"])
|
|
5276
|
+
for i, x in enumerate(sc["acc_m_s2"]):
|
|
5277
|
+
w.writerow([f"{i / sc['fs']:.6f}", f"{x / 9.80665:.6f}", "41.0"])
|
|
5278
|
+
counts = _np.round(sc["acc_m_s2"] / 9.80665 / 1e-4).astype(_np.int32)
|
|
5279
|
+
S.write_mseed([S.Trace("XX", "PUMP", "", "ACC", 1700000000.1234567, sc["fs"], counts, "synthetic", "INT32")], str(d / "pump.mseed"))
|
|
5280
|
+
back = S.read_any(str(d / "pump.mseed"))
|
|
5281
|
+
hist = d / "swd.csv"
|
|
5282
|
+
with open(hist, "w", newline="") as f:
|
|
5283
|
+
w = _csv.writer(f); w.writerow(["timestamp", "P_surf_psi"])
|
|
5284
|
+
for h in range(24):
|
|
5285
|
+
w.writerow([f"2026-03-01T{h:02d}:00:00Z", "1500"])
|
|
5286
|
+
ws = Workspace.create(str(d / "ws"), "Pad 3", actor="tester")
|
|
5287
|
+
w1 = ws.add_well_file(str(hist), display="SWD 1", actor="tester", station_md_ft=9800.0)
|
|
5288
|
+
run = lambda *a: _sp.run([sys.executable, "-m", "gea", "workspace", "--path", ws.path, "--actor", "tester", *a], capture_output=True, text=True)
|
|
5289
|
+
r1 = run("--action", "vibration-report", "--well", w1["id"], "--record", str(csvp), "--channel", "acc_g", "--vib-unit", "g", "--rpm", "1780",
|
|
5290
|
+
"--group", "2", "--support", "rigid", "--bearing", "9,7.94,39.04")
|
|
5291
|
+
r0 = run("--action", "vibration-report", "--well", w1["id"], "--record", str(csvp), "--channel", "nope")
|
|
5292
|
+
out = Path(ws.path, "reports", "wells", w1["id"])
|
|
5293
|
+
md = (out / "vibration_report.md").read_text(encoding="utf-8"); html = (out / "vibration_report.html").read_text(encoding="utf-8")
|
|
5294
|
+
js = json.loads((out / "vibration_report.json").read_text(encoding="utf-8"))
|
|
5295
|
+
audit = Path(ws.path, "records", "audit.jsonl").read_text(encoding="utf-8")
|
|
5296
|
+
r2 = _sp.run([sys.executable, "-m", "gea", "vibration", "--action", "assess", "--record", str(d / "pump.mseed"), "--unit", "g", "--sensitivity", "1e-4",
|
|
5297
|
+
"--rpm", "1780", "--group", "2", "--support", "rigid", "--bearing", "9,7.94,39.04"], capture_output=True, text=True)
|
|
5298
|
+
r3 = _sp.run([sys.executable, "-m", "gea", "vibration", "--action", "assess", "--record", str(d / "pump.mseed"), "--unit", "counts", "--rpm", "1780",
|
|
5299
|
+
"--group", "2", "--support", "rigid"], capture_output=True, text=True)
|
|
5300
|
+
r4 = _sp.run([sys.executable, "-m", "gea", "vibration"], capture_output=True, text=True)
|
|
5301
|
+
help_md = (pkg / "help" / "vibration.md").read_text(encoding="utf-8")
|
|
5302
|
+
ok(len(back) == 1 and back[0].npts == counts.size and not back[0].gaps and abs(back[0].starttime - 1700000000.1234567) < 2e-6
|
|
5303
|
+
and r1.returncode == 0 and "ISO 20816-3 zone C" in r1.stdout and "BPFO 106.3486 Hz: MATCHED" in r1.stdout and "written:" in r1.stdout
|
|
5304
|
+
and r0.returncode != 0 and "no channel" in (r0.stderr + r0.stdout)
|
|
5305
|
+
and Path(ws.path, "wells", w1["id"], "machine", "pump.csv").is_file()
|
|
5306
|
+
and "| **Result** | ZONE C |" in md and "Bearing defect frequencies" in md and "Group 2 (15 kW to 300 kW)" in md and "fault size" in md
|
|
5307
|
+
and not forbidden_terms(md) and not forbidden_terms(html)
|
|
5308
|
+
and js["assessment"]["record"]["sha256"] and js["assessment"]["zone"]["zone"] == "C" and js["assessment"]["declared"]["bearing"]["n_elements"] == 9
|
|
5309
|
+
and "well.vibration" in audit and '"zone": "C"' in audit
|
|
5310
|
+
and r2.returncode == 0 and "from acceleration (g), 2.0 s at 20000 Hz" in r2.stdout and "zone C" in r2.stdout and "MATCHED" in r2.stdout
|
|
5311
|
+
and r3.returncode == 1 and "NOT ASSESSED" in r3.stdout and "without a sensitivity" in r3.stdout
|
|
5312
|
+
and r4.returncode == 0 and "vibration selftest [SIMULATION_SELF_TEST]: OK" in r4.stdout
|
|
5313
|
+
and any(t["topic"] == "vibration" for t in H.topics()) and not H.check("vibration")
|
|
5314
|
+
and "fault size" in help_md.split("will not call a measurement")[1] and "2.3 / 4.5 / 7.1" in help_md,
|
|
5315
|
+
"BH3 a 20 kHz record round-trips through this program's own miniSEED writer as one trace with no gap (the header's 0.1 ms time field "
|
|
5316
|
+
"is coarser than a sample above 5 kHz and every record read back as a gap until blockette 1001 carried the microseconds); "
|
|
5317
|
+
"`--action vibration-report` copies the record beside the well, writes the report in three forms with the zone as its result, the "
|
|
5318
|
+
"declarations in their own table and the defect frequencies each matched or not, audits it with the zone and the declarations, and names "
|
|
5319
|
+
"a channel that is not there; `gea vibration --action assess` reads a miniSEED record in counts with a declared sensitivity and says "
|
|
5320
|
+
"NOT ASSESSED without one; the self-test runs from the command line; the help page carries the boundaries and names the fault size it will not claim")
|
|
5321
|
+
|
|
5211
5322
|
def main() -> int:
|
|
5212
5323
|
print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
|
|
5213
5324
|
# a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
|
|
@@ -5270,6 +5381,7 @@ def main() -> int:
|
|
|
5270
5381
|
section_be_osdu(tmp)
|
|
5271
5382
|
section_bf_quakeml(tmp)
|
|
5272
5383
|
section_bg_ppdm(tmp)
|
|
5384
|
+
section_bh_vibration(tmp)
|
|
5273
5385
|
if _FAILS:
|
|
5274
5386
|
print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
|
|
5275
5387
|
for f in _FAILS:
|
|
@@ -1703,6 +1703,64 @@ def sra_packet_report(pk: dict, evaluated_at: Optional[datetime] = None, program
|
|
|
1703
1703
|
data={'packet': pk, 'report_id': report_id, 'evaluated_at_utc': now.strftime('%Y-%m-%dT%H:%M:%SZ'), '_records': [], '_catalogue_obj': None})
|
|
1704
1704
|
|
|
1705
1705
|
|
|
1706
|
+
def vibration_report(r: dict, evaluated_at: Optional[datetime] = None, program_version: str = '') -> Document:
|
|
1707
|
+
"""One machine record through ISO 20816-3 and the envelope: the broadband value and its zone for the
|
|
1708
|
+
declared machine, the demodulation band, the bearing's defect frequencies each matched or not, and every
|
|
1709
|
+
declaration and gap by name. Built from `vibration.assess`; nothing is recomputed here."""
|
|
1710
|
+
now = evaluated_at or _utc_now()
|
|
1711
|
+
label = str(r.get('label') or r.get('record', {}).get('name') or 'machine')
|
|
1712
|
+
report_id = f"VIB-{label.replace('/', '-').replace(' ', '-')[:24]}-{now.strftime('%Y%m%dT%H%M%SZ')}"
|
|
1713
|
+
bb = r.get('broadband') or {}; z = r.get('zone'); env = r.get('envelope') or {}; d = r.get('declared') or {}
|
|
1714
|
+
rec = r.get('record') or {}
|
|
1715
|
+
result = (f"ZONE {z['zone']}" + (f" ({z['zone_qualified']})" if z.get('zone_qualified') else '')) if z else r.get('status', '-')
|
|
1716
|
+
paras = []
|
|
1717
|
+
if bb.get('status') == 'EVALUATED':
|
|
1718
|
+
paras.append(f"The broadband r.m.s. vibration velocity is {bb['rms_mm_s']} mm/s over {bb['band_hz'][0]:g} Hz to {bb['band_hz'][1]:g} Hz"
|
|
1719
|
+
+ (' - a partial band: the record cannot carry the standard\'s 1000 Hz' if bb.get('band_partial') else '')
|
|
1720
|
+
+ f", from {'an' if bb['from'] == 'acceleration' else 'a'} {bb['from']} channel in {bb['unit_in']}, {bb['seconds']} s at {bb['fs_hz']:g} Hz.")
|
|
1721
|
+
else:
|
|
1722
|
+
paras.append(f"The broadband value was not evaluated: {bb.get('detail') or 'see the gaps'}.")
|
|
1723
|
+
if z:
|
|
1724
|
+
paras.append(f"For a {z['group_basis'].split(':')[0]} machine on a {z['support']} support that is ISO 20816-3 zone {z['zone']}: {z['meaning']}. "
|
|
1725
|
+
f"The boundaries for this group and support are A/B {z['boundaries_mm_s']['A/B']}, B/C {z['boundaries_mm_s']['B/C']} and C/D "
|
|
1726
|
+
f"{z['boundaries_mm_s']['C/D']} mm/s" + (f"; {z['margin_to_next_mm_s']} mm/s remain to the next boundary." if z['margin_to_next_mm_s'] is not None else '.'))
|
|
1727
|
+
secs = [Section('1', 'Summary', paras)]
|
|
1728
|
+
secs.append(Section('2', 'What was declared', ['The group, the support class, the shaft speed and the bearing are the operator\'s declarations; the record carries none of them.'],
|
|
1729
|
+
[Table(['Declaration', 'Value'],
|
|
1730
|
+
[['Machine group', (GROUPS_TEXT.get(d.get('group')) if d.get('group') else 'not declared')],
|
|
1731
|
+
['Support class', d.get('support') or 'not declared'], ['Shaft speed (r/min)', d.get('rpm') if d.get('rpm') is not None else 'not declared'],
|
|
1732
|
+
['Bearing', (f"{d['bearing']['n_elements']} elements, d {d['bearing']['d_mm']} mm, D {d['bearing']['D_mm']} mm, contact {d['bearing'].get('contact_deg', 0)}°" if d.get('bearing') else 'not declared')],
|
|
1733
|
+
['Demodulation band', (f"{d['band_hz'][0]:g}-{d['band_hz'][1]:g} Hz, declared" if d.get('band_hz') else 'chosen by kurtosis')],
|
|
1734
|
+
['Channel unit', d.get('unit') or '-']])]))
|
|
1735
|
+
n = 3
|
|
1736
|
+
if env.get('band') and env['band'].get('band_hz'):
|
|
1737
|
+
b = env['band']; m = env.get('match')
|
|
1738
|
+
ep = [f"The envelope was taken in {b['band_hz'][0]:g}-{b['band_hz'][1]:g} Hz ({b['status'].lower()}" + (f", kurtosis {b['kurtosis']}" if b.get('kurtosis') is not None else '')
|
|
1739
|
+
+ f"); the envelope spectrum's resolution is {env.get('resolution_hz')} Hz."]
|
|
1740
|
+
tables = []
|
|
1741
|
+
if m:
|
|
1742
|
+
bf = env['bearing']
|
|
1743
|
+
ep.append(f"Shaft speed {bf['fr']} Hz. {m['status']}. Basis: {m['basis']}.")
|
|
1744
|
+
tables.append(Table(['Defect frequency', 'Hz', 'Standing', 'Found at (Hz)', 'Sidebands at fr'],
|
|
1745
|
+
[[k, v['frequency_hz'], v['standing'], ', '.join(f"{h['found_hz']} ({h['harmonic']}x)" for h in v['harmonics_found']) or '-',
|
|
1746
|
+
(', '.join(str(x) for x in v['sidebands']['found']) or 'none') if v.get('sidebands') else '-'] for k, v in m['rows'].items()], 'Bearing defect frequencies'))
|
|
1747
|
+
elif env.get('peaks'):
|
|
1748
|
+
ep.append('No bearing geometry was declared: the envelope spectrum\'s largest peaks are listed and nothing is matched.')
|
|
1749
|
+
tables.append(Table(['Peak (Hz)', 'Amplitude', 'Over median'], [[p['f_hz'], _fmt(p['amplitude']), p.get('over_median')] for p in env['peaks'][:10]], 'Envelope spectrum peaks'))
|
|
1750
|
+
secs.append(Section(str(n), 'The envelope spectrum', ep, tables)); n += 1
|
|
1751
|
+
secs.append(Section(str(n), 'What needs attention', list(r.get('gaps') or []) or ['Nothing: every declaration was made and the record carries the band.'])); n += 1
|
|
1752
|
+
secs.append(Section(str(n), 'What this report does not call a measurement', [x.rstrip('.') + '.' for x in (r.get('not_a_measurement') or [])]))
|
|
1753
|
+
front = [['Report ID', report_id], ['Record', rec.get('name') or label], ['Channel', rec.get('channel') or '-'],
|
|
1754
|
+
['Generated (UTC)', now.strftime('%Y-%m-%dT%H:%M:%SZ')],
|
|
1755
|
+
['Program', f'{PROGRAM_NAME}' + (f' build {program_version}' if program_version else '')], ['Result', result]]
|
|
1756
|
+
return Document(title=f'{PROGRAM_NAME} - Machine Vibration Report', report_id=report_id, front=front, sections=secs,
|
|
1757
|
+
footer='ISO 20816-1 quantity, ISO 20816-3 zones for the declared machine; the envelope against the declared bearing. Nothing here is a fault size.',
|
|
1758
|
+
data={'assessment': r, 'report_id': report_id, 'evaluated_at_utc': now.strftime('%Y-%m-%dT%H:%M:%SZ'), '_records': [], '_catalogue_obj': None})
|
|
1759
|
+
|
|
1760
|
+
|
|
1761
|
+
GROUPS_TEXT = {1: 'Group 1 (above 300 kW)', 2: 'Group 2 (15 kW to 300 kW)'}
|
|
1762
|
+
|
|
1763
|
+
|
|
1706
1764
|
def forbidden_terms(text: str) -> List[str]:
|
|
1707
1765
|
low = text.lower()
|
|
1708
1766
|
return [t for t in FORBIDDEN_TERMS if t in low]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Machine vibration
|
|
2
|
+
|
|
3
|
+
> The pump's record read the way an operations engineer expects: which ISO 20816-3 zone the machine is in, and - when it is not A or B - what the bearings are doing, by envelope analysis against the bearing's own defect frequencies.
|
|
4
|
+
|
|
5
|
+
**The command**: `gea workspace --path C:\site --action vibration-report --well <id> --record pump.csv --channel acc --vib-unit g --rpm 1780 --group 2 --support rigid --bearing 9,7.94,39.04` writes `reports/wells/<id>/vibration_report.{md,html,json}` and copies the record beside the well under `machine/` with its hash. The record is a delimited export whose first column is a timestamp or elapsed seconds (the historian reader) or a miniSEED/SAC record (the seismic reader; counts as recorded, so give the unit and `--sensitivity` units-per-count). The unit (`--vib-unit` in the workspace, `--unit` in `gea vibration`) is g, m/s2, mm/s or in/s. `--demod-band lo hi` declares the demodulation band instead of letting kurtosis choose it. `gea vibration --action assess --record ...` does the same without a workspace; `gea vibration` runs the self-test on a labelled pump record.
|
|
6
|
+
|
|
7
|
+
**What it writes**: the broadband r.m.s. vibration velocity in mm/s over 10 Hz to 1000 Hz (2 Hz to 1000 Hz below 600 r/min), the quantity ISO 20816-1 defines - from an acceleration channel by integration in the frequency domain inside the band, from a velocity channel by band-limiting; the ISO 20816-3 zone for the declared machine group (Group 1 above 300 kW; Group 2 from 15 kW to 300 kW) and support class (rigid when the machine-foundation system's lowest natural frequency is at least 1.25 times the main excitation frequency, otherwise flexible), with the boundaries printed (Group 1 rigid 2.3 / 4.5 / 7.1; Group 1 flexible 3.5 / 7.1 / 11.0; Group 2 rigid 1.4 / 2.8 / 4.5; Group 2 flexible 2.3 / 4.5 / 7.1 mm/s for A/B, B/C, C/D) and the margin to the next; the demodulation band (chosen as the candidate band with the highest kurtosis, because a bearing fault's impacts are impulsive and kurtosis is their measure, or declared); the envelope spectrum of the analytic signal in that band; the bearing's defect frequencies from its geometry and the shaft speed - BPFO, BPFI, BSF, FTF - each MATCHED (a peak at the fundamental within 2% or one resolution bin, at least four times the spectrum's median, harmonics at the same tolerance, and for the inner race the sidebands at the shaft speed) or NOT MATCHED.
|
|
8
|
+
|
|
9
|
+
**The number to check**: the zone, the r.m.s. value it was set by, and `FAULT FREQUENCY PRESENT` or `NO FAULT FREQUENCY MATCHED` with the matched frequency named. `PARTIAL BAND` on the zone means the record's rate cannot carry 1000 Hz and the value was taken to the record's own Nyquist frequency.
|
|
10
|
+
|
|
11
|
+
**What this page will not call a measurement**: a machine group or a support class - the record does not say what the machine is standing on, and both are declared. A zone from a record that cannot carry the band, which is marked PARTIAL BAND and not promoted; or from a record shorter than a second. A fault size - a matched frequency says the bearing rings at it, not how far the fault has gone. A defect frequency without the bearing's geometry - without it the envelope spectrum's peaks are listed and nothing is matched. A match on harmonics alone - the harmonics of one defect frequency fall near multiples of another, so the fundamental is required. An mm/s value from a record in counts without a declared sensitivity.
|
|
@@ -42,6 +42,7 @@ INDEX: List[tuple] = [
|
|
|
42
42
|
('osdu', 'The OSDU-shaped export', 'the site as the manifest an operator\'s data platform loads'),
|
|
43
43
|
('quakeml', 'The QuakeML catalogue export', 'the site\'s own events in the format the regulator\'s catalogue tools read'),
|
|
44
44
|
('ppdm', 'The well as master data names it', 'the US Well Number taken apart and the PPDM "What is a Well" components the site can name'),
|
|
45
|
+
('vibration', 'Machine vibration', 'the pump\'s record through the ISO 20816-3 zones and bearing envelope analysis'),
|
|
45
46
|
('doctor', 'Which code is running', 'gea doctor and the serve start-up gate'),
|
|
46
47
|
('audit-update', 'Audit / Update', 'the whole audit log with filters, the program against PyPI, every report against its source'),
|
|
47
48
|
('upkeep', 'Upkeep', 'housekeeping, sessions, the TLS proxy, the load test'),
|
|
@@ -80,6 +80,14 @@ def _btime_to_epoch(year: int, doy: int, hour: int, minute: int, sec: int, frac0
|
|
|
80
80
|
return d.timestamp() + frac0001 / 10000.0
|
|
81
81
|
|
|
82
82
|
|
|
83
|
+
def _epoch_to_btime_usec(t: float) -> Tuple[int, int, int, int, int, int, int]:
|
|
84
|
+
"""The header's 0.1 ms field and the microseconds left over for blockette 1001 (0 to 99)."""
|
|
85
|
+
d = _dt.datetime.fromtimestamp(t, tz=_dt.timezone.utc)
|
|
86
|
+
us = int(round(d.microsecond))
|
|
87
|
+
frac = us // 100
|
|
88
|
+
return d.year, d.timetuple().tm_yday, d.hour, d.minute, d.second, frac, us - frac * 100
|
|
89
|
+
|
|
90
|
+
|
|
83
91
|
def _epoch_to_btime(t: float) -> Tuple[int, int, int, int, int, int]:
|
|
84
92
|
d = _EPOCH + _dt.timedelta(seconds=float(t))
|
|
85
93
|
frac = int(round((d.microsecond / 1e6) * 10000.0))
|
|
@@ -597,15 +605,19 @@ def write_mseed(traces: Sequence[Trace], path: str, encoding: str = 'STEIM1', re
|
|
|
597
605
|
body = np.asarray(data[i:i + n], dtype='>f8').tobytes().ljust(payload_room, b'\x00')
|
|
598
606
|
if n == 0:
|
|
599
607
|
raise ValueError("no sample fits in a record")
|
|
600
|
-
|
|
608
|
+
# the header's time has 0.1 ms resolution; above 5 kHz that is coarser than a sample, and a record whose start
|
|
609
|
+
# is rounded to it reads back as a gap or an overlap against the one before. Blockette 1001 carries the
|
|
610
|
+
# microseconds the header cannot, so the record's start is written exactly and the reader joins the records.
|
|
611
|
+
year, doy, hh, mm, ss, frac, usec = _epoch_to_btime_usec(t0)
|
|
601
612
|
hdr = (f"{seq % 1000000:06d}".encode() + b'D' + b' '
|
|
602
613
|
+ tr.station[:5].ljust(5).encode() + tr.location[:2].ljust(2).encode() + tr.channel[:3].ljust(3).encode() + tr.network[:2].ljust(2).encode()
|
|
603
614
|
+ struct.pack('>HHBBBBH', year, doy, hh, mm, ss, 0, frac)
|
|
604
615
|
+ struct.pack('>Hhh', n, fac, mult)
|
|
605
|
-
+ struct.pack('BBBB', 0, 0, 0,
|
|
616
|
+
+ struct.pack('BBBB', 0, 0, 0, 2)
|
|
606
617
|
+ struct.pack('>iHH', 0, 64, 48))
|
|
607
|
-
b1000 = struct.pack('>HHBBBB', 1000,
|
|
608
|
-
|
|
618
|
+
b1000 = struct.pack('>HHBBBB', 1000, 56, enc_code, 1, rl_log, 0)
|
|
619
|
+
b1001 = struct.pack('>HHBbBB', 1001, 0, 0, usec, 0, 0)
|
|
620
|
+
rec = (hdr + b1000 + b1001).ljust(64, b'\x00') + body
|
|
609
621
|
assert len(rec) == reclen
|
|
610
622
|
f.write(rec)
|
|
611
623
|
prev = int(data[i + n - 1]) if encoding in ('STEIM1', 'STEIM2') else None
|