gea-program 0.83.2__tar.gz → 0.84.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 (430) hide show
  1. {gea_program-0.83.2/gea_program.egg-info → gea_program-0.84.0}/PKG-INFO +22 -4
  2. {gea_program-0.83.2 → gea_program-0.84.0}/README.md +21 -3
  3. {gea_program-0.83.2 → gea_program-0.84.0}/gea/__init__.py +1 -1
  4. {gea_program-0.83.2 → gea_program-0.84.0}/gea/__main__.py +79 -0
  5. {gea_program-0.83.2 → gea_program-0.84.0}/gea/acceptance_tests.py +198 -0
  6. gea_program-0.84.0/gea/fluid.py +981 -0
  7. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/driller.md +1 -1
  8. gea_program-0.84.0/gea/help/fluid.md +13 -0
  9. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/install.md +2 -2
  10. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/reader.md +1 -1
  11. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/recorder.md +1 -1
  12. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/01-install.md +2 -2
  13. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/14-production-pages.md +7 -6
  14. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/19-dossier-reader.md +1 -1
  15. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/22-updates.md +1 -1
  16. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/23-vpn.md +1 -1
  17. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/25-install-recorder.md +2 -2
  18. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/29-driller-rig.md +1 -1
  19. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial.md +2 -2
  20. {gea_program-0.83.2 → gea_program-0.84.0}/gea/helplib.py +2 -1
  21. {gea_program-0.83.2 → gea_program-0.84.0}/gea/service.py +33 -0
  22. {gea_program-0.83.2 → gea_program-0.84.0}/gea/web/app.html +85 -1
  23. {gea_program-0.83.2 → gea_program-0.84.0/gea_program.egg-info}/PKG-INFO +22 -4
  24. {gea_program-0.83.2 → gea_program-0.84.0}/gea_program.egg-info/SOURCES.txt +2 -0
  25. {gea_program-0.83.2 → gea_program-0.84.0}/pyproject.toml +1 -1
  26. {gea_program-0.83.2 → gea_program-0.84.0}/LICENSE +0 -0
  27. {gea_program-0.83.2 → gea_program-0.84.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
  28. {gea_program-0.83.2 → gea_program-0.84.0}/gea/accuracy_statement.py +0 -0
  29. {gea_program-0.83.2 → gea_program-0.84.0}/gea/alarm_engine.py +0 -0
  30. {gea_program-0.83.2 → gea_program-0.84.0}/gea/alerts.py +0 -0
  31. {gea_program-0.83.2 → gea_program-0.84.0}/gea/backup.py +0 -0
  32. {gea_program-0.83.2 → gea_program-0.84.0}/gea/bench.py +0 -0
  33. {gea_program-0.83.2 → gea_program-0.84.0}/gea/bit_seismic.py +0 -0
  34. {gea_program-0.83.2 → gea_program-0.84.0}/gea/blind_harness.py +0 -0
  35. {gea_program-0.83.2 → gea_program-0.84.0}/gea/casing_design.py +0 -0
  36. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
  37. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
  38. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
  39. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
  40. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
  41. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
  42. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
  43. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
  44. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
  45. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
  46. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
  47. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
  48. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
  49. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
  50. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
  51. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
  52. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
  53. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
  54. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
  55. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
  56. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
  57. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
  58. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
  59. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
  60. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
  61. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
  62. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
  63. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
  64. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
  65. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
  66. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
  67. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
  68. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
  69. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
  70. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
  71. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
  72. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
  73. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
  74. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
  75. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
  76. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
  77. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
  78. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
  79. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
  80. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
  81. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
  82. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
  83. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
  84. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
  85. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
  86. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
  87. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
  88. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
  89. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
  90. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
  91. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
  92. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
  93. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
  94. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
  95. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
  96. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
  97. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
  98. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
  99. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
  100. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
  101. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
  102. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
  103. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/med_160_sapropels.txt +0 -0
  104. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
  105. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
  106. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
  107. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
  108. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
  109. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
  110. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
  111. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
  112. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
  113. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
  114. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
  115. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
  116. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
  117. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
  118. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
  119. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
  120. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
  121. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
  122. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
  123. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
  124. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
  125. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
  126. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
  127. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
  128. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
  129. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
  130. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
  131. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
  132. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
  133. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
  134. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
  135. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
  136. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
  137. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
  138. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
  139. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
  140. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog_map.py +0 -0
  141. {gea_program-0.83.2 → gea_program-0.84.0}/gea/catalog_register.py +0 -0
  142. {gea_program-0.83.2 → gea_program-0.84.0}/gea/certificates.py +0 -0
  143. {gea_program-0.83.2 → gea_program-0.84.0}/gea/cli.py +0 -0
  144. {gea_program-0.83.2 → gea_program-0.84.0}/gea/client_reports.py +0 -0
  145. {gea_program-0.83.2 → gea_program-0.84.0}/gea/collision.py +0 -0
  146. {gea_program-0.83.2 → gea_program-0.84.0}/gea/config_versioning.py +0 -0
  147. {gea_program-0.83.2 → gea_program-0.84.0}/gea/conformance.py +0 -0
  148. {gea_program-0.83.2 → gea_program-0.84.0}/gea/control_room.py +0 -0
  149. {gea_program-0.83.2 → gea_program-0.84.0}/gea/correlation.py +0 -0
  150. {gea_program-0.83.2 → gea_program-0.84.0}/gea/dashboard.py +0 -0
  151. {gea_program-0.83.2 → gea_program-0.84.0}/gea/declarations.py +0 -0
  152. {gea_program-0.83.2 → gea_program-0.84.0}/gea/decline.py +0 -0
  153. {gea_program-0.83.2 → gea_program-0.84.0}/gea/deviation.py +0 -0
  154. {gea_program-0.83.2 → gea_program-0.84.0}/gea/dlis.py +0 -0
  155. {gea_program-0.83.2 → gea_program-0.84.0}/gea/dnp3.py +0 -0
  156. {gea_program-0.83.2 → gea_program-0.84.0}/gea/doctor.py +0 -0
  157. {gea_program-0.83.2 → gea_program-0.84.0}/gea/dossier.py +0 -0
  158. {gea_program-0.83.2 → gea_program-0.84.0}/gea/dossier_verify.py +0 -0
  159. {gea_program-0.83.2 → gea_program-0.84.0}/gea/downhole_engine.py +0 -0
  160. {gea_program-0.83.2 → gea_program-0.84.0}/gea/drift_monitor.py +0 -0
  161. {gea_program-0.83.2 → gea_program-0.84.0}/gea/drill_string.py +0 -0
  162. {gea_program-0.83.2 → gea_program-0.84.0}/gea/driller_link.py +0 -0
  163. {gea_program-0.83.2 → gea_program-0.84.0}/gea/earth_model.py +0 -0
  164. {gea_program-0.83.2 → gea_program-0.84.0}/gea/economics.py +0 -0
  165. {gea_program-0.83.2 → gea_program-0.84.0}/gea/ed25519.py +0 -0
  166. {gea_program-0.83.2 → gea_program-0.84.0}/gea/edr.py +0 -0
  167. {gea_program-0.83.2 → gea_program-0.84.0}/gea/elevation.py +0 -0
  168. {gea_program-0.83.2 → gea_program-0.84.0}/gea/etp.py +0 -0
  169. {gea_program-0.83.2 → gea_program-0.84.0}/gea/etp12_schemas.json +0 -0
  170. {gea_program-0.83.2 → gea_program-0.84.0}/gea/example_register_map.json +0 -0
  171. {gea_program-0.83.2 → gea_program-0.84.0}/gea/fat_sat.py +0 -0
  172. {gea_program-0.83.2 → gea_program-0.84.0}/gea/field_pull.py +0 -0
  173. {gea_program-0.83.2 → gea_program-0.84.0}/gea/files.py +0 -0
  174. {gea_program-0.83.2 → gea_program-0.84.0}/gea/fixtures/README.md +0 -0
  175. {gea_program-0.83.2 → gea_program-0.84.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
  176. {gea_program-0.83.2 → gea_program-0.84.0}/gea/fixtures/comcat_mahoning_1990-2026.txt +0 -0
  177. {gea_program-0.83.2 → gea_program-0.84.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
  178. {gea_program-0.83.2 → gea_program-0.84.0}/gea/fixtures/ne_110m_coastline.json +0 -0
  179. {gea_program-0.83.2 → gea_program-0.84.0}/gea/follower.py +0 -0
  180. {gea_program-0.83.2 → gea_program-0.84.0}/gea/forward_model.py +0 -0
  181. {gea_program-0.83.2 → gea_program-0.84.0}/gea/frac_hits.py +0 -0
  182. {gea_program-0.83.2 → gea_program-0.84.0}/gea/friction_priors.py +0 -0
  183. {gea_program-0.83.2 → gea_program-0.84.0}/gea/gamma.py +0 -0
  184. {gea_program-0.83.2 → gea_program-0.84.0}/gea/gauge_aging.py +0 -0
  185. {gea_program-0.83.2 → gea_program-0.84.0}/gea/gauge_specs.py +0 -0
  186. {gea_program-0.83.2 → gea_program-0.84.0}/gea/geodesy.py +0 -0
  187. {gea_program-0.83.2 → gea_program-0.84.0}/gea/geomag.py +0 -0
  188. {gea_program-0.83.2 → gea_program-0.84.0}/gea/gravity_reference.py +0 -0
  189. {gea_program-0.83.2 → gea_program-0.84.0}/gea/hartip.py +0 -0
  190. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/IT_SECURITY.md +0 -0
  191. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/TESTER_GUIDE.md +0 -0
  192. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/alarms.md +0 -0
  193. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/alerts.md +0 -0
  194. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/audit-update.md +0 -0
  195. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/backup.md +0 -0
  196. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/bit-image.md +0 -0
  197. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/casing.md +0 -0
  198. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/catalog.md +0 -0
  199. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/charts.md +0 -0
  200. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/collision.md +0 -0
  201. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/company-sign-in.md +0 -0
  202. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/conformance.md +0 -0
  203. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/control-room.md +0 -0
  204. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/data-in.md +0 -0
  205. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/declare.md +0 -0
  206. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/decline.md +0 -0
  207. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/dlis.md +0 -0
  208. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/doctor.md +0 -0
  209. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/dossier.md +0 -0
  210. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/drift.md +0 -0
  211. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/drillstring.md +0 -0
  212. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/economics.md +0 -0
  213. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/edr.md +0 -0
  214. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/etp.md +0 -0
  215. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/field-ports.md +0 -0
  216. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/files.md +0 -0
  217. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/frac-hits.md +0 -0
  218. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/historian.md +0 -0
  219. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/https.md +0 -0
  220. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/hydraulics.md +0 -0
  221. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/instruments.md +0 -0
  222. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/interval.md +0 -0
  223. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/invoice-check.md +0 -0
  224. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/map.md +0 -0
  225. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/month-end.md +0 -0
  226. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/notifications.md +0 -0
  227. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/opseis.md +0 -0
  228. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/osdu.md +0 -0
  229. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/pad-summary.md +0 -0
  230. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/patches.md +0 -0
  231. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/penetrator.md +0 -0
  232. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/plan.md +0 -0
  233. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/pore-pressure.md +0 -0
  234. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/ppdm.md +0 -0
  235. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/quakeml.md +0 -0
  236. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/quality.md +0 -0
  237. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/records.md +0 -0
  238. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/report-history.md +0 -0
  239. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/rig-time.md +0 -0
  240. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/rocks.md +0 -0
  241. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/seedlink.md +0 -0
  242. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/seismic.md +0 -0
  243. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/setup.md +0 -0
  244. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/simulation.md +0 -0
  245. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/site.md +0 -0
  246. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/sites.md +0 -0
  247. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/slip.md +0 -0
  248. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/soak.md +0 -0
  249. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/sra.md +0 -0
  250. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/start.md +0 -0
  251. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/structure.md +0 -0
  252. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tools.md +0 -0
  253. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/torque-drag.md +0 -0
  254. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/transients.md +0 -0
  255. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/02-sign-in.md +0 -0
  256. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/03-site.md +0 -0
  257. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/04-add-well.md +0 -0
  258. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/05-records.md +0 -0
  259. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/06-well-page.md +0 -0
  260. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/07-declare.md +0 -0
  261. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/08-patches.md +0 -0
  262. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/09-alarms.md +0 -0
  263. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/10-control-room.md +0 -0
  264. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/11-summary-month.md +0 -0
  265. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/12-where-the-well-is.md +0 -0
  266. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/13-drilling-pages.md +0 -0
  267. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/15-seismic.md +0 -0
  268. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/16-seismicity.md +0 -0
  269. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/17-recorder-office.md +0 -0
  270. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/18-reports.md +0 -0
  271. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/20-admin.md +0 -0
  272. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/21-upkeep.md +0 -0
  273. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/24-the-box.md +0 -0
  274. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/26-monitor.md +0 -0
  275. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/27-mirror-vpn.md +0 -0
  276. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/tutorial/28-driller-office.md +0 -0
  277. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/upkeep.md +0 -0
  278. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/vibration.md +0 -0
  279. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/vpn.md +0 -0
  280. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/well-report.md +0 -0
  281. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/well-tests.md +0 -0
  282. {gea_program-0.83.2 → gea_program-0.84.0}/gea/help/well3d.md +0 -0
  283. {gea_program-0.83.2 → gea_program-0.84.0}/gea/housekeeping.py +0 -0
  284. {gea_program-0.83.2 → gea_program-0.84.0}/gea/hydraulics.py +0 -0
  285. {gea_program-0.83.2 → gea_program-0.84.0}/gea/icon.py +0 -0
  286. {gea_program-0.83.2 → gea_program-0.84.0}/gea/interval.py +0 -0
  287. {gea_program-0.83.2 → gea_program-0.84.0}/gea/inverse_engine.py +0 -0
  288. {gea_program-0.83.2 → gea_program-0.84.0}/gea/invoice_check.py +0 -0
  289. {gea_program-0.83.2 → gea_program-0.84.0}/gea/jobs.py +0 -0
  290. {gea_program-0.83.2 → gea_program-0.84.0}/gea/launcher.py +0 -0
  291. {gea_program-0.83.2 → gea_program-0.84.0}/gea/live_ports.py +0 -0
  292. {gea_program-0.83.2 → gea_program-0.84.0}/gea/loadtest.py +0 -0
  293. {gea_program-0.83.2 → gea_program-0.84.0}/gea/matplotlib_demo.py +0 -0
  294. {gea_program-0.83.2 → gea_program-0.84.0}/gea/modbus.py +0 -0
  295. {gea_program-0.83.2 → gea_program-0.84.0}/gea/modbus_rtu.py +0 -0
  296. {gea_program-0.83.2 → gea_program-0.84.0}/gea/model_card.py +0 -0
  297. {gea_program-0.83.2 → gea_program-0.84.0}/gea/month_end.py +0 -0
  298. {gea_program-0.83.2 → gea_program-0.84.0}/gea/mqtt_port.py +0 -0
  299. {gea_program-0.83.2 → gea_program-0.84.0}/gea/notify.py +0 -0
  300. {gea_program-0.83.2 → gea_program-0.84.0}/gea/oidc.py +0 -0
  301. {gea_program-0.83.2 → gea_program-0.84.0}/gea/oidc_mock.py +0 -0
  302. {gea_program-0.83.2 → gea_program-0.84.0}/gea/op_seismicity.py +0 -0
  303. {gea_program-0.83.2 → gea_program-0.84.0}/gea/opcua_port.py +0 -0
  304. {gea_program-0.83.2 → gea_program-0.84.0}/gea/operator_app.py +0 -0
  305. {gea_program-0.83.2 → gea_program-0.84.0}/gea/osdu.py +0 -0
  306. {gea_program-0.83.2 → gea_program-0.84.0}/gea/pad_summary.py +0 -0
  307. {gea_program-0.83.2 → gea_program-0.84.0}/gea/patches.py +0 -0
  308. {gea_program-0.83.2 → gea_program-0.84.0}/gea/pdf_report.py +0 -0
  309. {gea_program-0.83.2 → gea_program-0.84.0}/gea/penetrator.py +0 -0
  310. {gea_program-0.83.2 → gea_program-0.84.0}/gea/permits.py +0 -0
  311. {gea_program-0.83.2 → gea_program-0.84.0}/gea/piwebapi.py +0 -0
  312. {gea_program-0.83.2 → gea_program-0.84.0}/gea/pore_pressure.py +0 -0
  313. {gea_program-0.83.2 → gea_program-0.84.0}/gea/ports.py +0 -0
  314. {gea_program-0.83.2 → gea_program-0.84.0}/gea/ppdm.py +0 -0
  315. {gea_program-0.83.2 → gea_program-0.84.0}/gea/profile_catalog.py +0 -0
  316. {gea_program-0.83.2 → gea_program-0.84.0}/gea/project.py +0 -0
  317. {gea_program-0.83.2 → gea_program-0.84.0}/gea/qt6_downhole_app.py +0 -0
  318. {gea_program-0.83.2 → gea_program-0.84.0}/gea/quakeml.py +0 -0
  319. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reader.py +0 -0
  320. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reader_app.py +0 -0
  321. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reconciler.py +0 -0
  322. {gea_program-0.83.2 → gea_program-0.84.0}/gea/recorder_link.py +0 -0
  323. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
  324. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
  325. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/WMM2025.COF +0 -0
  326. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/eia_henry_hub_daily.csv.gz +0 -0
  327. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/eia_prices.provenance.json +0 -0
  328. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/eia_wti_daily.csv.gz +0 -0
  329. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/iscwsa_rev4_example.json +0 -0
  330. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/iscwsa_rev5_example.json +0 -0
  331. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/l0701_sonic_gr.las.gz +0 -0
  332. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/l0701_sonic_gr.provenance.json +0 -0
  333. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/libmseed_steim.provenance.json +0 -0
  334. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
  335. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
  336. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
  337. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/mahoning_example.json +0 -0
  338. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/mud_motor_specs.json +0 -0
  339. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/owsg_tool_models.json +0 -0
  340. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/penetrator_ratings.json +0 -0
  341. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/seismicity_protocols.json +0 -0
  342. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/tool_sources.json +0 -0
  343. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/us_outline.json +0 -0
  344. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/us_outline.provenance.json +0 -0
  345. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_3d.provenance.json +0 -0
  346. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_f4_interpretation.las.gz +0 -0
  347. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_f4_logs.provenance.json +0 -0
  348. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_f4_lwd.las.gz +0 -0
  349. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_surfaces.json.gz +0 -0
  350. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_traj_F-10.xml.gz +0 -0
  351. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_traj_F-4.xml.gz +0 -0
  352. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_traj_F-5_12.25in.xml.gz +0 -0
  353. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_traj_F-5_17.5in.xml.gz +0 -0
  354. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_traj_F-5_36in.xml.gz +0 -0
  355. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_traj_F-5_8.5in.xml.gz +0 -0
  356. {gea_program-0.83.2 → gea_program-0.84.0}/gea/reference/volve_well_picks.csv.gz +0 -0
  357. {gea_program-0.83.2 → gea_program-0.84.0}/gea/report_history.py +0 -0
  358. {gea_program-0.83.2 → gea_program-0.84.0}/gea/rig_state.py +0 -0
  359. {gea_program-0.83.2 → gea_program-0.84.0}/gea/rock_inventory.py +0 -0
  360. {gea_program-0.83.2 → gea_program-0.84.0}/gea/sample_record.py +0 -0
  361. {gea_program-0.83.2 → gea_program-0.84.0}/gea/sample_well_profile.csv +0 -0
  362. {gea_program-0.83.2 → gea_program-0.84.0}/gea/sbom.py +0 -0
  363. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seedlink.py +0 -0
  364. {gea_program-0.83.2 → gea_program-0.84.0}/gea/segy.py +0 -0
  365. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic.py +0 -0
  366. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_array.py +0 -0
  367. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_assoc.py +0 -0
  368. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_detect.py +0 -0
  369. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_film.py +0 -0
  370. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_harmonic.py +0 -0
  371. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_qc.py +0 -0
  372. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_response.py +0 -0
  373. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_signature.py +0 -0
  374. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_track.py +0 -0
  375. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_uncertainty.py +0 -0
  376. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_unlisted.py +0 -0
  377. {gea_program-0.83.2 → gea_program-0.84.0}/gea/seismic_watch.py +0 -0
  378. {gea_program-0.83.2 → gea_program-0.84.0}/gea/sensor_swap.py +0 -0
  379. {gea_program-0.83.2 → gea_program-0.84.0}/gea/series_cache.py +0 -0
  380. {gea_program-0.83.2 → gea_program-0.84.0}/gea/service_life.py +0 -0
  381. {gea_program-0.83.2 → gea_program-0.84.0}/gea/setup_checklist.py +0 -0
  382. {gea_program-0.83.2 → gea_program-0.84.0}/gea/shapefile.py +0 -0
  383. {gea_program-0.83.2 → gea_program-0.84.0}/gea/shell.py +0 -0
  384. {gea_program-0.83.2 → gea_program-0.84.0}/gea/shut_in.py +0 -0
  385. {gea_program-0.83.2 → gea_program-0.84.0}/gea/simulation.py +0 -0
  386. {gea_program-0.83.2 → gea_program-0.84.0}/gea/site_map.py +0 -0
  387. {gea_program-0.83.2 → gea_program-0.84.0}/gea/sla_report.py +0 -0
  388. {gea_program-0.83.2 → gea_program-0.84.0}/gea/slip.py +0 -0
  389. {gea_program-0.83.2 → gea_program-0.84.0}/gea/soak.py +0 -0
  390. {gea_program-0.83.2 → gea_program-0.84.0}/gea/sra.py +0 -0
  391. {gea_program-0.83.2 → gea_program-0.84.0}/gea/store_forward.py +0 -0
  392. {gea_program-0.83.2 → gea_program-0.84.0}/gea/strata_join.py +0 -0
  393. {gea_program-0.83.2 → gea_program-0.84.0}/gea/structure.py +0 -0
  394. {gea_program-0.83.2 → gea_program-0.84.0}/gea/supervisor.py +0 -0
  395. {gea_program-0.83.2 → gea_program-0.84.0}/gea/survey_cmd.py +0 -0
  396. {gea_program-0.83.2 → gea_program-0.84.0}/gea/survey_view.py +0 -0
  397. {gea_program-0.83.2 → gea_program-0.84.0}/gea/telemetry.py +0 -0
  398. {gea_program-0.83.2 → gea_program-0.84.0}/gea/timestamp.py +0 -0
  399. {gea_program-0.83.2 → gea_program-0.84.0}/gea/tls.py +0 -0
  400. {gea_program-0.83.2 → gea_program-0.84.0}/gea/tool_catalog.py +0 -0
  401. {gea_program-0.83.2 → gea_program-0.84.0}/gea/tool_library.py +0 -0
  402. {gea_program-0.83.2 → gea_program-0.84.0}/gea/tool_taxonomy.py +0 -0
  403. {gea_program-0.83.2 → gea_program-0.84.0}/gea/torque_drag.py +0 -0
  404. {gea_program-0.83.2 → gea_program-0.84.0}/gea/transient.py +0 -0
  405. {gea_program-0.83.2 → gea_program-0.84.0}/gea/tray.py +0 -0
  406. {gea_program-0.83.2 → gea_program-0.84.0}/gea/tutorial.py +0 -0
  407. {gea_program-0.83.2 → gea_program-0.84.0}/gea/updates.py +0 -0
  408. {gea_program-0.83.2 → gea_program-0.84.0}/gea/vibration.py +0 -0
  409. {gea_program-0.83.2 → gea_program-0.84.0}/gea/vpn.py +0 -0
  410. {gea_program-0.83.2 → gea_program-0.84.0}/gea/web/reader.html +0 -0
  411. {gea_program-0.83.2 → gea_program-0.84.0}/gea/well3d.py +0 -0
  412. {gea_program-0.83.2 → gea_program-0.84.0}/gea/well_assembler.py +0 -0
  413. {gea_program-0.83.2 → gea_program-0.84.0}/gea/well_records.py +0 -0
  414. {gea_program-0.83.2 → gea_program-0.84.0}/gea/well_report.py +0 -0
  415. {gea_program-0.83.2 → gea_program-0.84.0}/gea/well_test_validation.py +0 -0
  416. {gea_program-0.83.2 → gea_program-0.84.0}/gea/wellplan.py +0 -0
  417. {gea_program-0.83.2 → gea_program-0.84.0}/gea/wellpos.py +0 -0
  418. {gea_program-0.83.2 → gea_program-0.84.0}/gea/winident.py +0 -0
  419. {gea_program-0.83.2 → gea_program-0.84.0}/gea/wits0.py +0 -0
  420. {gea_program-0.83.2 → gea_program-0.84.0}/gea/witsml.py +0 -0
  421. {gea_program-0.83.2 → gea_program-0.84.0}/gea/workspace.py +0 -0
  422. {gea_program-0.83.2 → gea_program-0.84.0}/gea/workspaces.py +0 -0
  423. {gea_program-0.83.2 → gea_program-0.84.0}/gea/x25519.py +0 -0
  424. {gea_program-0.83.2 → gea_program-0.84.0}/gea/xlsx_read.py +0 -0
  425. {gea_program-0.83.2 → gea_program-0.84.0}/gea_program.egg-info/dependency_links.txt +0 -0
  426. {gea_program-0.83.2 → gea_program-0.84.0}/gea_program.egg-info/entry_points.txt +0 -0
  427. {gea_program-0.83.2 → gea_program-0.84.0}/gea_program.egg-info/requires.txt +0 -0
  428. {gea_program-0.83.2 → gea_program-0.84.0}/gea_program.egg-info/top_level.txt +0 -0
  429. {gea_program-0.83.2 → gea_program-0.84.0}/setup.cfg +0 -0
  430. {gea_program-0.83.2 → gea_program-0.84.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.83.2
3
+ Version: 0.84.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
@@ -847,7 +847,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
847
847
  reader made from the workspace knows the site's key fingerprints, so it
848
848
  says whether a dossier is the site's; it allows no network request, and it
849
849
  leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
850
- it installed, every release also carries `GEA-Reader-Setup-0.83.2.exe`: GEA
850
+ it installed, every release also carries `GEA-Reader-Setup-0.84.0.exe`: GEA
851
851
  Reader as a Windows program of its own - its own icon and taskbar button,
852
852
  Check with GEA Reader on a dossier's right-click menu, fingerprints the client
853
853
  saves kept on that computer, nothing of GEA-Program. `gea help reader`.
@@ -948,6 +948,24 @@ stage to the monitored well; with an earthquake catalogue, the earthquakes
948
948
  during each stage. A frac hit is an alert. The **Frac hits** tab,
949
949
  `gea frac-hits`, `gea help frac-hits`.
950
950
 
951
+ ### Fluid balance
952
+
953
+ Where the water went, as far as arithmetic can say. Every barrel that went
954
+ into or came out of a formation through the site's wells, by day, with its
955
+ density and its dissolved solids (declared as specific gravity or TDS, the
956
+ density from TDS by McCain's correlation), from the operator's own injection
957
+ or production reports attached as CSV or from a disposal well's declared
958
+ injection channels; the formation declared with its porosity, thickness,
959
+ area and compressibilities; the storage the wells' bottomhole pressures say
960
+ the formation has against the storage declared - closed as declared, more
961
+ room (the fluid finding room the declaration does not have: an aquifer,
962
+ leak-off, a larger connected volume) or less - with the unaccounted barrels
963
+ and their tonnes of solids named; each injection well's Hall plot; and its
964
+ neighbours by distance with the day the pressure front reaches them, the
965
+ pressure rise there and the volume it would take for the water itself to
966
+ arrive, every projection labelled SIMULATION. The **Fluid balance** tab,
967
+ `gea fluid`, `gea help fluid`.
968
+
951
969
  ### Plan vs actual and the survey tools
952
970
 
953
971
  Each well against its directional plan: at every survey station, how far
@@ -1612,7 +1630,7 @@ attaches the zips to the GitHub release of that tag.
1612
1630
 
1613
1631
  ### The Windows installer
1614
1632
 
1615
- Every release also carries `GEA-Program-Setup-0.83.2.exe` (for 0.83.2): the
1633
+ Every release also carries `GEA-Program-Setup-0.84.0.exe` (for 0.84.0): the
1616
1634
  same Windows kit installed like any Windows program, for the signed-in user
1617
1635
  alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
1618
1636
  It asks for the site workspace (an existing one such as `C:\site` is used as
@@ -1631,7 +1649,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
1631
1649
  software deployment:
1632
1650
 
1633
1651
  ```
1634
- GEA-Program-Setup-0.83.2.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1652
+ GEA-Program-Setup-0.84.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1635
1653
  ```
1636
1654
 
1637
1655
  The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
@@ -808,7 +808,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
808
808
  reader made from the workspace knows the site's key fingerprints, so it
809
809
  says whether a dossier is the site's; it allows no network request, and it
810
810
  leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
811
- it installed, every release also carries `GEA-Reader-Setup-0.83.2.exe`: GEA
811
+ it installed, every release also carries `GEA-Reader-Setup-0.84.0.exe`: GEA
812
812
  Reader as a Windows program of its own - its own icon and taskbar button,
813
813
  Check with GEA Reader on a dossier's right-click menu, fingerprints the client
814
814
  saves kept on that computer, nothing of GEA-Program. `gea help reader`.
@@ -909,6 +909,24 @@ stage to the monitored well; with an earthquake catalogue, the earthquakes
909
909
  during each stage. A frac hit is an alert. The **Frac hits** tab,
910
910
  `gea frac-hits`, `gea help frac-hits`.
911
911
 
912
+ ### Fluid balance
913
+
914
+ Where the water went, as far as arithmetic can say. Every barrel that went
915
+ into or came out of a formation through the site's wells, by day, with its
916
+ density and its dissolved solids (declared as specific gravity or TDS, the
917
+ density from TDS by McCain's correlation), from the operator's own injection
918
+ or production reports attached as CSV or from a disposal well's declared
919
+ injection channels; the formation declared with its porosity, thickness,
920
+ area and compressibilities; the storage the wells' bottomhole pressures say
921
+ the formation has against the storage declared - closed as declared, more
922
+ room (the fluid finding room the declaration does not have: an aquifer,
923
+ leak-off, a larger connected volume) or less - with the unaccounted barrels
924
+ and their tonnes of solids named; each injection well's Hall plot; and its
925
+ neighbours by distance with the day the pressure front reaches them, the
926
+ pressure rise there and the volume it would take for the water itself to
927
+ arrive, every projection labelled SIMULATION. The **Fluid balance** tab,
928
+ `gea fluid`, `gea help fluid`.
929
+
912
930
  ### Plan vs actual and the survey tools
913
931
 
914
932
  Each well against its directional plan: at every survey station, how far
@@ -1573,7 +1591,7 @@ attaches the zips to the GitHub release of that tag.
1573
1591
 
1574
1592
  ### The Windows installer
1575
1593
 
1576
- Every release also carries `GEA-Program-Setup-0.83.2.exe` (for 0.83.2): the
1594
+ Every release also carries `GEA-Program-Setup-0.84.0.exe` (for 0.84.0): the
1577
1595
  same Windows kit installed like any Windows program, for the signed-in user
1578
1596
  alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
1579
1597
  It asks for the site workspace (an existing one such as `C:\site` is used as
@@ -1592,7 +1610,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
1592
1610
  software deployment:
1593
1611
 
1594
1612
  ```
1595
- GEA-Program-Setup-0.83.2.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1613
+ GEA-Program-Setup-0.84.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1596
1614
  ```
1597
1615
 
1598
1616
  The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
@@ -123,7 +123,7 @@ from .profile_catalog import (
123
123
  read_pangaea_txt,
124
124
  )
125
125
 
126
- __version__ = "0.83.2"
126
+ __version__ = "0.84.0"
127
127
  __all__ = [
128
128
  "aging_rate", "rate_psi_yr", "accuracy_psi",
129
129
  "Sensor", "SimulatorConfig", "DownholeEngine",
@@ -561,6 +561,35 @@ def main(argv=None) -> int:
561
561
  p_pn.add_argument("--actor", type=str, default="cli")
562
562
  p_pn.add_argument("--json", action="store_true")
563
563
 
564
+ p_fl = sub.add_parser("fluid", help="the fluid ledger and the material balance: every barrel in or out of a formation through the site's wells by day, with its density and dissolved solids, against the room the formation has; the storage the pressure says against the storage declared; the Hall plot; the neighbours with the front and pressure projections (SIMULATION)")
565
+ p_fl.add_argument("--workspace", type=str, default=None, help="the workspace folder; without one the self-test runs on labelled scenes")
566
+ p_fl.add_argument("--well", type=str, default=None, help="the well a declaration, a report or a removal is for")
567
+ p_fl.add_argument("--declare", action="store_true", help="declare the well's role, formation or density (with --source)")
568
+ p_fl.add_argument("--role", type=str, default=None, choices=("injection", "production"))
569
+ p_fl.add_argument("--formation", type=str, default=None, help="--declare: the formation the well is completed in; alone with --porosity etc.: the formation to declare")
570
+ p_fl.add_argument("--density-sg", type=float, default=None, help="--declare: the injected water's specific gravity")
571
+ p_fl.add_argument("--density-ppg", type=float, default=None, help="--declare: the injected water's density in lb/gal")
572
+ p_fl.add_argument("--tds-mgl", type=float, default=None, help="--declare: the injected water's total dissolved solids, mg/L (density by McCain 1991)")
573
+ p_fl.add_argument("--from", dest="from_day", type=str, default=None, help="--declare: the first day the density applies (YYYY-MM-DD; blank: from the start)")
574
+ p_fl.add_argument("--to", dest="to_day", type=str, default=None, help="--declare: the last day the density applies (blank: open)")
575
+ p_fl.add_argument("--attach", type=str, default=None, help="the operator's injection or production report (CSV: a date column and a volume column; pressures, BHP, density or TDS when it has them) for --well")
576
+ p_fl.add_argument("--porosity", type=float, default=None, help="--formation: porosity, fraction")
577
+ p_fl.add_argument("--thickness-ft", type=float, default=None, help="--formation: net thickness, ft")
578
+ p_fl.add_argument("--area-acres", type=float, default=None, help="--formation: the connected area, acres")
579
+ p_fl.add_argument("--c-water", type=float, default=None, help="--formation: water compressibility, 1/psi (default 3e-6)")
580
+ p_fl.add_argument("--c-pore", type=float, default=None, help="--formation: pore-volume compressibility, 1/psi (default 4e-6)")
581
+ p_fl.add_argument("--k-md", type=float, default=None, help="--formation: permeability, md (for the front and pressure projections)")
582
+ p_fl.add_argument("--mu-cp", type=float, default=None, help="--formation: water viscosity, cp (default 0.6)")
583
+ p_fl.add_argument("--p-initial-psi", type=float, default=None, help="--formation: the initial formation pressure, psi (the Hall plot's p_e)")
584
+ p_fl.add_argument("--water-sg", type=float, default=None, help="--formation: the formation water's specific gravity")
585
+ p_fl.add_argument("--water-tds-mgl", type=float, default=None, help="--formation: the formation water's TDS, mg/L")
586
+ p_fl.add_argument("--source", type=str, default="", help="where the declaration or the report came from (required with --declare, --attach and a formation)")
587
+ p_fl.add_argument("--remove", action="store_true", help="remove the well's fluid declaration (--well), one of its reports (--well --report) or a formation (--formation)")
588
+ p_fl.add_argument("--report", type=str, default=None, help="--remove: the report file to remove from --well")
589
+ p_fl.add_argument("--as-of", type=str, default=None, help="the balance up to this day (YYYY-MM-DD)")
590
+ p_fl.add_argument("--write", action="store_true", help="write the report under reports/fluid/ (fluid_balance.json, .md, the ledger CSVs)")
591
+ p_fl.add_argument("--actor", type=str, default="cli")
592
+ p_fl.add_argument("--json", action="store_true")
564
593
  p_os = sub.add_parser("seismicity", help="operations and seismicity: each well's drilling, completion and disposal windows against the earthquake catalogue around it - the events during and after each, the levels a regulator's protocol would reach, and the rate during operations against the rest of the record; the Mahoning Valley worked example")
565
594
  p_os.add_argument("--workspace", type=str, default=None)
566
595
  p_os.add_argument("--scene", type=str, default=None, choices=("workspace", "mahoning"), help="your wells (the default with --workspace) or the public worked example")
@@ -2608,6 +2637,56 @@ def main(argv=None) -> int:
2608
2637
  raise SystemExit(f"penetrator: {e.args[0] if e.args else e}")
2609
2638
  print(_json.dumps(p, default=str) if a.json else _PN.text(p))
2610
2639
  return 0
2640
+ elif a.cmd == "fluid":
2641
+ import json as _json
2642
+ from . import fluid as _FL
2643
+ from .cli import _safe_stdout
2644
+ from .workspace import Workspace, WorkspaceError
2645
+ _safe_stdout()
2646
+ if not a.workspace:
2647
+ r = _FL.selftest()
2648
+ print(_json.dumps(r, default=str) if a.json else "\n".join(f"{'PASS' if c['pass'] else 'FAIL'} {c['check']}" + (f": {c['value']}" if 'value' in c else '') for c in r["checks"]) + f"\n{'OK' if r['ok'] else 'FAILED'} - {r['label']}")
2649
+ return 0 if r["ok"] else 1
2650
+ try:
2651
+ ws = Workspace(a.workspace)
2652
+ except WorkspaceError as e:
2653
+ raise SystemExit(f"fluid: {e}")
2654
+ try:
2655
+ if a.remove:
2656
+ r = _FL.remove(ws, a.actor, a.well, a.report, None if a.well else a.formation)
2657
+ print("removed " + ", ".join(f"{k} {v}" for k, v in r.items())); return 0
2658
+ if a.attach:
2659
+ if not a.well:
2660
+ raise SystemExit("fluid: --attach needs --well")
2661
+ with open(a.attach, "rb") as f:
2662
+ r = _FL.attach_report(ws, a.actor, a.well, os.path.basename(a.attach), f.read(), a.source)
2663
+ print(f"attached {r['file']} to {a.well}: {r['n_rows']} day(s), {r['start']} to {r['end']}; columns " + ", ".join(f"{k}={v}" for k, v in r["columns"].items())
2664
+ + (f"; {r['skipped']} row(s) skipped" if r["skipped"] else "") + (f"; {r['duplicate_days']} day(s) twice" if r["duplicate_days"] else ""))
2665
+ return 0
2666
+ if a.declare:
2667
+ if not a.well:
2668
+ raise SystemExit("fluid: --declare needs --well")
2669
+ r = _FL.declare_well(ws, a.actor, a.well, a.role, a.formation, a.density_sg, a.tds_mgl, a.density_ppg, a.from_day, a.to_day, a.source)
2670
+ print(f"{a.well}: role {r.get('role') or '-'}, formation {r.get('formation') or '-'}, {len(r.get('densities', []))} density declaration(s)")
2671
+ return 0
2672
+ fm_vals = {"porosity": a.porosity, "thickness_ft": a.thickness_ft, "area_acres": a.area_acres, "c_water_per_psi": a.c_water, "c_pore_per_psi": a.c_pore,
2673
+ "k_md": a.k_md, "mu_cp": a.mu_cp, "p_initial_psi": a.p_initial_psi, "water_sg": a.water_sg, "water_tds_mgl": a.water_tds_mgl}
2674
+ if a.formation and any(v is not None for v in fm_vals.values()):
2675
+ r = _FL.declare_formation(ws, a.actor, a.formation, a.source, **fm_vals)
2676
+ st = _FL.storage_declared(r)
2677
+ print(f"{a.formation}: " + ", ".join(f"{k} {v:g}" for k, v in r.items() if isinstance(v, (int, float))) + f"; {st['how']}")
2678
+ return 0
2679
+ if a.write:
2680
+ from . import __version__ as _ver84
2681
+ r = _FL.write_report(ws, _ver84, a.actor)
2682
+ print(f"written: {', '.join(r['files'])} under {r['folder']}")
2683
+ p = r["page"]
2684
+ else:
2685
+ p = _FL.page(ws, a.as_of)
2686
+ except (_FL.FluidError, WorkspaceError, ValueError, OSError) as e:
2687
+ raise SystemExit(f"fluid: {e.args[0] if e.args else e}")
2688
+ print(_json.dumps(p, default=str) if a.json else _FL.text(p))
2689
+ return 0
2611
2690
  elif a.cmd == "seismicity":
2612
2691
  import json as _json
2613
2692
  from . import op_seismicity as _OS
@@ -17430,6 +17430,203 @@ def section_ea_vpn_client(tmp: str) -> None:
17430
17430
  + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
17431
17431
 
17432
17432
 
17433
+ def section_eb_fluid(tmp: str) -> None:
17434
+ """Section EB - the fluid ledger and the material balance: the arithmetic on labelled scenes (McCain's density, the
17435
+ exponential integral, a closed tank's storage recovered, a leaking tank named with the volume it lost, the Hall
17436
+ slope, the front); the workspace (declarations with their sources and the refusals, the operator's reports read and
17437
+ kept with their SHA-256, a producer's liquid signed out, a disposal well in the ledger by its own declaration with
17438
+ the interval statement beside it, the formation's balance, the neighbours by distance with the other-formation
17439
+ rule, the report written, the words free of the client-report terms); the routes, the tab, the command, the help,
17440
+ the README and the lesson."""
17441
+ import base64 as _b64
17442
+ import http.cookiejar
17443
+ import subprocess as _sp
17444
+ import urllib.error
17445
+ import urllib.request
17446
+ from datetime import datetime, timedelta
17447
+ from . import __version__ as _ver
17448
+ from . import client_reports as CR
17449
+ from . import fluid as FL
17450
+ from . import helplib as H
17451
+ from .service import Service, Users
17452
+ from .workspace import Workspace
17453
+ pkg = Path(__file__).parent
17454
+ d = Path(tmp, "eb"); d.mkdir()
17455
+ # -- EB1 the arithmetic ---------------------------------------------------------------------------------------------------
17456
+ st = FL.selftest()
17457
+ sc = FL.synthetic_scene(days=200, leak_fraction=0.0, seed=3, storage_bbl_per_psi=900.0)
17458
+ rows = FL.parse_report(sc["csv"])["rows"]
17459
+ days = []; cum = 0.0
17460
+ for r in rows:
17461
+ cum += r["volume"]
17462
+ days.append({"date": r["date"], "volume_bbl": r["volume"], "cum_bbl": cum, "p_avg_psi": r["p_avg"], "p_max_psi": None, "bhp_psi": r["bhp"], "sg": None, "tds_mgl": None, "water_t": None, "solids_t": None})
17463
+ vp = 900.0 / (FL.C_WATER_PER_PSI + FL.C_PORE_PER_PSI)
17464
+ fm = {"porosity": 0.1, "thickness_ft": 200.0, "area_acres": vp / (FL.BBL_PER_ACRE_FT * 200.0 * 0.1), "k_md": 30.0, "mu_cp": 0.6}
17465
+ fb = FL.formation_balance("T", fm, [{"well": "I", "days": days}])
17466
+ small = FL.formation_balance("S", {**fm, "area_acres": fm["area_acres"] * 4.0}, [{"well": "I", "days": days}]) # four times the room declared: the pressure rose more than it allows
17467
+ e1 = {x: FL._e1(x) for x in (0.1, 1.0, 5.0)}
17468
+ c1 = {
17469
+ "selftest": st["ok"] and st["label"] == "SIMULATION" and len(st["checks"]) >= 12,
17470
+ "mccain": abs(FL.density_from_tds(150000.0)["sg"] - 1.104) < 0.01 and FL.density_from_tds(0.0)["sg"] == 1.0,
17471
+ "declaration": FL.density_declaration(ppg=9.0)["sg_how"].startswith("declared as 9") and "note" in FL.density_declaration(sg=1.0, tds_mgl=200000.0),
17472
+ "e1": abs(e1[0.1] - 1.8229) < 1e-3 and abs(e1[1.0] - 0.21938) < 1e-4 and abs(e1[5.0] - 0.0011483) < 1e-6,
17473
+ "closed": fb["verdict"] == FL.STATUS_CLOSED and abs(fb["fit"]["storage_bbl_per_psi"] / 900.0 - 1.0) < 0.05 and abs(fb["unaccounted_bbl"]) < 0.06 * fb["cum_net_bbl"],
17474
+ "less_room": small["verdict"] == FL.STATUS_LESS and small["storage_ratio"] < 0.3,
17475
+ "front": abs(FL.radius_of_investigation_ft(100.0, 240.0, 0.2, 1.0, 1e-5) - 0.0325 * (100.0 * 240.0 / (0.2 * 1.0 * 1e-5)) ** 0.5) < 1e-6
17476
+ and FL.line_source_dp_psi(5000.0, 30.0, 200.0, 0.1, 0.6, 7e-6, 500.0, 2400.0) > FL.line_source_dp_psi(5000.0, 30.0, 200.0, 0.1, 0.6, 7e-6, 5000.0, 2400.0) > 0.0
17477
+ and abs(FL.volume_to_reach_bbl(FL.swept_radius_ft(250000.0, 200.0, 0.1), 200.0, 0.1) - 250000.0) < 1.0,
17478
+ "mass": FL.mass_of(1000.0, 1.1, 100000.0) == (174.89, 15.899),
17479
+ }
17480
+ failed1 = [k for k, v in c1.items() if not v]
17481
+ ok(not failed1,
17482
+ "EB1 the arithmetic on labelled scenes: McCain's brine density (150,000 mg/L at 1.10; fresh water at 1.000) and a declaration in lb/gal, with the note "
17483
+ "when a declared gravity and TDS disagree; E1 at 0.1, 1 and 5; a closed tank's storage recovered within 5% and called CLOSED AS DECLARED, a quarter "
17484
+ "of the room declared called LESS ROOM; the radius of investigation, the line source falling with distance, the swept cylinder's volume round-tripping, "
17485
+ "the tonnes of brine and solids in a thousand barrels" + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
17486
+ # -- EB2 the workspace ------------------------------------------------------------------------------------------------------
17487
+ wsp = str(d / "ws"); ws = Workspace.create(wsp, "Pad 3", actor="tester")
17488
+ inj = ws.add_well_records("SWD 1", actor="tester"); prod = ws.add_well_records("Producer 7H", actor="tester"); far = ws.add_well_records("Far 2", actor="tester")
17489
+ for w_, la, lo in ((inj, 31.96, -102.24), (prod, 31.965, -102.24), (far, 32.05, -102.30)):
17490
+ ws.set_well(w_["id"], surface={"lat": la, "lon": lo, "datum": "NAD83"}, actor="tester")
17491
+ ws.set_well(inj["id"], disposal={"top_interval_ft": 8700.0, "base_interval_ft": 9300.0, "depth_reference": "TVD", "depth_tier": "deep"}, actor="tester")
17492
+ refused = {}
17493
+ for name, fn in (("role", lambda: FL.declare_well(ws, "tester", inj["id"], role="pumping", source="x")),
17494
+ ("source", lambda: FL.declare_well(ws, "tester", inj["id"], role="injection")),
17495
+ ("nothing", lambda: FL.declare_well(ws, "tester", inj["id"], source="x")),
17496
+ ("well", lambda: FL.declare_well(ws, "tester", "nowhere", role="injection", source="x")),
17497
+ ("tds", lambda: FL.declare_well(ws, "tester", inj["id"], tds_mgl=900000.0, source="x")),
17498
+ ("no_date", lambda: FL.attach_report(ws, "tester", inj["id"], "x.csv", b"volume_bbl,bhp_psi\n1,2\n", "x")),
17499
+ ("no_volume", lambda: FL.attach_report(ws, "tester", inj["id"], "x.csv", b"date,bhp_psi\n2026-01-01,2\n", "x")),
17500
+ ("fm_source", lambda: FL.declare_formation(ws, "tester", "E", "", porosity=0.1)),
17501
+ ("fm_empty", lambda: FL.declare_formation(ws, "tester", "E", "s")),
17502
+ ("rm_none", lambda: FL.remove(ws, "tester", formation="Nowhere"))):
17503
+ try:
17504
+ fn(); refused[name] = False
17505
+ except FL.FluidError:
17506
+ refused[name] = True
17507
+ before = FL.page(ws) # the disposal well alone, by its declaration, no record
17508
+ leak = FL.synthetic_scene(days=240, leak_fraction=0.6, seed=5)
17509
+ FL.declare_well(ws, "tester", inj["id"], role="injection", formation="Ellenburger", source="completion report W-2")
17510
+ FL.declare_well(ws, "tester", inj["id"], tds_mgl=120000.0, source="water analysis 2026-01")
17511
+ FL.declare_well(ws, "tester", prod["id"], role="production", formation="Ellenburger", sg=1.05, source="permit")
17512
+ FL.declare_well(ws, "tester", far["id"], role="production", formation="Wolfcamp", source="permit")
17513
+ rep = FL.attach_report(ws, "tester", inj["id"], "h10 2026.csv", leak["csv"].encode(), "H-10 filed 2026-09")
17514
+ pcsv = "Date,Oil (bbl),Water (bbl),Gas (mcf)\n" + "\n".join(f"{(datetime(2026, 1, 1) + timedelta(days=i)).strftime('%m/%d/%Y')},{50 + i % 7},{300 + i % 11},900" for i in range(200)) + "\n"
17515
+ FL.attach_report(ws, "tester", prod["id"], "prod.csv", pcsv.encode(), "operator production report")
17516
+ vp = 600.0 / 7e-6
17517
+ FL.declare_formation(ws, "tester", "Ellenburger", "petrophysics 2025", porosity=0.12, thickness_ft=100.0, area_acres=vp / (7758 * 100 * 0.12), k_md=50, mu_cp=0.6, p_initial_psi=3000, water_tds_mgl=60000)
17518
+ pg = FL.page(ws)
17519
+ wl = {w_["well"]: w_ for w_ in pg["wells"]}
17520
+ el = next(f_ for f_ in pg["formations"] if f_["formation"] == "Ellenburger")
17521
+ wc = next(f_ for f_ in pg["formations"] if f_["formation"] == "Wolfcamp")
17522
+ nb = wl[inj["id"]]["neighbours"]; nbr = {r_["well"]: r_ for r_ in nb["rows"]}
17523
+ wr = FL.write_report(ws, _ver, "tester")
17524
+ txt = (Path(wr["folder"]) / "fluid_balance.md").read_text(encoding="utf-8").lower()
17525
+ # the report file changed under its hash is not read; the declaration removed takes the well out
17526
+ rp = Path(ws.well_dir(inj["id"]), "records", "fluid", rep["file"]); rep_bytes = rp.read_bytes(); rp.write_bytes(rep_bytes + b"2026-12-31,1,1,1,1\n")
17527
+ pg2 = FL.page(ws)
17528
+ rp.write_bytes(rep_bytes)
17529
+ FL.remove(ws, "tester", well_id=prod["id"])
17530
+ pg3 = FL.page(ws)
17531
+ audit = Path(ws.audit_path).read_text(encoding="utf-8")
17532
+ c2 = {
17533
+ "refusals": all(refused.values()),
17534
+ "before": before["status"] == "OK" and len(before["wells"]) == 1 and before["wells"][0]["role"] == "injection" and before["wells"][0]["record"] == "NO VOLUME RECORD"
17535
+ and "declaration" in before["wells"][0]["role_how"] and before["formations"] == [],
17536
+ "report_kept": rep["file"] == "h10_2026.csv" and rep["n_rows"] == 240 and rep["columns"]["tds"] == "tds_mgl" and rp.is_file() and len(rep["sha256"]) == 64,
17537
+ "ledger": wl[inj["id"]]["n_with_volume"] == 240 and wl[inj["id"]]["cum_bbl"] > 1.5e6 and wl[inj["id"]]["record"].startswith("the operator")
17538
+ and wl[inj["id"]]["days"][0]["density_from"] == "the report" and wl[inj["id"]]["cum_solids_t"] > 30000.0
17539
+ and wl[prod["id"]]["cum_bbl"] < 0 and wl[prod["id"]]["n_with_volume"] == 200 and abs(wl[prod["id"]]["days"][0]["volume_bbl"] + 350.0) < 0.01
17540
+ and wl[prod["id"]]["days"][0]["density_from"] == "permit" and wl[far["id"]]["record"] == "NO VOLUME RECORD",
17541
+ "interval": wl[inj["id"]].get("interval") is not None and "status" in wl[inj["id"]]["interval"],
17542
+ "balance": el["verdict"] == FL.STATUS_MORE and el["storage_ratio"] > 2.0 and abs(el["unaccounted_bbl"] / leak["truth"]["leaked_bbl"] - 1.0) < 0.12
17543
+ and el["cum_out_bbl"] > 60000.0 and el["unaccounted_solids_t"] > 0 and wc["status"] == "NO RECORD" and wc["storage"]["status"] == "NOT DECLARED",
17544
+ "hall": wl[inj["id"]]["hall"]["status"] == "DRAWN" and wl[inj["id"]]["hall"]["p_e_how"].startswith("declared"),
17545
+ "neighbours": 1700.0 < nbr[prod["id"]]["distance_ft"] < 1900.0 and nbr[prod["id"]]["front"] == "ARRIVED" and nbr[prod["id"]]["dp_now_psi"] > 100.0
17546
+ and nbr[prod["id"]]["dp_1yr_psi"] > nbr[prod["id"]]["dp_now_psi"] and nbr[far["id"]]["front"] == "OTHER FORMATION" and "dp_now_psi" not in nbr[far["id"]]
17547
+ and nb["density_difference"]["delta_sg"] > 0.03 and "under-rides" in nb["density_difference"]["reading"] and nb["projection"]["label"].startswith("SIMULATION"),
17548
+ "written": set(wr["files"]) >= {"fluid_balance.json", "fluid_balance.md", "ledger_Ellenburger.csv", f"well_{inj['id']}.csv"} and "unaccounted" in txt and "simulation" in txt
17549
+ and not [t for t in CR.FORBIDDEN_TERMS if t in txt],
17550
+ "changed_file": any("changed since it was attached" in n_ for n_ in next(w_ for w_ in pg2["wells"] if w_["well"] == inj["id"])["notes"])
17551
+ and next(w_ for w_ in pg2["wells"] if w_["well"] == inj["id"])["record"] == "NO VOLUME RECORD",
17552
+ "removed": prod["id"] not in {w_["well"] for w_ in pg3["wells"]} and all(x in audit for x in ("fluid.declare", "fluid.formation", "fluid.report.attach", "fluid.report", "fluid.remove")),
17553
+ }
17554
+ failed2 = [k for k, v in c2.items() if not v]
17555
+ ok(not failed2,
17556
+ "EB2 the workspace: a role not injection or production, a declaration or a report without its source, nothing declared, an unknown well, a TDS beyond "
17557
+ "brine, a report without a date or a volume column, a formation without a source or a value, a removal of nothing - each declined by name; a disposal "
17558
+ "well is in the ledger by its own declaration with NO VOLUME RECORD until a report comes, the interval statement beside it; the operator's report kept "
17559
+ "under the well's records with its SHA-256 and read day by day (the report's own TDS first, the declared density after), a producer's oil and water "
17560
+ "signed out, the formation's balance MORE ROOM THAN DECLARED with the unaccounted barrels within 12% of what the labelled tank lost and their solids; the "
17561
+ "Hall plot on the declared initial pressure; the neighbours by surface distance - the near producer with the front ARRIVED and the pressure rising a year "
17562
+ "on, the well in another formation given its distance and no projection, the denser injectate said to under-ride; the report written with its CSVs and "
17563
+ "free of the client-report terms; a report file changed under its hash not read; a declaration removed takes the well out; every step audited"
17564
+ + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
17565
+ # -- EB3 the routes, the tab, the command, the help, the README and the lesson -----------------------------------------------
17566
+ Users(str(Path(wsp, "users.json"))).add("v", "viewer-pass-1", "viewer"); Users(str(Path(wsp, "users.json"))).add("op", "op-pass-123", "operator")
17567
+ svc = Service(wsp, port=0, scheduler=False).start()
17568
+ base_url = svc.url.rstrip("/")
17569
+
17570
+ def opener(name, pw_):
17571
+ o = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
17572
+ rq = urllib.request.Request(base_url + "/api/login", method="POST", data=json.dumps({"name": name, "password": pw_}).encode())
17573
+ rq.add_header("Content-Type", "application/json"); rq.add_header("X-GEA-Action", "1"); o.open(rq, timeout=30)
17574
+ return o
17575
+
17576
+ def call(o, method, path, body=None):
17577
+ rq = urllib.request.Request(base_url + path, method=method, data=(json.dumps(body).encode() if body is not None else None))
17578
+ if method == "POST":
17579
+ rq.add_header("Content-Type", "application/json"); rq.add_header("X-GEA-Action", "1")
17580
+ try:
17581
+ with o.open(rq, timeout=120) as rr_:
17582
+ return rr_.status, json.loads(rr_.read())
17583
+ except urllib.error.HTTPError as e:
17584
+ return e.code, json.loads(e.read())
17585
+ try:
17586
+ V, O = opener("v", "viewer-pass-1"), opener("op", "op-pass-123")
17587
+ s_vg, vg = call(V, "GET", "/api/fluid")
17588
+ s_vd, _ = call(V, "POST", "/api/fluid/declare", {"well_id": prod["id"], "role": "production", "source": "x"})
17589
+ s_od, od = call(O, "POST", "/api/fluid/declare", {"well_id": prod["id"], "role": "production", "formation": "Ellenburger", "density_sg": "1.05", "source": "permit (api)"})
17590
+ s_bd, _ = call(O, "POST", "/api/fluid/declare", {"well_id": prod["id"], "role": "pumping", "source": "x"})
17591
+ s_nw, _ = call(O, "POST", "/api/fluid/declare", {"well_id": "nowhere", "role": "injection", "source": "x"})
17592
+ s_or, orp = call(O, "POST", "/api/fluid/report", {"well_id": prod["id"], "filename": "prod.csv", "content_b64": _b64.b64encode(pcsv.encode()).decode(), "source": "api"})
17593
+ s_br, _ = call(O, "POST", "/api/fluid/report", {"well_id": prod["id"], "filename": "b.csv", "content_b64": "***", "source": "api"})
17594
+ s_of, of_ = call(O, "POST", "/api/fluid/formation", {"name": "Wolfcamp", "porosity": "0.06", "thickness_ft": "300", "area_acres": "640", "source": "api"})
17595
+ s_ow, ow = call(O, "POST", "/api/fluid/write", {})
17596
+ s_g2, g2 = call(V, "GET", "/api/fluid")
17597
+ s_rm, _ = call(O, "POST", "/api/fluid/remove", {"formation": "Wolfcamp"})
17598
+ s_r2, _ = call(O, "POST", "/api/fluid/remove", {"formation": "Wolfcamp"})
17599
+ finally:
17600
+ svc.stop()
17601
+ cli_s = _sp.run([sys.executable, "-m", "gea", "fluid"], capture_output=True, text=True, cwd=str(pkg.parent))
17602
+ cli_j = _sp.run([sys.executable, "-m", "gea", "fluid", "--json"], capture_output=True, text=True, cwd=str(pkg.parent))
17603
+ cli_w = _sp.run([sys.executable, "-m", "gea", "fluid", "--workspace", wsp], capture_output=True, text=True, cwd=str(pkg.parent))
17604
+ cli_d = _sp.run([sys.executable, "-m", "gea", "fluid", "--workspace", wsp, "--declare", "--well", far["id"], "--tds-mgl", "80000", "--from", "2026-01-01", "--source", "analysis (cli)"], capture_output=True, text=True, cwd=str(pkg.parent))
17605
+ cli_f = _sp.run([sys.executable, "-m", "gea", "fluid", "--workspace", wsp, "--formation", "Wolfcamp", "--porosity", "0.06", "--thickness-ft", "300", "--area-acres", "640", "--source", "cli"], capture_output=True, text=True, cwd=str(pkg.parent))
17606
+ cli_b = _sp.run([sys.executable, "-m", "gea", "fluid", "--workspace", wsp, "--declare", "--well", far["id"], "--role", "injection"], capture_output=True, text=True, cwd=str(pkg.parent))
17607
+ page_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
17608
+ readme = (pkg.parent / "README.md").read_text(encoding="utf-8") if (pkg.parent / "README.md").is_file() else ""
17609
+ lesson = (pkg / "help" / "tutorial" / "14-production-pages.md").read_text(encoding="utf-8")
17610
+ c3 = {
17611
+ "api": s_vg == 200 and vg["status"] == "OK" and s_vd == 403 and s_od == 200 and od["role"] == "production" and s_bd == 400 and s_nw == 400 and s_or == 200 and orp["n_rows"] == 200
17612
+ and s_br == 400 and s_of == 200 and of_["porosity"] == 0.06 and s_ow == 200 and "fluid_balance.json" in ow["files"] and s_g2 == 200
17613
+ and any(f_["formation"] == "Wolfcamp" and f_["storage"]["status"] == "OK" for f_ in g2["formations"]) and s_rm == 200 and s_r2 == 400,
17614
+ "cli": cli_s.returncode == 0 and "OK - SIMULATION" in cli_s.stdout and cli_j.returncode == 0 and json.loads(cli_j.stdout)["ok"] is True
17615
+ and cli_w.returncode == 0 and "MORE ROOM THAN DECLARED" in cli_w.stdout and "Hall plot" in cli_w.stdout and cli_d.returncode == 0 and "1 density" in cli_d.stdout
17616
+ and cli_f.returncode == 0 and "storage c_t V_p" in cli_f.stdout and cli_b.returncode != 0 and "source" in cli_b.stderr,
17617
+ "page": all(x in page_src for x in ("VIEWS.fluid", "['#/fluid', 'Fluid balance']", "/api/fluid/declare", "/api/fluid/report", "/api/fluid/formation", "flBalancePlot", "flHallPlot", "help('fluid')")),
17618
+ "help": not H.check("fluid") and H.VIEW_TOPIC.get("fluid") == "fluid" and any(t == "fluid" for t, _, _ in H.INDEX)
17619
+ and all(x in (H.page("fluid") or "") for x in ("McCain", "Hall", "SIMULATION", "gea fluid --workspace C:\\site", "7,758")),
17620
+ "readme_lesson": (not readme or ("### Fluid balance" in readme and "`gea fluid`" in readme)) and "Fluid balance" in lesson and "fluid" in lesson.split("Help:")[-1],
17621
+ }
17622
+ failed3 = [k for k, v in c3.items() if not v]
17623
+ ok(not failed3,
17624
+ "EB3 on the API (anyone reads the balance; only an operator declares, attaches a report, declares a formation, writes or removes - a bad role, an "
17625
+ "unknown well, a report that is not base64 and a removal of nothing are 400), the command (the self-test plain and as JSON, the balance, a density "
17626
+ "from the command line, a formation, a declaration without its source stopped), the tab with its two plots, the help page, the README and lesson 14"
17627
+ + (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
17628
+
17629
+
17433
17630
  def main() -> int:
17434
17631
  print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
17435
17632
  # a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
@@ -17564,6 +17761,7 @@ def main() -> int:
17564
17761
  section_dy_vibration(tmp)
17565
17762
  section_dz_textbook_oracle(tmp)
17566
17763
  section_ea_vpn_client(tmp)
17764
+ section_eb_fluid(tmp)
17567
17765
  if _FAILS:
17568
17766
  print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
17569
17767
  for f in _FAILS: