gea-program 0.14.0__tar.gz → 0.16.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.14.0 → gea_program-0.16.0}/PKG-INFO +52 -4
- {gea_program-0.14.0 → gea_program-0.16.0}/README.md +51 -3
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/__init__.py +2 -1
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/__main__.py +90 -6
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/acceptance_tests.py +265 -1
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/certificates.py +31 -2
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/client_reports.py +22 -4
- gea_program-0.16.0/gea/conformance.py +230 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/doctor.py +25 -1
- gea_program-0.16.0/gea/etp.py +1027 -0
- gea_program-0.16.0/gea/etp12_schemas.json +3702 -0
- gea_program-0.16.0/gea/help/conformance.md +11 -0
- gea_program-0.16.0/gea/help/etp.md +11 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/helplib.py +2 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/patches.py +5 -2
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/service.py +18 -3
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/web/app.html +4 -4
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/workspace.py +1 -1
- {gea_program-0.14.0 → gea_program-0.16.0}/gea_program.egg-info/PKG-INFO +52 -4
- {gea_program-0.14.0 → gea_program-0.16.0}/gea_program.egg-info/SOURCES.txt +5 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/pyproject.toml +2 -2
- {gea_program-0.14.0 → gea_program-0.16.0}/LICENSE +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/accuracy_statement.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/alarm_engine.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/bench.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/blind_harness.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/med_160_sapropels.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/cli.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/config_versioning.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/correlation.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/dashboard.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/deviation.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/downhole_engine.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/drift_monitor.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/earth_model.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/example_register_map.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/fat_sat.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/files.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/follower.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/forward_model.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/gamma.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/gauge_aging.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/gauge_specs.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/geodesy.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/gravity_reference.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/TESTER_GUIDE.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/alarms.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/audit-update.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/data-in.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/doctor.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/drift.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/files.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/instruments.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/notifications.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/osdu.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/patches.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/ppdm.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/quakeml.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/quality.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/seismic.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/site.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/sites.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/sra.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/start.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/transients.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/upkeep.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/vibration.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/help/well-tests.md +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/housekeeping.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/inverse_engine.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/jobs.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/live_ports.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/loadtest.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/matplotlib_demo.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/modbus.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/model_card.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/mqtt_port.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/notify.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/opcua_port.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/operator_app.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/osdu.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/permits.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/ports.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/ppdm.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/profile_catalog.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/project.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/qt6_downhole_app.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/quakeml.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/reconciler.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/reference/libmseed_steim.provenance.json +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/rock_inventory.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/sample_record.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/sample_well_profile.csv +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/sbom.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/segy.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_array.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_assoc.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_detect.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_film.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_harmonic.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_qc.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_response.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_signature.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_track.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_uncertainty.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/seismic_unlisted.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/sensor_swap.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/service_life.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/shell.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/shut_in.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/sla_report.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/sra.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/store_forward.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/strata_join.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/supervisor.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/survey_cmd.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/survey_view.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/telemetry.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/tool_library.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/transient.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/vibration.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/well_assembler.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/well_test_validation.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/wits0.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea/witsml.py +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea_program.egg-info/dependency_links.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea_program.egg-info/entry_points.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea_program.egg-info/requires.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/gea_program.egg-info/top_level.txt +0 -0
- {gea_program-0.14.0 → gea_program-0.16.0}/setup.cfg +0 -0
- {gea_program-0.14.0 → gea_program-0.16.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.16.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
|
|
@@ -72,7 +72,7 @@ reaches a client document. Nothing unmeasured is ever reported as met.
|
|
|
72
72
|
rate-controlled replay, duplicate suppression, per-record latency.
|
|
73
73
|
- **Configuration versioning, SBOM, monthly SLA, FAT/SAT**
|
|
74
74
|
(`config_versioning.py`, `sbom.py`, `sla_report.py`, `fat_sat.py`).
|
|
75
|
-
- **Live protocol ports** (`live_ports.py`, `wits0.py`, `witsml.py`, `opcua_port.py`,
|
|
75
|
+
- **Live protocol ports** (`live_ports.py`, `wits0.py`, `witsml.py`, `etp.py`, `opcua_port.py`,
|
|
76
76
|
`mqtt_port.py`, `modbus.py`): WITS Level 0 from the drill floor (TCP connect,
|
|
77
77
|
TCP listen, serial), WITSML 1.4.1 stores (read-only, polled), OPC UA (read and
|
|
78
78
|
subscribe), MQTT (number, JSON, Sparkplug B), Modbus TCP; every message becomes
|
|
@@ -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 (337 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]")
|
|
@@ -143,7 +143,7 @@ gea swaps / gea certificates / gea notify / gea housekeeping / gea loadtest #
|
|
|
143
143
|
|
|
144
144
|
## Live data
|
|
145
145
|
|
|
146
|
-
The engine reads live data through
|
|
146
|
+
The engine reads live data through six protocol ports. All are **read-only**,
|
|
147
147
|
all map only what the site declares (a tag map the client owns; an empty map
|
|
148
148
|
is declined), and all write every received message to a JSON-lines recording
|
|
149
149
|
that `--replay` turns back into records without a connection - which is how a
|
|
@@ -156,6 +156,9 @@ gea wits0-sim --port 5001 # a WITS0 sender to rehear
|
|
|
156
156
|
gea wits0 --config wits0.json --seconds 60 --record floor/session.jsonl --out floor --stream-csv floor/stream.csv # in the first window, while the sender runs
|
|
157
157
|
gea witsml --write-example-config witsml.json # a WITSML 1.4.1 store: url, uids, mnemonics -> tags; credentials by env name
|
|
158
158
|
gea witsml --config witsml.json --seconds 60 --out store # needs a real store: the example url is a placeholder until you edit it
|
|
159
|
+
gea etp --write-example-config etp.json # a WITSML 2.x store over ETP v1.2: ws:// or wss:// url, bearer token by env name, channel URIs -> tags, units
|
|
160
|
+
gea etp-sim --port 9800 # an ETP store with two channels to rehearse with - run it in a SECOND window and leave it running
|
|
161
|
+
gea etp --config etp.json --seconds 60 --record rig/session.jsonl --out rig # subscribes; the store pushes every value as it is written
|
|
159
162
|
gea opcua --write-example-config opcua.json # edit: endpoint, security, credential env names, nodes
|
|
160
163
|
gea opcua --config opcua.json --seconds 60 --record opc/session.jsonl --out opc --stream-csv opc/stream.csv # needs a real OPC UA server, likewise
|
|
161
164
|
gea mqtt --write-example-config mqtt.json # edit: broker, TLS, credential env names, topics
|
|
@@ -167,6 +170,7 @@ gea ingest --file floor/stream.csv # a stream CSV feeds the h
|
|
|
167
170
|
|---|---|---|---|
|
|
168
171
|
| `wits0` | WITS Level 0 frames (`&&` ... `!!`, four-digit item codes) over TCP connect, TCP listen or serial; record-01 dictionary built in | numeric GOOD; sentinels (-9999, -999.25) and non-numeric -> GAP with the reason | items 0105/0106 (date, time) when present, else arrival; ingest at arrival |
|
|
169
172
|
| `witsml` | WITSML 1.4.1 SOAP store: GetVersion, GetCap, GetFromStore on one log object, rows newer than the last seen at each poll | numeric GOOD; the store's nullValue and empty fields -> GAP | the index curve of a time log; arrival for a depth log |
|
|
173
|
+
| `etp` | Energistics ETP v1.2 over WebSocket (`etp12.energistics.org`, Avro binary to the published schemas): RequestSession/OpenSession, GetChannelMetadata for the declared URIs, SubscribeChannels, ChannelData pushed by the store (Protocol 21) | numeric GOOD; a non-numeric or null value -> BAD with the reason; a channel the map does not name is counted unmapped | the store's own index: an ETP DateTime index is microseconds since the epoch; an ElapsedTime index is seconds from its declared start; a depth index leaves the arrival time standing, named |
|
|
170
174
|
| `opcua` | opc.tcp, read + subscribe; Basic256Sha256 SignAndEncrypt when a certificate and key are given | StatusCode severity bits: Good -> GOOD, Uncertain -> STALE, Bad -> GAP (value withheld) | source timestamp, else server timestamp, else arrival |
|
|
171
175
|
| `mqtt` | MQTT v5 / v3.1.1, TLS optional, QoS per topic; `+`/`#` wildcards | number: GOOD or GAP; JSON: value/time/quality paths; Sparkplug B: `is_null` -> GAP, `Quality` != 192 -> STALE | JSON time path, Sparkplug metric timestamp, else arrival |
|
|
172
176
|
| `modbus_g6` | Modbus TCP, user-supplied register map with a citation | read failures -> GAP | arrival |
|
|
@@ -619,6 +623,50 @@ promoted; the group and the support are declarations; a matched frequency
|
|
|
619
623
|
is not a fault size. CSV or miniSEED/SAC; `gea vibration` runs the labelled
|
|
620
624
|
pump; `gea help vibration`.
|
|
621
625
|
|
|
626
|
+
### WITSML 2.x over ETP
|
|
627
|
+
|
|
628
|
+
The newer rigs and stores do not poll: Energistics ETP v1.2 is a WebSocket
|
|
629
|
+
session, Avro-encoded to the published schemas, on which the customer names
|
|
630
|
+
the channels it wants and the store pushes every value as it is written.
|
|
631
|
+
`gea/etp.py` is that customer: the handshake with the subprotocol, the
|
|
632
|
+
binary encoding and the payload limits; RequestSession for Discovery, Store
|
|
633
|
+
and ChannelSubscribe and what the store answered; the channel metadata for
|
|
634
|
+
the URIs the mapping declares (a URI the store does not have is named as
|
|
635
|
+
missing); the subscription; and each ChannelData DataItem as a record under
|
|
636
|
+
the mapping's tag and unit, with the store's own index as the source time -
|
|
637
|
+
microseconds since the epoch for a DateTime index, seconds from the declared
|
|
638
|
+
start for ElapsedTime, the arrival time standing (and named) for a depth
|
|
639
|
+
index - and the arrival as the ingest time, so the latency is per record.
|
|
640
|
+
Client message ids even, the store's odd; a ProtocolException carried with
|
|
641
|
+
its code; a client or a store without the subprotocol refused at the
|
|
642
|
+
handshake. The patch supervisor runs it like every other port; the page
|
|
643
|
+
offers it; `gea etp-sim` is a store with two channels of a synthetic
|
|
644
|
+
disposal well; `gea etp --selftest` runs the codec and a loopback session;
|
|
645
|
+
`gea help etp`. The doctor now also names a panel started through the
|
|
646
|
+
`gea.exe` launcher, which pip cannot replace while it runs - stop, update,
|
|
647
|
+
start with `python -m gea serve`.
|
|
648
|
+
|
|
649
|
+
### Conformity, in the standards' words
|
|
650
|
+
|
|
651
|
+
The drift report's "bias inside the instrument's class" is a statement of
|
|
652
|
+
conformity, and ISO/IEC 17025:2017 7.8.6 says what one carries: the result it
|
|
653
|
+
applies to, the specification, and the decision rule - which has to take
|
|
654
|
+
the uncertainty into account. The report now states it that way: the tag's
|
|
655
|
+
bias over the window with its sample count, the certificate's accuracy
|
|
656
|
+
class as the tolerance limit, the bias's expanded uncertainty (k = 2) as the
|
|
657
|
+
guard band, and the ILAC-G8:09/2019 non-binary rule - PASS, CONDITIONAL
|
|
658
|
+
PASS, CONDITIONAL FAIL or FAIL, with the acceptance limit printed; without
|
|
659
|
+
an uncertainty it falls back to simple acceptance and says so. The
|
|
660
|
+
certificate register takes what 7.8.4 asks the paper to carry (the expanded
|
|
661
|
+
uncertainty with k and probability, the traceability statement as worded,
|
|
662
|
+
the conditions, the calibration date, the method, who authorised it) and
|
|
663
|
+
`gea certificates --action conformance` prints each certificate against
|
|
664
|
+
the fourteen items of 7.8.2.1 and 7.8.4.1 - CARRIED, NOT CARRIED, NOT
|
|
665
|
+
RECORDED - with COMPLETE or INCOMPLETE and the missing clauses named. The
|
|
666
|
+
well page's filing form takes the items and its table shows U (k) and the
|
|
667
|
+
standing. `gea conformance --action decide` states one decision. `gea help
|
|
668
|
+
conformance`.
|
|
669
|
+
|
|
622
670
|
### Audit / Update
|
|
623
671
|
|
|
624
672
|
The Audit / Update tab holds three things. The whole audit log
|
|
@@ -33,7 +33,7 @@ reaches a client document. Nothing unmeasured is ever reported as met.
|
|
|
33
33
|
rate-controlled replay, duplicate suppression, per-record latency.
|
|
34
34
|
- **Configuration versioning, SBOM, monthly SLA, FAT/SAT**
|
|
35
35
|
(`config_versioning.py`, `sbom.py`, `sla_report.py`, `fat_sat.py`).
|
|
36
|
-
- **Live protocol ports** (`live_ports.py`, `wits0.py`, `witsml.py`, `opcua_port.py`,
|
|
36
|
+
- **Live protocol ports** (`live_ports.py`, `wits0.py`, `witsml.py`, `etp.py`, `opcua_port.py`,
|
|
37
37
|
`mqtt_port.py`, `modbus.py`): WITS Level 0 from the drill floor (TCP connect,
|
|
38
38
|
TCP listen, serial), WITSML 1.4.1 stores (read-only, polled), OPC UA (read and
|
|
39
39
|
subscribe), MQTT (number, JSON, Sparkplug B), Modbus TCP; every message becomes
|
|
@@ -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 (337 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]")
|
|
@@ -104,7 +104,7 @@ gea swaps / gea certificates / gea notify / gea housekeeping / gea loadtest #
|
|
|
104
104
|
|
|
105
105
|
## Live data
|
|
106
106
|
|
|
107
|
-
The engine reads live data through
|
|
107
|
+
The engine reads live data through six protocol ports. All are **read-only**,
|
|
108
108
|
all map only what the site declares (a tag map the client owns; an empty map
|
|
109
109
|
is declined), and all write every received message to a JSON-lines recording
|
|
110
110
|
that `--replay` turns back into records without a connection - which is how a
|
|
@@ -117,6 +117,9 @@ gea wits0-sim --port 5001 # a WITS0 sender to rehear
|
|
|
117
117
|
gea wits0 --config wits0.json --seconds 60 --record floor/session.jsonl --out floor --stream-csv floor/stream.csv # in the first window, while the sender runs
|
|
118
118
|
gea witsml --write-example-config witsml.json # a WITSML 1.4.1 store: url, uids, mnemonics -> tags; credentials by env name
|
|
119
119
|
gea witsml --config witsml.json --seconds 60 --out store # needs a real store: the example url is a placeholder until you edit it
|
|
120
|
+
gea etp --write-example-config etp.json # a WITSML 2.x store over ETP v1.2: ws:// or wss:// url, bearer token by env name, channel URIs -> tags, units
|
|
121
|
+
gea etp-sim --port 9800 # an ETP store with two channels to rehearse with - run it in a SECOND window and leave it running
|
|
122
|
+
gea etp --config etp.json --seconds 60 --record rig/session.jsonl --out rig # subscribes; the store pushes every value as it is written
|
|
120
123
|
gea opcua --write-example-config opcua.json # edit: endpoint, security, credential env names, nodes
|
|
121
124
|
gea opcua --config opcua.json --seconds 60 --record opc/session.jsonl --out opc --stream-csv opc/stream.csv # needs a real OPC UA server, likewise
|
|
122
125
|
gea mqtt --write-example-config mqtt.json # edit: broker, TLS, credential env names, topics
|
|
@@ -128,6 +131,7 @@ gea ingest --file floor/stream.csv # a stream CSV feeds the h
|
|
|
128
131
|
|---|---|---|---|
|
|
129
132
|
| `wits0` | WITS Level 0 frames (`&&` ... `!!`, four-digit item codes) over TCP connect, TCP listen or serial; record-01 dictionary built in | numeric GOOD; sentinels (-9999, -999.25) and non-numeric -> GAP with the reason | items 0105/0106 (date, time) when present, else arrival; ingest at arrival |
|
|
130
133
|
| `witsml` | WITSML 1.4.1 SOAP store: GetVersion, GetCap, GetFromStore on one log object, rows newer than the last seen at each poll | numeric GOOD; the store's nullValue and empty fields -> GAP | the index curve of a time log; arrival for a depth log |
|
|
134
|
+
| `etp` | Energistics ETP v1.2 over WebSocket (`etp12.energistics.org`, Avro binary to the published schemas): RequestSession/OpenSession, GetChannelMetadata for the declared URIs, SubscribeChannels, ChannelData pushed by the store (Protocol 21) | numeric GOOD; a non-numeric or null value -> BAD with the reason; a channel the map does not name is counted unmapped | the store's own index: an ETP DateTime index is microseconds since the epoch; an ElapsedTime index is seconds from its declared start; a depth index leaves the arrival time standing, named |
|
|
131
135
|
| `opcua` | opc.tcp, read + subscribe; Basic256Sha256 SignAndEncrypt when a certificate and key are given | StatusCode severity bits: Good -> GOOD, Uncertain -> STALE, Bad -> GAP (value withheld) | source timestamp, else server timestamp, else arrival |
|
|
132
136
|
| `mqtt` | MQTT v5 / v3.1.1, TLS optional, QoS per topic; `+`/`#` wildcards | number: GOOD or GAP; JSON: value/time/quality paths; Sparkplug B: `is_null` -> GAP, `Quality` != 192 -> STALE | JSON time path, Sparkplug metric timestamp, else arrival |
|
|
133
137
|
| `modbus_g6` | Modbus TCP, user-supplied register map with a citation | read failures -> GAP | arrival |
|
|
@@ -580,6 +584,50 @@ promoted; the group and the support are declarations; a matched frequency
|
|
|
580
584
|
is not a fault size. CSV or miniSEED/SAC; `gea vibration` runs the labelled
|
|
581
585
|
pump; `gea help vibration`.
|
|
582
586
|
|
|
587
|
+
### WITSML 2.x over ETP
|
|
588
|
+
|
|
589
|
+
The newer rigs and stores do not poll: Energistics ETP v1.2 is a WebSocket
|
|
590
|
+
session, Avro-encoded to the published schemas, on which the customer names
|
|
591
|
+
the channels it wants and the store pushes every value as it is written.
|
|
592
|
+
`gea/etp.py` is that customer: the handshake with the subprotocol, the
|
|
593
|
+
binary encoding and the payload limits; RequestSession for Discovery, Store
|
|
594
|
+
and ChannelSubscribe and what the store answered; the channel metadata for
|
|
595
|
+
the URIs the mapping declares (a URI the store does not have is named as
|
|
596
|
+
missing); the subscription; and each ChannelData DataItem as a record under
|
|
597
|
+
the mapping's tag and unit, with the store's own index as the source time -
|
|
598
|
+
microseconds since the epoch for a DateTime index, seconds from the declared
|
|
599
|
+
start for ElapsedTime, the arrival time standing (and named) for a depth
|
|
600
|
+
index - and the arrival as the ingest time, so the latency is per record.
|
|
601
|
+
Client message ids even, the store's odd; a ProtocolException carried with
|
|
602
|
+
its code; a client or a store without the subprotocol refused at the
|
|
603
|
+
handshake. The patch supervisor runs it like every other port; the page
|
|
604
|
+
offers it; `gea etp-sim` is a store with two channels of a synthetic
|
|
605
|
+
disposal well; `gea etp --selftest` runs the codec and a loopback session;
|
|
606
|
+
`gea help etp`. The doctor now also names a panel started through the
|
|
607
|
+
`gea.exe` launcher, which pip cannot replace while it runs - stop, update,
|
|
608
|
+
start with `python -m gea serve`.
|
|
609
|
+
|
|
610
|
+
### Conformity, in the standards' words
|
|
611
|
+
|
|
612
|
+
The drift report's "bias inside the instrument's class" is a statement of
|
|
613
|
+
conformity, and ISO/IEC 17025:2017 7.8.6 says what one carries: the result it
|
|
614
|
+
applies to, the specification, and the decision rule - which has to take
|
|
615
|
+
the uncertainty into account. The report now states it that way: the tag's
|
|
616
|
+
bias over the window with its sample count, the certificate's accuracy
|
|
617
|
+
class as the tolerance limit, the bias's expanded uncertainty (k = 2) as the
|
|
618
|
+
guard band, and the ILAC-G8:09/2019 non-binary rule - PASS, CONDITIONAL
|
|
619
|
+
PASS, CONDITIONAL FAIL or FAIL, with the acceptance limit printed; without
|
|
620
|
+
an uncertainty it falls back to simple acceptance and says so. The
|
|
621
|
+
certificate register takes what 7.8.4 asks the paper to carry (the expanded
|
|
622
|
+
uncertainty with k and probability, the traceability statement as worded,
|
|
623
|
+
the conditions, the calibration date, the method, who authorised it) and
|
|
624
|
+
`gea certificates --action conformance` prints each certificate against
|
|
625
|
+
the fourteen items of 7.8.2.1 and 7.8.4.1 - CARRIED, NOT CARRIED, NOT
|
|
626
|
+
RECORDED - with COMPLETE or INCOMPLETE and the missing clauses named. The
|
|
627
|
+
well page's filing form takes the items and its table shows U (k) and the
|
|
628
|
+
standing. `gea conformance --action decide` states one decision. `gea help
|
|
629
|
+
conformance`.
|
|
630
|
+
|
|
583
631
|
### Audit / Update
|
|
584
632
|
|
|
585
633
|
The Audit / Update tab holds three things. The whole audit log
|
|
@@ -87,6 +87,7 @@ from .opcua_port import ASYNCUA_AVAILABLE, OpcUaTap # registers the 'op
|
|
|
87
87
|
from .mqtt_port import PAHO_AVAILABLE, MqttTap # registers the 'mqtt' port at import
|
|
88
88
|
from .wits0 import Wits0Tap, SERIAL_AVAILABLE # registers the 'wits0' port at import
|
|
89
89
|
from .witsml import WitsmlTap # registers the 'witsml' port at import
|
|
90
|
+
from .etp import EtpTap # registers the 'etp' port at import (WITSML 2.x over ETP v1.2)
|
|
90
91
|
from .well_assembler import (
|
|
91
92
|
WellAssembly, WellComponent, assemble, assemble_ktb_hb, assemble_odp_504b,
|
|
92
93
|
assemble_site_1027, assemble_u1324, BUILTIN_ASSEMBLIES,
|
|
@@ -122,7 +123,7 @@ from .profile_catalog import (
|
|
|
122
123
|
read_pangaea_txt,
|
|
123
124
|
)
|
|
124
125
|
|
|
125
|
-
__version__ = "0.
|
|
126
|
+
__version__ = "0.16.0"
|
|
126
127
|
__all__ = [
|
|
127
128
|
"aging_rate", "rate_psi_yr", "accuracy_psi",
|
|
128
129
|
"Sensor", "SimulatorConfig", "DownholeEngine",
|
|
@@ -265,7 +265,8 @@ def main(argv=None) -> int:
|
|
|
265
265
|
for name, helptxt in (("opcua", "OPC UA client port: read once or subscribe; record; replay a recording offline"),
|
|
266
266
|
("mqtt", "MQTT subscriber port (3.1.1/5.0; number | json | Sparkplug B): run; record; replay offline"),
|
|
267
267
|
("wits0", "WITS Level 0 port (drill floor: mud logger / EDR) over TCP connect, TCP listen or serial: run; record; replay offline"),
|
|
268
|
-
("witsml", "WITSML 1.4.1 read-only client: poll a log object from the store; record; replay offline")
|
|
268
|
+
("witsml", "WITSML 1.4.1 read-only client: poll a log object from the store; record; replay offline"),
|
|
269
|
+
("etp", "WITSML 2.x over Energistics ETP v1.2 (WebSocket, Avro): subscribe to channels and the store pushes; record; replay the session's shape")):
|
|
269
270
|
p_lp = sub.add_parser(name, help=helptxt)
|
|
270
271
|
p_lp.add_argument("--config", type=str, default=None, help="site map JSON (client-owned)")
|
|
271
272
|
p_lp.add_argument("--write-example-config", type=str, default=None, help="write an example map here and exit")
|
|
@@ -275,6 +276,7 @@ def main(argv=None) -> int:
|
|
|
275
276
|
p_lp.add_argument("--read-once", action="store_true", help="opcua: one Read of all nodes instead of a subscription")
|
|
276
277
|
p_lp.add_argument("--out", type=str, default=None, help="write the records CSV here")
|
|
277
278
|
p_lp.add_argument("--stream-csv", type=str, default=None, help="also write a historian-style CSV the other commands ingest")
|
|
279
|
+
p_lp.add_argument("--selftest", action="store_true", help="etp: the codec round-trip and a session against the simulated store on the loopback")
|
|
278
280
|
|
|
279
281
|
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
282
|
p_ws.add_argument("--path", type=str, required=True, help="the workspace folder")
|
|
@@ -400,6 +402,11 @@ def main(argv=None) -> int:
|
|
|
400
402
|
p_us.add_argument("--password-env", type=str, default="GEA_PASSWORD", help="environment variable holding the password (never a flag, never on the command line)")
|
|
401
403
|
p_us.add_argument("--actor", type=str, default="cli")
|
|
402
404
|
|
|
405
|
+
p_es = sub.add_parser("etp-sim", help="an ETP v1.2 store for testing a patch without a rig: two channels of a synthetic disposal well, pushed as a customer subscribes")
|
|
406
|
+
p_es.add_argument("--port", type=int, default=9800)
|
|
407
|
+
p_es.add_argument("--frames", type=int, default=600)
|
|
408
|
+
p_es.add_argument("--interval", type=float, default=1.0, help="seconds between samples")
|
|
409
|
+
p_es.add_argument("--seed", type=int, default=1)
|
|
403
410
|
p_w0 = sub.add_parser("wits0-sim", help="a WITS0 sender for testing a patch without a rig: listens once, then streams a deterministic drilling sequence")
|
|
404
411
|
p_w0.add_argument("--port", type=int, default=5001)
|
|
405
412
|
p_w0.add_argument("--frames", type=int, default=600)
|
|
@@ -409,6 +416,14 @@ def main(argv=None) -> int:
|
|
|
409
416
|
|
|
410
417
|
p_osdu = sub.add_parser("osdu", help="the OSDU-shaped export: the self-test on a labelled site")
|
|
411
418
|
p_osdu.add_argument("--action", choices=["selftest"], default="selftest")
|
|
419
|
+
p_cf = sub.add_parser("conformance", help="ISO/IEC 17025 7.8 certificate items and the ILAC-G8 decision rules: the self-test, or one decision")
|
|
420
|
+
p_cf.add_argument("--action", choices=["selftest", "decide"], default="selftest")
|
|
421
|
+
p_cf.add_argument("--value", type=float, default=None, help="decide: the measured value (a deviation; the tolerance is symmetric)")
|
|
422
|
+
p_cf.add_argument("--tolerance", type=float, default=None, help="decide: the tolerance limit TL")
|
|
423
|
+
p_cf.add_argument("--uncertainty", type=float, default=None, help="decide: the expanded uncertainty U of the value (omit: simple acceptance)")
|
|
424
|
+
p_cf.add_argument("--k", type=float, default=2.0)
|
|
425
|
+
p_cf.add_argument("--rule", choices=["simple-acceptance", "binary-guard-band", "non-binary-guard-band"], default="non-binary-guard-band")
|
|
426
|
+
p_cf.add_argument("--unit", type=str, default="")
|
|
412
427
|
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
428
|
p_vib.add_argument("--action", choices=["selftest", "assess"], default="selftest")
|
|
414
429
|
p_vib.add_argument("--record", type=str, default=None, help="assess: the record (CSV with a time column, or miniSEED/SAC)")
|
|
@@ -522,7 +537,7 @@ def main(argv=None) -> int:
|
|
|
522
537
|
|
|
523
538
|
p_ce = sub.add_parser("certificates", help="calibration certificates per instrument: list, file one, status against today")
|
|
524
539
|
p_ce.add_argument("--register", type=str, required=True, help="the well's certificates.jsonl")
|
|
525
|
-
p_ce.add_argument("--action", choices=["list", "add", "status"], default="list")
|
|
540
|
+
p_ce.add_argument("--action", choices=["list", "add", "status", "conformance"], default="list")
|
|
526
541
|
p_ce.add_argument("--tag", type=str, default=None)
|
|
527
542
|
p_ce.add_argument("--tags", type=str, default=None, help="comma-separated tags for --action status")
|
|
528
543
|
p_ce.add_argument("--serial", type=str, default="")
|
|
@@ -536,6 +551,17 @@ def main(argv=None) -> int:
|
|
|
536
551
|
p_ce.add_argument("--doc", type=str, default=None, help="the certificate file (hashed, not copied)")
|
|
537
552
|
p_ce.add_argument("--note", type=str, default="")
|
|
538
553
|
p_ce.add_argument("--actor", type=str, default="cli")
|
|
554
|
+
p_ce.add_argument("--calibrated", type=str, default="", help="ISO/IEC 17025 7.8.2.1 i: the date the calibration was performed")
|
|
555
|
+
p_ce.add_argument("--method", type=str, default="", help="7.8.2.1 f: the method used")
|
|
556
|
+
p_ce.add_argument("--authorised-by", type=str, default="", help="7.8.2.1 o: who authorised the certificate")
|
|
557
|
+
p_ce.add_argument("--uncertainty", type=float, default=None, help="7.8.4.1 a: the expanded uncertainty U, in --uncertainty-unit (default the result's unit)")
|
|
558
|
+
p_ce.add_argument("--uncertainty-unit", type=str, default="")
|
|
559
|
+
p_ce.add_argument("--k", type=float, default=None, help="7.8.4.1 a: the coverage factor U is stated at")
|
|
560
|
+
p_ce.add_argument("--probability", type=float, default=None, help="7.8.4.1 a: the coverage probability as a fraction (0.95)")
|
|
561
|
+
p_ce.add_argument("--conditions", type=str, default="", help="7.8.4.1 b: the conditions the calibration was made under")
|
|
562
|
+
p_ce.add_argument("--traceability", type=str, default="", help="7.8.4.1 c: the statement of metrological traceability, as the certificate words it")
|
|
563
|
+
p_ce.add_argument("--adjustment", type=str, default="", help="7.8.4.1 d: results before and after adjustment, if the certificate carries them")
|
|
564
|
+
p_ce.add_argument("--decision-rule", type=str, default="", help="7.8.6: the decision rule the certificate's conformity statement names, if any")
|
|
539
565
|
|
|
540
566
|
p_tr = sub.add_parser("transient", help="shut-in detection and build-up analysis (Horner + Bourdet derivative with a bootstrap band)")
|
|
541
567
|
p_tr.add_argument("--file", type=str, required=True, help="historian file")
|
|
@@ -773,7 +799,10 @@ def main(argv=None) -> int:
|
|
|
773
799
|
if a.action == "add":
|
|
774
800
|
try:
|
|
775
801
|
print(_json.dumps(reg.add(a.tag or "", a.serial, a.certificate, a.issued or "", a.valid_until or "", a.actor, a.lab,
|
|
776
|
-
a.accuracy_pct_fs, a.full_scale, a.unit, a.doc, a.note
|
|
802
|
+
a.accuracy_pct_fs, a.full_scale, a.unit, a.doc, a.note,
|
|
803
|
+
calibrated_utc=a.calibrated, method=a.method, authorised_by=a.authorised_by, uncertainty=a.uncertainty,
|
|
804
|
+
uncertainty_unit=a.uncertainty_unit, uncertainty_k=a.k, uncertainty_probability=a.probability,
|
|
805
|
+
conditions=a.conditions, traceability=a.traceability, adjustment=a.adjustment, decision_rule=a.decision_rule), indent=1))
|
|
777
806
|
except (ValueError, TypeError) as e:
|
|
778
807
|
raise SystemExit(f"certificates: {e}")
|
|
779
808
|
return 0
|
|
@@ -784,6 +813,13 @@ def main(argv=None) -> int:
|
|
|
784
813
|
print(f"{r['tag_id']:24s} {r['status']:9s} {r.get('certificate_id') or '-':16s} until {r.get('valid_until_utc') or '-'} {('' if r['days_left'] is None else str(r['days_left']) + ' d')}")
|
|
785
814
|
print(_json.dumps(CertificateRegister.summary(rows)))
|
|
786
815
|
return 0 if CertificateRegister.summary(rows)['all_valid'] else 1
|
|
816
|
+
if a.action == "conformance":
|
|
817
|
+
from .conformance import report_lines
|
|
818
|
+
c = reg.conformance()
|
|
819
|
+
for r in c["rows"]:
|
|
820
|
+
print("\n".join(report_lines(r)))
|
|
821
|
+
print(f"certificates: {c['n']} filed, {c['complete']} COMPLETE against ISO/IEC 17025:2017 7.8" + (f"; incomplete: {', '.join(c['incomplete'])}" if c['incomplete'] else ''))
|
|
822
|
+
return 0 if not c["incomplete"] else 1
|
|
787
823
|
for e in reg.list():
|
|
788
824
|
print(f"{e['tag_id']:24s} {e['serial']:12s} {e['certificate_id']:16s} {e['issued_utc'][:10]} to {e['valid_until_utc'][:10]} ±{e.get('accuracy_pct_fs') or '-'} % FS {e.get('lab', '')}")
|
|
789
825
|
print(f"certificates: {len(reg.list())} filed")
|
|
@@ -1524,6 +1560,23 @@ def main(argv=None) -> int:
|
|
|
1524
1560
|
return 0
|
|
1525
1561
|
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)"))
|
|
1526
1562
|
return 0
|
|
1563
|
+
elif a.cmd == "conformance":
|
|
1564
|
+
from . import conformance as _C
|
|
1565
|
+
if a.action == "decide":
|
|
1566
|
+
if a.value is None or a.tolerance is None:
|
|
1567
|
+
raise SystemExit("conformance --action decide needs --value and --tolerance")
|
|
1568
|
+
d = _C.decide(a.value, a.tolerance, a.uncertainty, rule=a.rule, k=a.k if a.uncertainty is not None else None,
|
|
1569
|
+
probability=(0.95 if abs(a.k - 2.0) < 1e-9 else None) if a.uncertainty is not None else None, unit=a.unit)
|
|
1570
|
+
print(d["statement"]); print(f" {d['rule_text']}")
|
|
1571
|
+
return 0 if d["outcome"] in ("PASS", "CONDITIONAL PASS") else 1
|
|
1572
|
+
r = _C.selftest()
|
|
1573
|
+
print(f"conformance selftest [{r['label']}]: {r['status']}")
|
|
1574
|
+
for k, v in r["checks"].items():
|
|
1575
|
+
print(f" {'ok ' if v else 'BAD'} {k}")
|
|
1576
|
+
print("\n".join(_C.report_lines(r["full"])))
|
|
1577
|
+
for d in r["decisions"]:
|
|
1578
|
+
print(" " + d["statement"])
|
|
1579
|
+
return 0 if r["status"] == "OK" else 1
|
|
1527
1580
|
elif a.cmd == "vibration":
|
|
1528
1581
|
from . import vibration as _V
|
|
1529
1582
|
if a.action == "assess":
|
|
@@ -1920,10 +1973,30 @@ def main(argv=None) -> int:
|
|
|
1920
1973
|
stop.set()
|
|
1921
1974
|
print("wits0-sim: stopped")
|
|
1922
1975
|
return 0
|
|
1923
|
-
elif a.cmd
|
|
1976
|
+
elif a.cmd == "etp-sim":
|
|
1977
|
+
from . import etp as _E
|
|
1978
|
+
th, port, stop = _E.simulate_store(port=a.port, frames=a.frames, interval_s=a.interval, seed=a.seed, verbose=True)
|
|
1979
|
+
print(f"etp-sim: an ETP v1.2 store listening on ws://127.0.0.1:{port}/ - this window is the STORE and stays here; nothing happens until a customer connects.\n"
|
|
1980
|
+
f" Open a SECOND window and run: gea etp --config etp.json --seconds 60 --out floor (with etp.json: url ws://127.0.0.1:{port}/ and the two example channel URIs)\n"
|
|
1981
|
+
f" or on the dashboard: Patch panel -> Add a patch -> etp, url ws://127.0.0.1:{port}/. Then it pushes {a.frames} samples per channel {a.interval:g} s apart. Ctrl+C stops it.", flush=True)
|
|
1982
|
+
try:
|
|
1983
|
+
while th.is_alive():
|
|
1984
|
+
th.join(0.5)
|
|
1985
|
+
except KeyboardInterrupt:
|
|
1986
|
+
stop.set()
|
|
1987
|
+
print("etp-sim: stopped")
|
|
1988
|
+
return 0
|
|
1989
|
+
elif a.cmd in ("opcua", "mqtt", "wits0", "witsml", "etp"):
|
|
1924
1990
|
import json as _json
|
|
1925
1991
|
from .live_ports import records_to_stream, summarize, write_records_csv
|
|
1926
|
-
mod = __import__({"opcua": "gea.opcua_port", "mqtt": "gea.mqtt_port", "wits0": "gea.wits0", "witsml": "gea.witsml"}[a.cmd], fromlist=["x"])
|
|
1992
|
+
mod = __import__({"opcua": "gea.opcua_port", "mqtt": "gea.mqtt_port", "wits0": "gea.wits0", "witsml": "gea.witsml", "etp": "gea.etp"}[a.cmd], fromlist=["x"])
|
|
1993
|
+
if a.cmd == "etp" and getattr(a, "selftest", False):
|
|
1994
|
+
r = mod.selftest()
|
|
1995
|
+
print(f"etp selftest [{r['label']}]: {r['status']}")
|
|
1996
|
+
for k, v in r["checks"].items():
|
|
1997
|
+
print(f" {'ok ' if v else 'BAD'} {k}")
|
|
1998
|
+
print(f" {r['n_records']} record(s) on {r['tags']}; store {r['store'].get('application')} protocols {r['store'].get('protocols')}; counts {r['counts']}")
|
|
1999
|
+
return 0 if r["status"] == "OK" else 1
|
|
1927
2000
|
if a.write_example_config:
|
|
1928
2001
|
print("config:", mod.write_example_config(a.write_example_config))
|
|
1929
2002
|
return 0
|
|
@@ -1948,6 +2021,11 @@ def main(argv=None) -> int:
|
|
|
1948
2021
|
tap = mod.Wits0Tap(a.config, recording_path=a.record)
|
|
1949
2022
|
recs = tap.run(a.seconds)
|
|
1950
2023
|
src = f"{tap.cfg['transport']} {tap.cfg.get('host') or tap.cfg.get('device') or ('listen:' + str(tap.cfg.get('listen_port')))}"
|
|
2024
|
+
elif a.cmd == "etp":
|
|
2025
|
+
tap = mod.EtpTap(a.config, recording_path=a.record)
|
|
2026
|
+
recs = tap.run(a.seconds)
|
|
2027
|
+
src = tap.cfg["url"] + (f" (store: {tap.state.get('store', {}).get('application')}, {tap.state.get('channels')} channel(s) subscribed"
|
|
2028
|
+
+ (f", missing {tap.state.get('missing_uris')}" if tap.state.get('missing_uris') else '') + ')')
|
|
1951
2029
|
else:
|
|
1952
2030
|
tap = mod.WitsmlTap(a.config, recording_path=a.record)
|
|
1953
2031
|
recs = tap.run(a.seconds)
|
|
@@ -1955,11 +2033,17 @@ def main(argv=None) -> int:
|
|
|
1955
2033
|
except (NotImplementedError, ConnectionError, ValueError) as e:
|
|
1956
2034
|
hint = {"wits0": "nothing is sending on that host:port - start `gea wits0-sim --port 5001` in a SECOND window first (it must be running while this reads), or point the config at the rig's real WITS0 feed",
|
|
1957
2035
|
"witsml": "no WITSML store answers at that url - the example config points at 127.0.0.1:8000, a placeholder; put the real store's url, uids and credential env names in it",
|
|
2036
|
+
"etp": "no ETP store answers at that url - start `gea etp-sim --port 9800` in a SECOND window first, or point the config at the rig's ETP endpoint (wss://...) with the channel URIs it publishes",
|
|
1958
2037
|
"opcua": "no OPC UA server answers at that endpoint - the example config is a placeholder; put the real server's endpoint, security and node ids in it",
|
|
1959
2038
|
"mqtt": "no MQTT broker answers at that host:port - the example config is a placeholder; put the real broker in it"}.get(a.cmd, "")
|
|
1960
2039
|
raise SystemExit(f"{a.cmd}: {e}" + (f"\n {hint}" if hint else "")) # the reason and what to do, without a traceback
|
|
1961
2040
|
print(f"{a.cmd}: {src}")
|
|
1962
|
-
|
|
2041
|
+
if a.cmd == "etp" and a.replay:
|
|
2042
|
+
shape = getattr(mod.replay, "summary", {})
|
|
2043
|
+
print(_json.dumps({"session_shape": shape, "records": 0,
|
|
2044
|
+
"note": "an ETP recording holds the messages as received with ChannelData as counts (the samples went to --out); the replay reproduces the session's shape, not the samples"}, indent=1))
|
|
2045
|
+
else:
|
|
2046
|
+
print(_json.dumps(summarize(recs), indent=1))
|
|
1963
2047
|
if a.out:
|
|
1964
2048
|
print(" records:", write_records_csv(recs, a.out))
|
|
1965
2049
|
if a.stream_csv and recs:
|