gea-program 0.1.0__tar.gz → 0.3.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.
Files changed (183) hide show
  1. gea_program-0.3.0/PKG-INFO +271 -0
  2. gea_program-0.3.0/README.md +232 -0
  3. {gea_program-0.1.0 → gea_program-0.3.0}/gea/BENCH_TEST_PROTOCOL.md +2 -3
  4. {gea_program-0.1.0 → gea_program-0.3.0}/gea/__init__.py +7 -5
  5. {gea_program-0.1.0 → gea_program-0.3.0}/gea/__main__.py +232 -2
  6. {gea_program-0.1.0 → gea_program-0.3.0}/gea/acceptance_tests.py +605 -42
  7. {gea_program-0.1.0 → gea_program-0.3.0}/gea/alarm_engine.py +43 -1
  8. {gea_program-0.1.0 → gea_program-0.3.0}/gea/bench.py +1 -1
  9. {gea_program-0.1.0 → gea_program-0.3.0}/gea/blind_harness.py +5 -5
  10. {gea_program-0.1.0 → gea_program-0.3.0}/gea/case_study.py +13 -14
  11. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +1 -1
  12. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +1 -1
  13. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +1 -1
  14. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +1 -1
  15. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +2 -2
  16. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +1 -1
  17. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +1 -1
  18. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +1 -1
  19. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +2 -2
  20. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +1 -1
  21. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +2 -2
  22. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +1 -1
  23. {gea_program-0.1.0 → gea_program-0.3.0}/gea/client_reports.py +11 -8
  24. {gea_program-0.1.0 → gea_program-0.3.0}/gea/correlation.py +2 -2
  25. {gea_program-0.1.0 → gea_program-0.3.0}/gea/dashboard.py +8 -3
  26. {gea_program-0.1.0 → gea_program-0.3.0}/gea/deviation.py +1 -1
  27. {gea_program-0.1.0 → gea_program-0.3.0}/gea/downhole_engine.py +14 -15
  28. {gea_program-0.1.0 → gea_program-0.3.0}/gea/earth_model.py +1 -2
  29. {gea_program-0.1.0 → gea_program-0.3.0}/gea/example_register_map.json +1 -1
  30. {gea_program-0.1.0 → gea_program-0.3.0}/gea/fat_sat.py +3 -0
  31. {gea_program-0.1.0 → gea_program-0.3.0}/gea/follower.py +6 -6
  32. {gea_program-0.1.0 → gea_program-0.3.0}/gea/forward_model.py +11 -13
  33. {gea_program-0.1.0 → gea_program-0.3.0}/gea/gamma.py +3 -3
  34. {gea_program-0.1.0 → gea_program-0.3.0}/gea/gauge_specs.py +8 -8
  35. {gea_program-0.1.0 → gea_program-0.3.0}/gea/gravity_reference.py +4 -5
  36. {gea_program-0.1.0 → gea_program-0.3.0}/gea/inverse_engine.py +2 -2
  37. gea_program-0.3.0/gea/jobs.py +297 -0
  38. gea_program-0.3.0/gea/live_ports.py +218 -0
  39. {gea_program-0.1.0 → gea_program-0.3.0}/gea/matplotlib_demo.py +2 -2
  40. {gea_program-0.1.0 → gea_program-0.3.0}/gea/modbus.py +8 -8
  41. {gea_program-0.1.0 → gea_program-0.3.0}/gea/model_card.py +1 -1
  42. gea_program-0.3.0/gea/mqtt_port.py +538 -0
  43. gea_program-0.3.0/gea/opcua_port.py +280 -0
  44. {gea_program-0.1.0 → gea_program-0.3.0}/gea/operator_app.py +10 -10
  45. gea_program-0.3.0/gea/patches.py +462 -0
  46. {gea_program-0.1.0 → gea_program-0.3.0}/gea/ports.py +9 -9
  47. {gea_program-0.1.0 → gea_program-0.3.0}/gea/profile_catalog.py +20 -20
  48. {gea_program-0.1.0 → gea_program-0.3.0}/gea/project.py +3 -3
  49. {gea_program-0.1.0 → gea_program-0.3.0}/gea/qt6_downhole_app.py +8 -9
  50. {gea_program-0.1.0 → gea_program-0.3.0}/gea/quartz_hpht_extension.py +17 -17
  51. {gea_program-0.1.0 → gea_program-0.3.0}/gea/reconciler.py +3 -3
  52. {gea_program-0.1.0 → gea_program-0.3.0}/gea/rock_inventory.py +33 -58
  53. {gea_program-0.1.0 → gea_program-0.3.0}/gea/sample_record.py +2 -2
  54. {gea_program-0.1.0 → gea_program-0.3.0}/gea/sbom.py +3 -1
  55. {gea_program-0.1.0 → gea_program-0.3.0}/gea/segy.py +2 -2
  56. gea_program-0.3.0/gea/service.py +992 -0
  57. {gea_program-0.1.0 → gea_program-0.3.0}/gea/service_life.py +7 -7
  58. {gea_program-0.1.0 → gea_program-0.3.0}/gea/strata_join.py +1 -1
  59. {gea_program-0.1.0 → gea_program-0.3.0}/gea/survey_cmd.py +3 -4
  60. {gea_program-0.1.0 → gea_program-0.3.0}/gea/survey_view.py +2 -5
  61. {gea_program-0.1.0 → gea_program-0.3.0}/gea/telemetry.py +1 -1
  62. {gea_program-0.1.0 → gea_program-0.3.0}/gea/tool_library.py +9 -9
  63. gea_program-0.3.0/gea/web/app.html +388 -0
  64. {gea_program-0.1.0 → gea_program-0.3.0}/gea/well_assembler.py +12 -13
  65. gea_program-0.3.0/gea/wits0.py +397 -0
  66. gea_program-0.3.0/gea/witsml.py +402 -0
  67. gea_program-0.3.0/gea/workspace.py +358 -0
  68. gea_program-0.3.0/gea_program.egg-info/PKG-INFO +271 -0
  69. {gea_program-0.1.0 → gea_program-0.3.0}/gea_program.egg-info/SOURCES.txt +10 -1
  70. gea_program-0.3.0/gea_program.egg-info/requires.txt +29 -0
  71. {gea_program-0.1.0 → gea_program-0.3.0}/pyproject.toml +7 -2
  72. {gea_program-0.1.0 → gea_program-0.3.0}/tests/test_acceptance.py +7 -6
  73. gea_program-0.1.0/PKG-INFO +0 -138
  74. gea_program-0.1.0/README.md +0 -112
  75. gea_program-0.1.0/gea/IMPORT_RECORD.md +0 -61
  76. gea_program-0.1.0/gea_program.egg-info/PKG-INFO +0 -138
  77. gea_program-0.1.0/gea_program.egg-info/requires.txt +0 -11
  78. {gea_program-0.1.0 → gea_program-0.3.0}/LICENSE +0 -0
  79. {gea_program-0.1.0 → gea_program-0.3.0}/gea/accuracy_statement.py +0 -0
  80. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
  81. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
  82. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
  83. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
  84. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
  85. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
  86. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
  87. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
  88. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
  89. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
  90. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
  91. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
  92. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
  93. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
  94. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
  95. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
  96. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
  97. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
  98. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
  99. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
  100. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
  101. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
  102. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
  103. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
  104. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
  105. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
  106. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
  107. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
  108. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
  109. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
  110. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
  111. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
  112. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
  113. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
  114. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
  115. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
  116. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
  117. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
  118. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
  119. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
  120. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
  121. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
  122. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
  123. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
  124. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
  125. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
  126. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
  127. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
  128. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
  129. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
  130. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
  131. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
  132. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
  133. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
  134. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
  135. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
  136. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
  137. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
  138. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
  139. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/med_160_sapropels.txt +0 -0
  140. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
  141. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
  142. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
  143. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
  144. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
  145. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
  146. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
  147. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
  148. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
  149. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
  150. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
  151. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
  152. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
  153. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
  154. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
  155. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
  156. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
  157. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
  158. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
  159. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
  160. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
  161. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
  162. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
  163. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
  164. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
  165. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
  166. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
  167. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
  168. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
  169. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
  170. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
  171. {gea_program-0.1.0 → gea_program-0.3.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
  172. {gea_program-0.1.0 → gea_program-0.3.0}/gea/cli.py +0 -0
  173. {gea_program-0.1.0 → gea_program-0.3.0}/gea/config_versioning.py +0 -0
  174. {gea_program-0.1.0 → gea_program-0.3.0}/gea/drift_monitor.py +0 -0
  175. {gea_program-0.1.0 → gea_program-0.3.0}/gea/sample_well_profile.csv +0 -0
  176. {gea_program-0.1.0 → gea_program-0.3.0}/gea/shell.py +0 -0
  177. {gea_program-0.1.0 → gea_program-0.3.0}/gea/sla_report.py +0 -0
  178. {gea_program-0.1.0 → gea_program-0.3.0}/gea/store_forward.py +0 -0
  179. {gea_program-0.1.0 → gea_program-0.3.0}/gea/well_test_validation.py +0 -0
  180. {gea_program-0.1.0 → gea_program-0.3.0}/gea_program.egg-info/dependency_links.txt +0 -0
  181. {gea_program-0.1.0 → gea_program-0.3.0}/gea_program.egg-info/entry_points.txt +0 -0
  182. {gea_program-0.1.0 → gea_program-0.3.0}/gea_program.egg-info/top_level.txt +0 -0
  183. {gea_program-0.1.0 → gea_program-0.3.0}/setup.cfg +0 -0
@@ -0,0 +1,271 @@
1
+ Metadata-Version: 2.4
2
+ Name: gea-program
3
+ Version: 0.3.0
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
+ Author: Daniel T. Murphy
6
+ License: MPL-2.0
7
+ Project-URL: Homepage, https://github.com/Daniel8Murphy0007/GEA-Program
8
+ Project-URL: Source, https://github.com/Daniel8Murphy0007/GEA-Program
9
+ Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Topic :: Scientific/Engineering
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: numpy>=1.24
18
+ Provides-Extra: plotting
19
+ Requires-Dist: matplotlib>=3.7; extra == "plotting"
20
+ Provides-Extra: desktop
21
+ Requires-Dist: PyQt6>=6.5; extra == "desktop"
22
+ Requires-Dist: matplotlib>=3.7; extra == "desktop"
23
+ Provides-Extra: modbus
24
+ Requires-Dist: pymodbus>=3.0; extra == "modbus"
25
+ Provides-Extra: opcua
26
+ Requires-Dist: asyncua>=1.0; extra == "opcua"
27
+ Provides-Extra: mqtt
28
+ Requires-Dist: paho-mqtt>=2.0; extra == "mqtt"
29
+ Provides-Extra: serial
30
+ Requires-Dist: pyserial>=3.5; extra == "serial"
31
+ Provides-Extra: live
32
+ Requires-Dist: asyncua>=1.0; extra == "live"
33
+ Requires-Dist: paho-mqtt>=2.0; extra == "live"
34
+ Requires-Dist: pymodbus>=3.0; extra == "live"
35
+ Requires-Dist: pyserial>=3.5; extra == "live"
36
+ Provides-Extra: xls
37
+ Requires-Dist: xlrd>=2.0; extra == "xls"
38
+ Dynamic: license-file
39
+
40
+ # GEA-Program
41
+
42
+ Downhole gauge monitoring for production operations: the program takes a well's
43
+ historian data and returns the reports a client engineer reads, in the outline
44
+ and language of a production-operations scope of work.
45
+
46
+ Every number in every report is recomputed from the source data at generation
47
+ time. Reports are gated for vocabulary: the program's internal register never
48
+ reaches a client document. Nothing unmeasured is ever reported as met.
49
+
50
+ ## What it does
51
+
52
+ - **Canonical measurement record** (`gea/sample_record.py`): one record shape for
53
+ every sample - tag, UTC timestamp, value, unit, quality flag, the rule and limit
54
+ that fired, source layer, ingest timestamp. Quality rules: RANGE / ROC /
55
+ FLATLINE / SPIKE / STALE / GAP; ranges from the gauge datasheet, cited.
56
+ - **Gauge drift and reconciliation** (`reconciler.py`, `drift_monitor.py`): the
57
+ live pressure series against the well baseline; classification with the
58
+ numbers beside it; scheduled evaluation log; CURRENT / STALE; re-fit change
59
+ log with before/after coefficients; approve -> apply -> re-evaluate; SLA clocks;
60
+ annual re-fit cap.
61
+ - **Accuracy statement** (`accuracy_statement.py`): MAPE with a seeded bootstrap
62
+ 90 % CI; the band read at the conservative end of the interval.
63
+ - **Well-test validation** (`well_test_validation.py`): stable-period detection
64
+ with the client-agreed criteria in a file (hashed on every report), reason
65
+ codes naming the failing value, virtual rates, two-level approval trail.
66
+ - **Alarm management** (`alarm_engine.py`): setpoint / deadband / on-delay state
67
+ machine, event log, ISA-18.2-style KPIs printed against their targets.
68
+ - **Model cards** (`model_card.py`): one card per model - inputs with sources,
69
+ settings with basis, calibration data with provenance, recomputed evaluation,
70
+ limitations, re-fit history, component hashes.
71
+ - **Store-and-forward** (`store_forward.py`): 72 h edge buffer, chronological
72
+ rate-controlled replay, duplicate suppression, per-record latency.
73
+ - **Configuration versioning, SBOM, monthly SLA, FAT/SAT**
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`,
76
+ `mqtt_port.py`, `modbus.py`): WITS Level 0 from the drill floor (TCP connect,
77
+ TCP listen, serial), WITSML 1.4.1 stores (read-only, polled), OPC UA (read and
78
+ subscribe), MQTT (number, JSON, Sparkplug B), Modbus TCP; every message becomes
79
+ a measurement record with its source timestamp, ingest timestamp and quality
80
+ flag; units declared on the map are converted; every session can be recorded
81
+ and replayed; in-package simulators for WITS0 and WITSML. See *Live data*.
82
+ - **The patch panel** (`patches.py`): supervised connections that stay up -
83
+ reconnect with backoff, heartbeat, latency, per-tag last values, records to
84
+ disk as they arrive, several sources folded into one stream by priority.
85
+ - **Dashboard** (`dashboard.py`): tiles, well ranking, alarm wall, drill-down to
86
+ every report; light and dark; status is always an icon with a label.
87
+ - **The dashboard as the door** (`workspace.py`, `jobs.py`, `service.py`,
88
+ `web/app.html`): one folder per site that the client owns; a standard-library
89
+ HTTP service that serves the page, the reports and a JSON API; every action
90
+ a job running the program's own command with its log kept; accounts with
91
+ roles; an audit log with the hash of every input. See *Serving the dashboard*.
92
+ - **Survey track** (`earth_model.py`, `strata_join.py`, `inverse_engine.py`,
93
+ `blind_harness.py`, `rock_inventory.py`, `forward_model.py`, ...): strata
94
+ property estimation over a public co-located library, blind-scored on every run.
95
+
96
+ ## Quick start
97
+
98
+ ```
99
+ pip install -e .
100
+ gea quickstart # a real catalogue well -> its reports -> the dashboard; the KTB strata survey
101
+ gea survey mywell.las # a LAS file in, one strata report out
102
+ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --td 10500 --out dashboard
103
+ gea client-report --report accuracy --out client_report
104
+ gea model-cards --out model_cards
105
+ gea sbom --out sbom
106
+ gea accept # the product gate (199 checks)
107
+ gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
108
+ gea gui # the desktop window (pip install "gea-program[desktop]")
109
+ gea workspace --path C:\site --action init --name "Pad 3" # a site folder
110
+ gea serve --workspace C:\site # the dashboard as the door: http://127.0.0.1:8765/
111
+ ```
112
+
113
+ `gea` is the front door (`gea/cli.py`); every other subcommand passes through to
114
+ `python -m gea`. PATH-proof form: `python -m gea.cli ...`. Open `dashboard/index.html`.
115
+
116
+ ## Live data
117
+
118
+ The engine reads live data through five protocol ports. All are **read-only**,
119
+ all map only what the site declares (a tag map the client owns; an empty map
120
+ is declined), and all write every received message to a JSON-lines recording
121
+ that `--replay` turns back into records without a connection - which is how a
122
+ site session is reproduced offline and how the mapping logic is tested.
123
+
124
+ ```
125
+ pip install "gea-program[live]" # asyncua, paho-mqtt, pymodbus, pyserial (or one extra at a time)
126
+ gea wits0 --write-example-config wits0.json # drill floor: transport tcp | listen | serial; item codes -> tags, units
127
+ gea wits0-sim --port 5001 # a WITS0 sender to rehearse with (no rig needed)
128
+ gea wits0 --config wits0.json --seconds 60 --record floor/session.jsonl --out floor --stream-csv floor/stream.csv
129
+ gea witsml --write-example-config witsml.json # a WITSML 1.4.1 store: url, uids, mnemonics -> tags; credentials by env name
130
+ gea witsml --config witsml.json --seconds 60 --out store
131
+ gea opcua --write-example-config opcua.json # edit: endpoint, security, credential env names, nodes
132
+ gea opcua --config opcua.json --seconds 60 --record opc/session.jsonl --out opc --stream-csv opc/stream.csv
133
+ gea mqtt --write-example-config mqtt.json # edit: broker, TLS, credential env names, topics
134
+ gea mqtt --config mqtt.json --replay mq/session.jsonl --out mq_replay # no broker needed
135
+ gea ingest --file floor/stream.csv # a stream CSV feeds the historian port like any other
136
+ ```
137
+
138
+ | port | transport | quality | timestamps |
139
+ |---|---|---|---|
140
+ | `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 |
141
+ | `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 |
142
+ | `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 |
143
+ | `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 |
144
+ | `modbus_g6` | Modbus TCP, user-supplied register map with a citation | read failures -> GAP | arrival |
145
+
146
+ Units: a mapping may declare `unit_in` (what the wire carries) beside `unit`
147
+ (what the tag catalogue uses); known pairs (pressure, temperature, length,
148
+ force, flow, density, torque, volume) are converted before scale and offset,
149
+ and a pair the program cannot convert is declined when the map loads.
150
+ Credentials never sit in a map: the map names the environment variables that
151
+ hold them. The example maps are in `docs/examples/`.
152
+
153
+ **Patches** keep a source connected: a patch names a protocol, its map, the
154
+ well it feeds, a priority and a staleness limit; the service keeps every
155
+ enabled patch up, reconnects with backoff (2 ... 60 s) when the source drops,
156
+ keeps a heartbeat (state, last sample, samples per minute, latency p50/p95,
157
+ reconnects, last error, the last value of every tag), and appends every record
158
+ to `wells/<id>/records/live/patch_<name>_<day>.records.csv`. The refresh folds
159
+ the record files of every patch on a well into one stream (higher priority
160
+ wins a tie) and reports it beside the well; a drill-floor stream with no
161
+ downhole gauge stations gets quality and alarms, and its drift report is
162
+ marked not applicable rather than invented. The Patch panel page adds,
163
+ starts, stops, enables and edits patches and shows their live values.
164
+
165
+ ## Serving the dashboard
166
+
167
+ The command line is the engine; the dashboard is the door. A client site is one
168
+ folder, the **workspace**, which the client owns and backs up like any project
169
+ folder:
170
+
171
+ ```
172
+ gea workspace --path C:\site --action init --name "Pad 3"
173
+ gea workspace --path C:\site --action add-catalog --entry volve_f12_f14_production_excerpt --well 15/9-F-12 --station-md 10000
174
+ gea workspace --path C:\site --action add-file --file exports\historian.csv --name "Well A"
175
+ gea workspace --path C:\site --action add-live --name "Pad 3 OPC" --port opcua --file opcua.json
176
+ gea workspace --path C:\site --action refresh --month 2026-09 # every report, into C:\site\reports
177
+ gea serve --workspace C:\site # http://127.0.0.1:8765/
178
+ ```
179
+
180
+ Open the address in a browser. The first visit asks for the first
181
+ administrator's name and password (once); everyone else is added under
182
+ Administration with a role: **viewer** reads everything; **operator** adds
183
+ wells, runs reports and the gate, starts and stops live taps, acknowledges
184
+ alarms and commits configuration; **approver** decides well tests and re-fits;
185
+ **admin** manages users, schedules and rollbacks. Pages: Home (tiles, well
186
+ ranking), Wells (add from a file, the catalogue or a live tag map; each well's
187
+ reports, quality, trends, tests and alarms), Patch panel (supervised sources,
188
+ their state and live values, their maps, live values), Alarms (the wall, acknowledge, definitions), Approvals (one queue),
189
+ Configuration (versioned JSON with history, diff and rollback), Reports
190
+ (generate and open every report), Verification (the acceptance suite, FAT/SAT,
191
+ SBOM and the standalone check from the page), Survey (a LAS file in, a strata
192
+ report out), Jobs (every run with its log), Administration (users, schedule,
193
+ audit log).
194
+
195
+ Every action the page takes is a job: `python -m gea <command>` run by the
196
+ service with its log kept under `jobs/`, so one code path serves the page, the
197
+ terminal and the acceptance gate, and a failed action shows its log instead of
198
+ disappearing. Every action is written to `records/audit.jsonl` with the
199
+ actor's name and the SHA-256 of the inputs it used. The service is written on
200
+ the standard library only (no new dependency, the standalone check still
201
+ passes), listens on the loopback interface by default (`--host 0.0.0.0` for a
202
+ site network, behind the site's TLS proxy), keeps sessions in HttpOnly
203
+ SameSite cookies, and requires the page's own header on every action so a
204
+ foreign form cannot act. Accounts live in `users.json` as salted PBKDF2-SHA256
205
+ hashes; `gea users --workspace C:\site --action add --name ... --role admin`
206
+ adds one from the terminal (the password comes from the `GEA_PASSWORD`
207
+ environment variable, never the command line).
208
+
209
+ The workspace layout: `wells/<id>/source` (the client's files, copied in
210
+ verbatim and hashed), `config/` (the version store), `monitor/` (drift
211
+ evaluations and change logs), `reports/` (the printed dashboard and every
212
+ report), `jobs/` (every run), `records/audit.jsonl`, `users.json`. All of it is
213
+ text: JSON, JSON lines, CSV, Markdown, HTML.
214
+
215
+ ## Layout
216
+
217
+ ```
218
+ gea/ the package: engines, record layer, reports, monitor, dashboard, cli, shell, acceptance suite,
219
+ workspace, jobs, service, patches and web/app.html (the served dashboard)
220
+ gea/catalog/ 52 public archive entries, each with a provenance file
221
+ docs/ TESTER_GUIDE.md, REQUIREMENTS_MATRIX.md (the scope-of-work mirror that shaped the reports), examples/ (port configs),
222
+ SESSION_LOG.md (the working record, session by session),
223
+ commercial/ (pilot proposal, bench readiness, commercial use), HISTORY.md (the ship-by-ship record)
224
+ tools/ standalone_check.py (the self-contained guard: imports, text, metadata; run by ci and ship.ps1)
225
+ CHANGELOG.md per-release summary (a tag ships only with its section); SHIP_LOG.md is written by ship.ps1
226
+ tests/ pytest wrapper around the acceptance suite and the standalone check
227
+ ```
228
+
229
+ ## Basis
230
+
231
+ GEA-Program is a self-contained package: every module imports only the
232
+ standard library, numpy, the declared optional extras and the package itself,
233
+ and `tools/standalone_check.py` (run by CI and by `ship.ps1`) fails the build
234
+ if that ever changes or if a tracked file names another program. The physics
235
+ is on standard constants - CODATA 2018 G, standard gravity 9.80665 m/s2, the
236
+ IUGG mean Earth radius - and the rock inventory carries seventeen published
237
+ density anchors and Vp ranges with their citations (Telford, Geldart and
238
+ Sheriff; Schon). Every catalogue entry under `gea/catalog/` has a provenance
239
+ file naming its public source.
240
+
241
+ Two statements the product carries on its own model cards: the gauge aging
242
+ envelope's lower bound is an engineering model with no field validation on
243
+ record, and five of the fourteen back-tested strata quantities are NOT
244
+ ACCEPTABLE at the 95 % target. Both are printed, never claimed otherwise.
245
+
246
+ ## Shipping
247
+
248
+ `.\ship.ps1` (PowerShell) gates, commits, tags and pushes in one screen: version in
249
+ `pyproject.toml` must equal `gea.__version__` (`-Bump x.y.z` sets both), the tag must
250
+ not exist anywhere, every version in `SHIP_LOG.md` must have its tag, `python -m gea
251
+ accept` must be green, `SHIP_MESSAGE.txt` must start with the tag; then commit, tag,
252
+ push, and the remote tag must be seen before SHIPPED is printed. `CHANGELOG.md` must carry a
253
+ section headed by the tag, and `tools/standalone_check.py` must report no findings. `-DryRun` runs every
254
+ check and changes nothing; `-NoPush` stops after the local tag.
255
+
256
+ ## Publishing to PyPI
257
+
258
+ The name `gea-program` is free on PyPI as of 2026-09-29; a PyPI project is created by
259
+ its first upload, there is nothing to "start" beforehand except the trusted publisher.
260
+ One-time setup, before the first tag is pushed: sign in to PyPI -> your account ->
261
+ Publishing -> "Add a new pending publisher": project name `gea-program`, owner
262
+ `Daniel8Murphy0007`, repository `GEA-Program`, workflow `release-to-pypi.yml`,
263
+ environment `pypi`. Then in GitHub -> Settings -> Environments create `pypi`. From then
264
+ on `.\ship.ps1` pushes the tag and `.github/workflows/release-to-pypi.yml` gates, builds,
265
+ verifies the wheel and publishes; the package page is
266
+ https://pypi.org/project/gea-program/ after the first successful run.
267
+
268
+ ## Licence
269
+
270
+ Mozilla Public License 2.0 (MPL-2.0); see `LICENSE`. Every source file carries the MPL-2.0
271
+ header (Exhibit A). Copyright (c) 2026 Daniel T. Murphy.
@@ -0,0 +1,232 @@
1
+ # GEA-Program
2
+
3
+ Downhole gauge monitoring for production operations: the program takes a well's
4
+ historian data and returns the reports a client engineer reads, in the outline
5
+ and language of a production-operations scope of work.
6
+
7
+ Every number in every report is recomputed from the source data at generation
8
+ time. Reports are gated for vocabulary: the program's internal register never
9
+ reaches a client document. Nothing unmeasured is ever reported as met.
10
+
11
+ ## What it does
12
+
13
+ - **Canonical measurement record** (`gea/sample_record.py`): one record shape for
14
+ every sample - tag, UTC timestamp, value, unit, quality flag, the rule and limit
15
+ that fired, source layer, ingest timestamp. Quality rules: RANGE / ROC /
16
+ FLATLINE / SPIKE / STALE / GAP; ranges from the gauge datasheet, cited.
17
+ - **Gauge drift and reconciliation** (`reconciler.py`, `drift_monitor.py`): the
18
+ live pressure series against the well baseline; classification with the
19
+ numbers beside it; scheduled evaluation log; CURRENT / STALE; re-fit change
20
+ log with before/after coefficients; approve -> apply -> re-evaluate; SLA clocks;
21
+ annual re-fit cap.
22
+ - **Accuracy statement** (`accuracy_statement.py`): MAPE with a seeded bootstrap
23
+ 90 % CI; the band read at the conservative end of the interval.
24
+ - **Well-test validation** (`well_test_validation.py`): stable-period detection
25
+ with the client-agreed criteria in a file (hashed on every report), reason
26
+ codes naming the failing value, virtual rates, two-level approval trail.
27
+ - **Alarm management** (`alarm_engine.py`): setpoint / deadband / on-delay state
28
+ machine, event log, ISA-18.2-style KPIs printed against their targets.
29
+ - **Model cards** (`model_card.py`): one card per model - inputs with sources,
30
+ settings with basis, calibration data with provenance, recomputed evaluation,
31
+ limitations, re-fit history, component hashes.
32
+ - **Store-and-forward** (`store_forward.py`): 72 h edge buffer, chronological
33
+ rate-controlled replay, duplicate suppression, per-record latency.
34
+ - **Configuration versioning, SBOM, monthly SLA, FAT/SAT**
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`,
37
+ `mqtt_port.py`, `modbus.py`): WITS Level 0 from the drill floor (TCP connect,
38
+ TCP listen, serial), WITSML 1.4.1 stores (read-only, polled), OPC UA (read and
39
+ subscribe), MQTT (number, JSON, Sparkplug B), Modbus TCP; every message becomes
40
+ a measurement record with its source timestamp, ingest timestamp and quality
41
+ flag; units declared on the map are converted; every session can be recorded
42
+ and replayed; in-package simulators for WITS0 and WITSML. See *Live data*.
43
+ - **The patch panel** (`patches.py`): supervised connections that stay up -
44
+ reconnect with backoff, heartbeat, latency, per-tag last values, records to
45
+ disk as they arrive, several sources folded into one stream by priority.
46
+ - **Dashboard** (`dashboard.py`): tiles, well ranking, alarm wall, drill-down to
47
+ every report; light and dark; status is always an icon with a label.
48
+ - **The dashboard as the door** (`workspace.py`, `jobs.py`, `service.py`,
49
+ `web/app.html`): one folder per site that the client owns; a standard-library
50
+ HTTP service that serves the page, the reports and a JSON API; every action
51
+ a job running the program's own command with its log kept; accounts with
52
+ roles; an audit log with the hash of every input. See *Serving the dashboard*.
53
+ - **Survey track** (`earth_model.py`, `strata_join.py`, `inverse_engine.py`,
54
+ `blind_harness.py`, `rock_inventory.py`, `forward_model.py`, ...): strata
55
+ property estimation over a public co-located library, blind-scored on every run.
56
+
57
+ ## Quick start
58
+
59
+ ```
60
+ pip install -e .
61
+ gea quickstart # a real catalogue well -> its reports -> the dashboard; the KTB strata survey
62
+ gea survey mywell.las # a LAS file in, one strata report out
63
+ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --td 10500 --out dashboard
64
+ gea client-report --report accuracy --out client_report
65
+ gea model-cards --out model_cards
66
+ gea sbom --out sbom
67
+ gea accept # the product gate (199 checks)
68
+ gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
69
+ gea gui # the desktop window (pip install "gea-program[desktop]")
70
+ gea workspace --path C:\site --action init --name "Pad 3" # a site folder
71
+ gea serve --workspace C:\site # the dashboard as the door: http://127.0.0.1:8765/
72
+ ```
73
+
74
+ `gea` is the front door (`gea/cli.py`); every other subcommand passes through to
75
+ `python -m gea`. PATH-proof form: `python -m gea.cli ...`. Open `dashboard/index.html`.
76
+
77
+ ## Live data
78
+
79
+ The engine reads live data through five protocol ports. All are **read-only**,
80
+ all map only what the site declares (a tag map the client owns; an empty map
81
+ is declined), and all write every received message to a JSON-lines recording
82
+ that `--replay` turns back into records without a connection - which is how a
83
+ site session is reproduced offline and how the mapping logic is tested.
84
+
85
+ ```
86
+ pip install "gea-program[live]" # asyncua, paho-mqtt, pymodbus, pyserial (or one extra at a time)
87
+ gea wits0 --write-example-config wits0.json # drill floor: transport tcp | listen | serial; item codes -> tags, units
88
+ gea wits0-sim --port 5001 # a WITS0 sender to rehearse with (no rig needed)
89
+ gea wits0 --config wits0.json --seconds 60 --record floor/session.jsonl --out floor --stream-csv floor/stream.csv
90
+ gea witsml --write-example-config witsml.json # a WITSML 1.4.1 store: url, uids, mnemonics -> tags; credentials by env name
91
+ gea witsml --config witsml.json --seconds 60 --out store
92
+ gea opcua --write-example-config opcua.json # edit: endpoint, security, credential env names, nodes
93
+ gea opcua --config opcua.json --seconds 60 --record opc/session.jsonl --out opc --stream-csv opc/stream.csv
94
+ gea mqtt --write-example-config mqtt.json # edit: broker, TLS, credential env names, topics
95
+ gea mqtt --config mqtt.json --replay mq/session.jsonl --out mq_replay # no broker needed
96
+ gea ingest --file floor/stream.csv # a stream CSV feeds the historian port like any other
97
+ ```
98
+
99
+ | port | transport | quality | timestamps |
100
+ |---|---|---|---|
101
+ | `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 |
102
+ | `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 |
103
+ | `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 |
104
+ | `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 |
105
+ | `modbus_g6` | Modbus TCP, user-supplied register map with a citation | read failures -> GAP | arrival |
106
+
107
+ Units: a mapping may declare `unit_in` (what the wire carries) beside `unit`
108
+ (what the tag catalogue uses); known pairs (pressure, temperature, length,
109
+ force, flow, density, torque, volume) are converted before scale and offset,
110
+ and a pair the program cannot convert is declined when the map loads.
111
+ Credentials never sit in a map: the map names the environment variables that
112
+ hold them. The example maps are in `docs/examples/`.
113
+
114
+ **Patches** keep a source connected: a patch names a protocol, its map, the
115
+ well it feeds, a priority and a staleness limit; the service keeps every
116
+ enabled patch up, reconnects with backoff (2 ... 60 s) when the source drops,
117
+ keeps a heartbeat (state, last sample, samples per minute, latency p50/p95,
118
+ reconnects, last error, the last value of every tag), and appends every record
119
+ to `wells/<id>/records/live/patch_<name>_<day>.records.csv`. The refresh folds
120
+ the record files of every patch on a well into one stream (higher priority
121
+ wins a tie) and reports it beside the well; a drill-floor stream with no
122
+ downhole gauge stations gets quality and alarms, and its drift report is
123
+ marked not applicable rather than invented. The Patch panel page adds,
124
+ starts, stops, enables and edits patches and shows their live values.
125
+
126
+ ## Serving the dashboard
127
+
128
+ The command line is the engine; the dashboard is the door. A client site is one
129
+ folder, the **workspace**, which the client owns and backs up like any project
130
+ folder:
131
+
132
+ ```
133
+ gea workspace --path C:\site --action init --name "Pad 3"
134
+ gea workspace --path C:\site --action add-catalog --entry volve_f12_f14_production_excerpt --well 15/9-F-12 --station-md 10000
135
+ gea workspace --path C:\site --action add-file --file exports\historian.csv --name "Well A"
136
+ gea workspace --path C:\site --action add-live --name "Pad 3 OPC" --port opcua --file opcua.json
137
+ gea workspace --path C:\site --action refresh --month 2026-09 # every report, into C:\site\reports
138
+ gea serve --workspace C:\site # http://127.0.0.1:8765/
139
+ ```
140
+
141
+ Open the address in a browser. The first visit asks for the first
142
+ administrator's name and password (once); everyone else is added under
143
+ Administration with a role: **viewer** reads everything; **operator** adds
144
+ wells, runs reports and the gate, starts and stops live taps, acknowledges
145
+ alarms and commits configuration; **approver** decides well tests and re-fits;
146
+ **admin** manages users, schedules and rollbacks. Pages: Home (tiles, well
147
+ ranking), Wells (add from a file, the catalogue or a live tag map; each well's
148
+ reports, quality, trends, tests and alarms), Patch panel (supervised sources,
149
+ their state and live values, their maps, live values), Alarms (the wall, acknowledge, definitions), Approvals (one queue),
150
+ Configuration (versioned JSON with history, diff and rollback), Reports
151
+ (generate and open every report), Verification (the acceptance suite, FAT/SAT,
152
+ SBOM and the standalone check from the page), Survey (a LAS file in, a strata
153
+ report out), Jobs (every run with its log), Administration (users, schedule,
154
+ audit log).
155
+
156
+ Every action the page takes is a job: `python -m gea <command>` run by the
157
+ service with its log kept under `jobs/`, so one code path serves the page, the
158
+ terminal and the acceptance gate, and a failed action shows its log instead of
159
+ disappearing. Every action is written to `records/audit.jsonl` with the
160
+ actor's name and the SHA-256 of the inputs it used. The service is written on
161
+ the standard library only (no new dependency, the standalone check still
162
+ passes), listens on the loopback interface by default (`--host 0.0.0.0` for a
163
+ site network, behind the site's TLS proxy), keeps sessions in HttpOnly
164
+ SameSite cookies, and requires the page's own header on every action so a
165
+ foreign form cannot act. Accounts live in `users.json` as salted PBKDF2-SHA256
166
+ hashes; `gea users --workspace C:\site --action add --name ... --role admin`
167
+ adds one from the terminal (the password comes from the `GEA_PASSWORD`
168
+ environment variable, never the command line).
169
+
170
+ The workspace layout: `wells/<id>/source` (the client's files, copied in
171
+ verbatim and hashed), `config/` (the version store), `monitor/` (drift
172
+ evaluations and change logs), `reports/` (the printed dashboard and every
173
+ report), `jobs/` (every run), `records/audit.jsonl`, `users.json`. All of it is
174
+ text: JSON, JSON lines, CSV, Markdown, HTML.
175
+
176
+ ## Layout
177
+
178
+ ```
179
+ gea/ the package: engines, record layer, reports, monitor, dashboard, cli, shell, acceptance suite,
180
+ workspace, jobs, service, patches and web/app.html (the served dashboard)
181
+ gea/catalog/ 52 public archive entries, each with a provenance file
182
+ docs/ TESTER_GUIDE.md, REQUIREMENTS_MATRIX.md (the scope-of-work mirror that shaped the reports), examples/ (port configs),
183
+ SESSION_LOG.md (the working record, session by session),
184
+ commercial/ (pilot proposal, bench readiness, commercial use), HISTORY.md (the ship-by-ship record)
185
+ tools/ standalone_check.py (the self-contained guard: imports, text, metadata; run by ci and ship.ps1)
186
+ CHANGELOG.md per-release summary (a tag ships only with its section); SHIP_LOG.md is written by ship.ps1
187
+ tests/ pytest wrapper around the acceptance suite and the standalone check
188
+ ```
189
+
190
+ ## Basis
191
+
192
+ GEA-Program is a self-contained package: every module imports only the
193
+ standard library, numpy, the declared optional extras and the package itself,
194
+ and `tools/standalone_check.py` (run by CI and by `ship.ps1`) fails the build
195
+ if that ever changes or if a tracked file names another program. The physics
196
+ is on standard constants - CODATA 2018 G, standard gravity 9.80665 m/s2, the
197
+ IUGG mean Earth radius - and the rock inventory carries seventeen published
198
+ density anchors and Vp ranges with their citations (Telford, Geldart and
199
+ Sheriff; Schon). Every catalogue entry under `gea/catalog/` has a provenance
200
+ file naming its public source.
201
+
202
+ Two statements the product carries on its own model cards: the gauge aging
203
+ envelope's lower bound is an engineering model with no field validation on
204
+ record, and five of the fourteen back-tested strata quantities are NOT
205
+ ACCEPTABLE at the 95 % target. Both are printed, never claimed otherwise.
206
+
207
+ ## Shipping
208
+
209
+ `.\ship.ps1` (PowerShell) gates, commits, tags and pushes in one screen: version in
210
+ `pyproject.toml` must equal `gea.__version__` (`-Bump x.y.z` sets both), the tag must
211
+ not exist anywhere, every version in `SHIP_LOG.md` must have its tag, `python -m gea
212
+ accept` must be green, `SHIP_MESSAGE.txt` must start with the tag; then commit, tag,
213
+ push, and the remote tag must be seen before SHIPPED is printed. `CHANGELOG.md` must carry a
214
+ section headed by the tag, and `tools/standalone_check.py` must report no findings. `-DryRun` runs every
215
+ check and changes nothing; `-NoPush` stops after the local tag.
216
+
217
+ ## Publishing to PyPI
218
+
219
+ The name `gea-program` is free on PyPI as of 2026-09-29; a PyPI project is created by
220
+ its first upload, there is nothing to "start" beforehand except the trusted publisher.
221
+ One-time setup, before the first tag is pushed: sign in to PyPI -> your account ->
222
+ Publishing -> "Add a new pending publisher": project name `gea-program`, owner
223
+ `Daniel8Murphy0007`, repository `GEA-Program`, workflow `release-to-pypi.yml`,
224
+ environment `pypi`. Then in GitHub -> Settings -> Environments create `pypi`. From then
225
+ on `.\ship.ps1` pushes the tag and `.github/workflows/release-to-pypi.yml` gates, builds,
226
+ verifies the wheel and publishes; the package page is
227
+ https://pypi.org/project/gea-program/ after the first successful run.
228
+
229
+ ## Licence
230
+
231
+ Mozilla Public License 2.0 (MPL-2.0); see `LICENSE`. Every source file carries the MPL-2.0
232
+ header (Exhibit A). Copyright (c) 2026 Daniel T. Murphy.
@@ -1,10 +1,9 @@
1
1
  # Bench-Test Protocol — Measuring the 1.0324 Suppression Ratio
2
2
 
3
- **Field-tier step 8 (independent evaluation, adopted 2026-08-27).**
4
3
  Status of the quantity under test: `canonical_suppression()` = **1.0324 at
5
4
  unity trims** is today a **DERIVED_HYBRID** composition — industry baseline
6
5
  drift (0.215 %FS/yr class) with HPHT stress dressing, divided by a
7
- locked-primitive GEA composition. It is **not** a measured constant, and the
6
+ the program's suppression composition of three locked constants. It is **not** a measured constant, and the
8
7
  product labels it so everywhere it appears. This protocol is the experiment
9
8
  that would change — or refuse to change — that label.
10
9
 
@@ -77,7 +76,7 @@ product's own honesty rule.
77
76
 
78
77
  - **Confirmed:** `canonical_suppression()`'s label may move from
79
78
  DERIVED_HYBRID to MEASURED_ON_BENCH **with the test ID, dates, apparatus
80
- and per-pair results attached**. The composition's primitives are then a
79
+ and per-pair results attached**. The composition's constants are then a
81
80
  measured-consistent model, not just a labeled one.
82
81
  - **Refuted:** the label stays DERIVED_HYBRID; the refutation (conditions,
83
82
  measured R, uncertainty) is recorded beside it. No silent retuning of
@@ -8,10 +8,10 @@ deep-well (TD ~20,300 ft) six-gauge quartz P/T string with GEA-stabilized
8
8
  drift, transient events, live animation (matplotlib / optional PyQt6), and
9
9
  CSV export.
10
10
 
11
- Provenance: ported 2026-08-22 (Daniel GO) from the 22Aug2026 Grok thread
12
- template (grok_cce7a73b); canonical primitives locked, template tuning knobs
13
- renamed to engineering trims per the knob ruling. See README.md and
14
- PAPER_2256.
11
+ The program aging model composes a fixed drift-suppression factor from three
12
+ locked engineering constants (K_MEX = 25/12, PHI_RES = 0.84, F_TRZ = 0.1); the
13
+ user-facing settings are the two instrument trims (k_structural_trim,
14
+ phi_coupling_trim), never the constants. See README.md.
15
15
 
16
16
  Quick use (headless):
17
17
  from gea import DownholeEngine, SimulatorConfig
@@ -97,6 +97,8 @@ from .modbus import (
97
97
  RegisterMap,
98
98
  load_register_map,
99
99
  )
100
+ from .opcua_port import ASYNCUA_AVAILABLE, OpcUaTap # registers the 'opcua' port at import
101
+ from .mqtt_port import PAHO_AVAILABLE, MqttTap # registers the 'mqtt' port at import
100
102
  from .well_assembler import (
101
103
  WellAssembly, WellComponent, assemble, assemble_ktb_hb, assemble_odp_504b,
102
104
  assemble_site_1027, assemble_u1324, BUILTIN_ASSEMBLIES,
@@ -125,7 +127,7 @@ from .profile_catalog import (
125
127
  read_pangaea_txt,
126
128
  )
127
129
 
128
- __version__ = "0.1.0"
130
+ __version__ = "0.3.0"
129
131
  __all__ = [
130
132
  "calculate_quartz_transducer_hpht_program", "canonical_suppression",
131
133
  "conventional_drift", "drift_comparison",