gea-program 0.24.0__tar.gz → 0.25.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 (266) hide show
  1. {gea_program-0.24.0 → gea_program-0.25.0}/PKG-INFO +15 -2
  2. {gea_program-0.24.0 → gea_program-0.25.0}/README.md +14 -1
  3. {gea_program-0.24.0 → gea_program-0.25.0}/gea/__init__.py +1 -1
  4. {gea_program-0.24.0 → gea_program-0.25.0}/gea/__main__.py +61 -3
  5. {gea_program-0.24.0 → gea_program-0.25.0}/gea/acceptance_tests.py +107 -0
  6. gea_program-0.25.0/gea/catalog_register.py +146 -0
  7. gea_program-0.25.0/gea/friction_priors.py +133 -0
  8. gea_program-0.25.0/gea/help/catalog.md +11 -0
  9. {gea_program-0.24.0 → gea_program-0.25.0}/gea/helplib.py +1 -0
  10. {gea_program-0.24.0 → gea_program-0.25.0}/gea/model_card.py +4 -2
  11. {gea_program-0.24.0 → gea_program-0.25.0}/gea/rock_inventory.py +26 -0
  12. {gea_program-0.24.0 → gea_program-0.25.0}/gea/survey_cmd.py +9 -1
  13. {gea_program-0.24.0 → gea_program-0.25.0}/gea_program.egg-info/PKG-INFO +15 -2
  14. {gea_program-0.24.0 → gea_program-0.25.0}/gea_program.egg-info/SOURCES.txt +3 -0
  15. {gea_program-0.24.0 → gea_program-0.25.0}/pyproject.toml +1 -1
  16. {gea_program-0.24.0 → gea_program-0.25.0}/LICENSE +0 -0
  17. {gea_program-0.24.0 → gea_program-0.25.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
  18. {gea_program-0.24.0 → gea_program-0.25.0}/gea/accuracy_statement.py +0 -0
  19. {gea_program-0.24.0 → gea_program-0.25.0}/gea/alarm_engine.py +0 -0
  20. {gea_program-0.24.0 → gea_program-0.25.0}/gea/backup.py +0 -0
  21. {gea_program-0.24.0 → gea_program-0.25.0}/gea/bench.py +0 -0
  22. {gea_program-0.24.0 → gea_program-0.25.0}/gea/blind_harness.py +0 -0
  23. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
  24. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
  25. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
  26. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
  27. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
  28. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
  29. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
  30. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
  31. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
  32. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
  33. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
  34. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
  35. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
  36. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
  37. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
  38. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
  39. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
  40. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
  41. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
  42. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
  43. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
  44. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
  45. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
  46. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
  47. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
  48. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
  49. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
  50. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
  51. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
  52. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
  53. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
  54. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
  55. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
  56. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
  57. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
  58. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
  59. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
  60. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
  61. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
  62. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
  63. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
  64. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
  65. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
  66. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
  67. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
  68. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
  69. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
  70. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
  71. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
  72. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
  73. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
  74. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
  75. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
  76. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
  77. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
  78. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
  79. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
  80. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
  81. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
  82. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
  83. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
  84. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
  85. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
  86. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
  87. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
  88. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
  89. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
  90. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/med_160_sapropels.txt +0 -0
  91. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
  92. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
  93. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
  94. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
  95. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
  96. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
  97. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
  98. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
  99. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
  100. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
  101. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
  102. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
  103. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
  104. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
  105. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
  106. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
  107. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
  108. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
  109. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
  110. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
  111. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
  112. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
  113. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
  114. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
  115. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
  116. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
  117. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
  118. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
  119. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
  120. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
  121. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
  122. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
  123. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
  124. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
  125. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
  126. {gea_program-0.24.0 → gea_program-0.25.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
  127. {gea_program-0.24.0 → gea_program-0.25.0}/gea/certificates.py +0 -0
  128. {gea_program-0.24.0 → gea_program-0.25.0}/gea/cli.py +0 -0
  129. {gea_program-0.24.0 → gea_program-0.25.0}/gea/client_reports.py +0 -0
  130. {gea_program-0.24.0 → gea_program-0.25.0}/gea/config_versioning.py +0 -0
  131. {gea_program-0.24.0 → gea_program-0.25.0}/gea/conformance.py +0 -0
  132. {gea_program-0.24.0 → gea_program-0.25.0}/gea/correlation.py +0 -0
  133. {gea_program-0.24.0 → gea_program-0.25.0}/gea/dashboard.py +0 -0
  134. {gea_program-0.24.0 → gea_program-0.25.0}/gea/deviation.py +0 -0
  135. {gea_program-0.24.0 → gea_program-0.25.0}/gea/dlis.py +0 -0
  136. {gea_program-0.24.0 → gea_program-0.25.0}/gea/dnp3.py +0 -0
  137. {gea_program-0.24.0 → gea_program-0.25.0}/gea/doctor.py +0 -0
  138. {gea_program-0.24.0 → gea_program-0.25.0}/gea/downhole_engine.py +0 -0
  139. {gea_program-0.24.0 → gea_program-0.25.0}/gea/drift_monitor.py +0 -0
  140. {gea_program-0.24.0 → gea_program-0.25.0}/gea/earth_model.py +0 -0
  141. {gea_program-0.24.0 → gea_program-0.25.0}/gea/elevation.py +0 -0
  142. {gea_program-0.24.0 → gea_program-0.25.0}/gea/etp.py +0 -0
  143. {gea_program-0.24.0 → gea_program-0.25.0}/gea/etp12_schemas.json +0 -0
  144. {gea_program-0.24.0 → gea_program-0.25.0}/gea/example_register_map.json +0 -0
  145. {gea_program-0.24.0 → gea_program-0.25.0}/gea/fat_sat.py +0 -0
  146. {gea_program-0.24.0 → gea_program-0.25.0}/gea/files.py +0 -0
  147. {gea_program-0.24.0 → gea_program-0.25.0}/gea/follower.py +0 -0
  148. {gea_program-0.24.0 → gea_program-0.25.0}/gea/forward_model.py +0 -0
  149. {gea_program-0.24.0 → gea_program-0.25.0}/gea/gamma.py +0 -0
  150. {gea_program-0.24.0 → gea_program-0.25.0}/gea/gauge_aging.py +0 -0
  151. {gea_program-0.24.0 → gea_program-0.25.0}/gea/gauge_specs.py +0 -0
  152. {gea_program-0.24.0 → gea_program-0.25.0}/gea/geodesy.py +0 -0
  153. {gea_program-0.24.0 → gea_program-0.25.0}/gea/gravity_reference.py +0 -0
  154. {gea_program-0.24.0 → gea_program-0.25.0}/gea/hartip.py +0 -0
  155. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/TESTER_GUIDE.md +0 -0
  156. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/alarms.md +0 -0
  157. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/audit-update.md +0 -0
  158. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/backup.md +0 -0
  159. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/conformance.md +0 -0
  160. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/data-in.md +0 -0
  161. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/dlis.md +0 -0
  162. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/doctor.md +0 -0
  163. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/drift.md +0 -0
  164. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/etp.md +0 -0
  165. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/field-ports.md +0 -0
  166. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/files.md +0 -0
  167. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/historian.md +0 -0
  168. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/instruments.md +0 -0
  169. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/interval.md +0 -0
  170. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/month-end.md +0 -0
  171. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/notifications.md +0 -0
  172. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/osdu.md +0 -0
  173. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/patches.md +0 -0
  174. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/ppdm.md +0 -0
  175. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/quakeml.md +0 -0
  176. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/quality.md +0 -0
  177. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/seedlink.md +0 -0
  178. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/seismic.md +0 -0
  179. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/site.md +0 -0
  180. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/sites.md +0 -0
  181. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/soak.md +0 -0
  182. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/sra.md +0 -0
  183. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/start.md +0 -0
  184. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/structure.md +0 -0
  185. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/transients.md +0 -0
  186. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/upkeep.md +0 -0
  187. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/vibration.md +0 -0
  188. {gea_program-0.24.0 → gea_program-0.25.0}/gea/help/well-tests.md +0 -0
  189. {gea_program-0.24.0 → gea_program-0.25.0}/gea/housekeeping.py +0 -0
  190. {gea_program-0.24.0 → gea_program-0.25.0}/gea/interval.py +0 -0
  191. {gea_program-0.24.0 → gea_program-0.25.0}/gea/inverse_engine.py +0 -0
  192. {gea_program-0.24.0 → gea_program-0.25.0}/gea/jobs.py +0 -0
  193. {gea_program-0.24.0 → gea_program-0.25.0}/gea/live_ports.py +0 -0
  194. {gea_program-0.24.0 → gea_program-0.25.0}/gea/loadtest.py +0 -0
  195. {gea_program-0.24.0 → gea_program-0.25.0}/gea/matplotlib_demo.py +0 -0
  196. {gea_program-0.24.0 → gea_program-0.25.0}/gea/modbus.py +0 -0
  197. {gea_program-0.24.0 → gea_program-0.25.0}/gea/modbus_rtu.py +0 -0
  198. {gea_program-0.24.0 → gea_program-0.25.0}/gea/month_end.py +0 -0
  199. {gea_program-0.24.0 → gea_program-0.25.0}/gea/mqtt_port.py +0 -0
  200. {gea_program-0.24.0 → gea_program-0.25.0}/gea/notify.py +0 -0
  201. {gea_program-0.24.0 → gea_program-0.25.0}/gea/opcua_port.py +0 -0
  202. {gea_program-0.24.0 → gea_program-0.25.0}/gea/operator_app.py +0 -0
  203. {gea_program-0.24.0 → gea_program-0.25.0}/gea/osdu.py +0 -0
  204. {gea_program-0.24.0 → gea_program-0.25.0}/gea/patches.py +0 -0
  205. {gea_program-0.24.0 → gea_program-0.25.0}/gea/permits.py +0 -0
  206. {gea_program-0.24.0 → gea_program-0.25.0}/gea/piwebapi.py +0 -0
  207. {gea_program-0.24.0 → gea_program-0.25.0}/gea/ports.py +0 -0
  208. {gea_program-0.24.0 → gea_program-0.25.0}/gea/ppdm.py +0 -0
  209. {gea_program-0.24.0 → gea_program-0.25.0}/gea/profile_catalog.py +0 -0
  210. {gea_program-0.24.0 → gea_program-0.25.0}/gea/project.py +0 -0
  211. {gea_program-0.24.0 → gea_program-0.25.0}/gea/qt6_downhole_app.py +0 -0
  212. {gea_program-0.24.0 → gea_program-0.25.0}/gea/quakeml.py +0 -0
  213. {gea_program-0.24.0 → gea_program-0.25.0}/gea/reconciler.py +0 -0
  214. {gea_program-0.24.0 → gea_program-0.25.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
  215. {gea_program-0.24.0 → gea_program-0.25.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
  216. {gea_program-0.24.0 → gea_program-0.25.0}/gea/reference/libmseed_steim.provenance.json +0 -0
  217. {gea_program-0.24.0 → gea_program-0.25.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
  218. {gea_program-0.24.0 → gea_program-0.25.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
  219. {gea_program-0.24.0 → gea_program-0.25.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
  220. {gea_program-0.24.0 → gea_program-0.25.0}/gea/sample_record.py +0 -0
  221. {gea_program-0.24.0 → gea_program-0.25.0}/gea/sample_well_profile.csv +0 -0
  222. {gea_program-0.24.0 → gea_program-0.25.0}/gea/sbom.py +0 -0
  223. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seedlink.py +0 -0
  224. {gea_program-0.24.0 → gea_program-0.25.0}/gea/segy.py +0 -0
  225. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic.py +0 -0
  226. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_array.py +0 -0
  227. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_assoc.py +0 -0
  228. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_detect.py +0 -0
  229. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_film.py +0 -0
  230. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_harmonic.py +0 -0
  231. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_qc.py +0 -0
  232. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_response.py +0 -0
  233. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_signature.py +0 -0
  234. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_track.py +0 -0
  235. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_uncertainty.py +0 -0
  236. {gea_program-0.24.0 → gea_program-0.25.0}/gea/seismic_unlisted.py +0 -0
  237. {gea_program-0.24.0 → gea_program-0.25.0}/gea/sensor_swap.py +0 -0
  238. {gea_program-0.24.0 → gea_program-0.25.0}/gea/service.py +0 -0
  239. {gea_program-0.24.0 → gea_program-0.25.0}/gea/service_life.py +0 -0
  240. {gea_program-0.24.0 → gea_program-0.25.0}/gea/shapefile.py +0 -0
  241. {gea_program-0.24.0 → gea_program-0.25.0}/gea/shell.py +0 -0
  242. {gea_program-0.24.0 → gea_program-0.25.0}/gea/shut_in.py +0 -0
  243. {gea_program-0.24.0 → gea_program-0.25.0}/gea/sla_report.py +0 -0
  244. {gea_program-0.24.0 → gea_program-0.25.0}/gea/soak.py +0 -0
  245. {gea_program-0.24.0 → gea_program-0.25.0}/gea/sra.py +0 -0
  246. {gea_program-0.24.0 → gea_program-0.25.0}/gea/store_forward.py +0 -0
  247. {gea_program-0.24.0 → gea_program-0.25.0}/gea/strata_join.py +0 -0
  248. {gea_program-0.24.0 → gea_program-0.25.0}/gea/structure.py +0 -0
  249. {gea_program-0.24.0 → gea_program-0.25.0}/gea/supervisor.py +0 -0
  250. {gea_program-0.24.0 → gea_program-0.25.0}/gea/survey_view.py +0 -0
  251. {gea_program-0.24.0 → gea_program-0.25.0}/gea/telemetry.py +0 -0
  252. {gea_program-0.24.0 → gea_program-0.25.0}/gea/tool_library.py +0 -0
  253. {gea_program-0.24.0 → gea_program-0.25.0}/gea/transient.py +0 -0
  254. {gea_program-0.24.0 → gea_program-0.25.0}/gea/vibration.py +0 -0
  255. {gea_program-0.24.0 → gea_program-0.25.0}/gea/web/app.html +0 -0
  256. {gea_program-0.24.0 → gea_program-0.25.0}/gea/well_assembler.py +0 -0
  257. {gea_program-0.24.0 → gea_program-0.25.0}/gea/well_test_validation.py +0 -0
  258. {gea_program-0.24.0 → gea_program-0.25.0}/gea/wits0.py +0 -0
  259. {gea_program-0.24.0 → gea_program-0.25.0}/gea/witsml.py +0 -0
  260. {gea_program-0.24.0 → gea_program-0.25.0}/gea/workspace.py +0 -0
  261. {gea_program-0.24.0 → gea_program-0.25.0}/gea_program.egg-info/dependency_links.txt +0 -0
  262. {gea_program-0.24.0 → gea_program-0.25.0}/gea_program.egg-info/entry_points.txt +0 -0
  263. {gea_program-0.24.0 → gea_program-0.25.0}/gea_program.egg-info/requires.txt +0 -0
  264. {gea_program-0.24.0 → gea_program-0.25.0}/gea_program.egg-info/top_level.txt +0 -0
  265. {gea_program-0.24.0 → gea_program-0.25.0}/setup.cfg +0 -0
  266. {gea_program-0.24.0 → gea_program-0.25.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.24.0
3
+ Version: 0.25.0
4
4
  Summary: GEA-Program: downhole gauge monitoring - canonical measurement records, quality rules, drift evaluation with a re-fit change log, well-test validation, alarm management, model cards, store-and-forward, monthly SLA measurement, FAT/SAT protocols and a dashboard, generated from live objects in the client's reporting outline.
5
5
  Author: Daniel T. Murphy
6
6
  License: MPL-2.0
@@ -125,7 +125,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
125
125
  gea client-report --report accuracy --out client_report
126
126
  gea model-cards --out model_cards
127
127
  gea sbom --out sbom
128
- gea accept # the product gate (359 checks)
128
+ gea accept # the product gate (362 checks)
129
129
  gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
130
130
  gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
131
131
  gea gui # the desktop window (pip install "gea-program[desktop]")
@@ -648,6 +648,19 @@ against it; `gea seedlink --config ... --hello` prints what a server says of
648
648
  itself; `gea help seedlink`. A TexNet station is served by EarthScope at
649
649
  `rtserve.iris.washington.edu:18000`, network `TX`.
650
650
 
651
+ ### The catalogue accounted for
652
+
653
+ `gea catalog --list` is the register of the 52 shipped public datasets: for
654
+ each, what in this program reads it, or CARRIED, NO BAND with the reason;
655
+ the gate holds the register to the code both ways and reads every entry.
656
+ `gea survey --catalog <entry>` runs the strata survey on any catalogue log
657
+ with its provenance; `gea catalog --friction` reads seven laboratory
658
+ datasets on natural fault and sediment samples as the measured friction
659
+ envelope (0.21-0.90 on 70 measurements, none from the Permian) against
660
+ Byerlee's 0.6; `gea catalog --core` checks the published sandstone range
661
+ against the Volve core (65 of 70 plugs inside), an evaluation on the rock
662
+ inventory model card. `gea help catalog`.
663
+
651
664
  ### The log as delivered, and the historian
652
665
 
653
666
  A well log arrives as DLIS (API RP66 V1); `gea/dlis.py` reads the container
@@ -86,7 +86,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
86
86
  gea client-report --report accuracy --out client_report
87
87
  gea model-cards --out model_cards
88
88
  gea sbom --out sbom
89
- gea accept # the product gate (359 checks)
89
+ gea accept # the product gate (362 checks)
90
90
  gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
91
91
  gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
92
92
  gea gui # the desktop window (pip install "gea-program[desktop]")
@@ -609,6 +609,19 @@ against it; `gea seedlink --config ... --hello` prints what a server says of
609
609
  itself; `gea help seedlink`. A TexNet station is served by EarthScope at
610
610
  `rtserve.iris.washington.edu:18000`, network `TX`.
611
611
 
612
+ ### The catalogue accounted for
613
+
614
+ `gea catalog --list` is the register of the 52 shipped public datasets: for
615
+ each, what in this program reads it, or CARRIED, NO BAND with the reason;
616
+ the gate holds the register to the code both ways and reads every entry.
617
+ `gea survey --catalog <entry>` runs the strata survey on any catalogue log
618
+ with its provenance; `gea catalog --friction` reads seven laboratory
619
+ datasets on natural fault and sediment samples as the measured friction
620
+ envelope (0.21-0.90 on 70 measurements, none from the Permian) against
621
+ Byerlee's 0.6; `gea catalog --core` checks the published sandstone range
622
+ against the Volve core (65 of 70 plugs inside), an evaluation on the rock
623
+ inventory model card. `gea help catalog`.
624
+
612
625
  ### The log as delivered, and the historian
613
626
 
614
627
  A well log arrives as DLIS (API RP66 V1); `gea/dlis.py` reads the container
@@ -123,7 +123,7 @@ from .profile_catalog import (
123
123
  read_pangaea_txt,
124
124
  )
125
125
 
126
- __version__ = "0.24.0"
126
+ __version__ = "0.25.0"
127
127
  __all__ = [
128
128
  "aging_rate", "rate_psi_yr", "accuracy_psi",
129
129
  "Sensor", "SimulatorConfig", "DownholeEngine",
@@ -278,6 +278,11 @@ def main(argv=None) -> int:
278
278
  p_lp.add_argument("--stream-csv", type=str, default=None, help="also write a historian-style CSV the other commands ingest")
279
279
  p_lp.add_argument("--selftest", action="store_true", help="etp: the codec round-trip and a session against the simulated store on the loopback")
280
280
 
281
+ p_cat = sub.add_parser("catalog", help="the shipped catalogue: --list every entry with what reads it; --unused the carried ones; --check reads every entry; --friction the measured friction envelope; --core the core check; --entry X --info | --stream-csv")
282
+ p_cat.add_argument("--list", action="store_true"); p_cat.add_argument("--unused", action="store_true"); p_cat.add_argument("--check", action="store_true")
283
+ p_cat.add_argument("--friction", action="store_true"); p_cat.add_argument("--core", action="store_true")
284
+ p_cat.add_argument("--entry", type=str, default=None); p_cat.add_argument("--info", action="store_true"); p_cat.add_argument("--stream-csv", type=str, default=None)
285
+ p_cat.add_argument("--json", action="store_true")
281
286
  p_dl = sub.add_parser("dlis", help="a DLIS (RP66 V1) well log: --info describes it (origin, channels, frames, what was skipped); --frame --out writes the frame as a historian-style CSV; --to-las writes LAS 2.0")
282
287
  p_dl.add_argument("--file", type=str, required=True)
283
288
  p_dl.add_argument("--info", action="store_true")
@@ -689,6 +694,7 @@ def main(argv=None) -> int:
689
694
  p_sy = sub.add_parser("survey", help="a LAS or DLIS file in, one strata report out (--demo: the bundled public KTB excerpt); --out writes report.txt + survey.json")
690
695
  p_sy.add_argument("--file", type=str, default=None, help="LAS 2.0 or DLIS (RP66 V1) file")
691
696
  p_sy.add_argument("--frame", type=str, default=None, help="DLIS: the frame to read when the file holds several (gea dlis --file X --info lists them)")
697
+ p_sy.add_argument("--catalog", type=str, default=None, help="a catalogue LAS entry instead of a file (gea catalog --list names them)")
692
698
  p_sy.add_argument("--demo", action="store_true")
693
699
  p_sy.add_argument("--family", type=str, default="continental_crystalline", help="prior family for the estimator")
694
700
  p_sy.add_argument("--lat", type=float, default=None)
@@ -823,9 +829,9 @@ def main(argv=None) -> int:
823
829
  elif a.cmd == "survey":
824
830
  import json as _json
825
831
  from .survey_cmd import run_survey
826
- if not (a.file or a.demo):
827
- raise SystemExit("survey needs --file <LAS or DLIS> or --demo")
828
- txt, machine = run_survey(path=a.file, demo=a.demo, family=a.family, lat=a.lat, elev=a.elev, frame=a.frame)
832
+ if not (a.file or a.demo or a.catalog):
833
+ raise SystemExit("survey needs --file <LAS or DLIS>, --catalog <entry> or --demo")
834
+ txt, machine = run_survey(path=a.file, demo=a.demo, family=a.family, lat=a.lat, elev=a.elev, frame=a.frame, catalog=a.catalog)
829
835
  print(txt)
830
836
  if a.out:
831
837
  os.makedirs(a.out, exist_ok=True)
@@ -2298,6 +2304,58 @@ def main(argv=None) -> int:
2298
2304
  stop.set()
2299
2305
  print("etp-sim: stopped")
2300
2306
  return 0
2307
+ elif a.cmd == "catalog":
2308
+ import json as _json
2309
+ from . import catalog_register as _CR
2310
+ if a.friction:
2311
+ from . import friction_priors as _FP
2312
+ print(_json.dumps({"measured": _FP.measured(), "envelope": _FP.envelope()}, indent=1, default=str) if a.json else _FP.text()); return 0
2313
+ if a.core:
2314
+ from .rock_inventory import core_check
2315
+ c = core_check()
2316
+ print(_json.dumps(c, indent=1) if a.json else (f"core check ({c.get('entry')}): {c.get('how')}\n grain density {c['grain_density']['min']}-{c['grain_density']['max']} g/cc, porosity "
2317
+ f"{c['porosity_frac']['min']:.3f}-{c['porosity_frac']['max']:.3f}, bulk {c['bulk_density']['min']}-{c['bulk_density']['max']} g/cc; {c['outside']} plug(s) outside the range\n source: {c['source']} [{c['license']}]" if c.get('status') == 'OK' else str(c)))
2318
+ return 0
2319
+ if a.check:
2320
+ rows = _CR.check_all()
2321
+ bad = [r for r in rows if not r["ok"]]
2322
+ for r in rows:
2323
+ print(f" {'ok ' if r['ok'] else 'BAD'} {r['entry']:<40s} {r['shape']}")
2324
+ print(f"catalog: {len(rows) - len(bad)} of {len(rows)} entries read through their own readers" + (f"; {len(bad)} did not" if bad else ""))
2325
+ return 0 if not bad else 1
2326
+ if a.entry:
2327
+ from .profile_catalog import CATALOG as _CAT
2328
+ e = _CAT.get(a.entry)
2329
+ if e is None:
2330
+ raise SystemExit(f"catalog: no entry {a.entry!r} (gea catalog --list)")
2331
+ if a.stream_csv:
2332
+ st = e.stream()
2333
+ import csv as _csv
2334
+ with open(a.stream_csv, "w", newline="", encoding="utf-8") as f:
2335
+ wr = _csv.writer(f)
2336
+ wr.writerow([st.index_kind] + list(st.channels)); wr.writerow([""] + [st.channels[c].unit for c in st.channels])
2337
+ for i in range(len(st.index)):
2338
+ wr.writerow([float(st.index[i])] + ["" if st.channels[c].values[i] != st.channels[c].values[i] else float(st.channels[c].values[i]) for c in st.channels])
2339
+ print(f"{a.entry}: {len(st.index)} rows x {len(st.channels)} channels -> {a.stream_csv}")
2340
+ reg = next(r for r in _CR.register() if r["entry"] == a.entry)
2341
+ if a.json:
2342
+ print(_json.dumps({"register": reg, "provenance": e.provenance}, indent=1, default=str))
2343
+ else:
2344
+ print(f"{a.entry}: {reg['kind']} ({reg['tier']}), {reg['file']} {reg['bytes']:,} bytes, {reg['status']}")
2345
+ for u in reg["used_by"]:
2346
+ print(" used by:", u)
2347
+ for k in ("well", "source_database", "source_url", "license", "fetch_date", "coverage", "purpose"):
2348
+ if e.provenance.get(k):
2349
+ print(f" {k}: {str(e.provenance[k])[:300]}")
2350
+ print(" reads as:", _CR.check_entry(e)["shape"])
2351
+ return 0
2352
+ rows = _CR.register()
2353
+ if a.json:
2354
+ print(_json.dumps({"entries": rows, "audit": _CR.audit()}, indent=1, default=str)); return 0
2355
+ print(_CR.text(rows, unused_only=a.unused))
2356
+ if a.unused:
2357
+ print(f"\n {_CR.NO_BAND_REASON}")
2358
+ return 0
2301
2359
  elif a.cmd == "dlis":
2302
2360
  import json as _json
2303
2361
  from .dlis import DlisError, DlisFile, read as _read_dlis
@@ -6966,6 +6966,112 @@ def section_br_logs_historian(tmp: str) -> None:
6966
6966
  + (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
6967
6967
 
6968
6968
 
6969
+ def section_bs_catalog(tmp: str) -> None:
6970
+ """Section BS - the catalogue accounted for: every entry reads; the register against the code both ways; the
6971
+ measured friction envelope with provenance; the core check in the model card; every LAS entry through the
6972
+ survey with an estimate or a named refusal; the CLI; the help."""
6973
+ import subprocess as _sp
6974
+ from . import catalog_register as CR
6975
+ from . import friction_priors as FP
6976
+ from . import helplib as H
6977
+ from .profile_catalog import CATALOG
6978
+ from .rock_inventory import core_check
6979
+ from .survey_cmd import run_survey
6980
+ pkg = Path(__file__).parent
6981
+ d = Path(tmp, "bs"); d.mkdir()
6982
+
6983
+ checks = CR.check_all()
6984
+ bad = [c for c in checks if not c["ok"]]
6985
+ aud = CR.audit()
6986
+ reg = CR.register()
6987
+ used = [r for r in reg if r["status"] == "USED"]
6988
+ carried = [r for r in reg if r["status"] != "USED"]
6989
+ c1 = {
6990
+ "every_entry_reads": not bad and len(checks) == len(CR.public()) >= 50 and len(reg) == len(CR.public()) and aud["n_operator"] == len(CATALOG) - len(CR.public()),
6991
+ "register_matches_code": aud["unregistered"] == [] and aud["unnamed"] == [] and aud["n_used"] == len(used) and aud["n_total"] == len(reg),
6992
+ "carried_stated": all(r["why"].startswith("a science-hole dataset") and not r["used_by"] for r in carried) and all(r["used_by"] for r in used),
6993
+ "sidecars": all(r["source"] and r["license"] and r["kind"] for r in reg),
6994
+ }
6995
+ failed1 = [k for k, v in c1.items() if not v]
6996
+ ok(not failed1,
6997
+ f"BS1 the catalogue accounted for: {len(checks)} public entries each read through its own reader (an operator tier, when present on a machine, is counted and never listed); the register against the code both ways (an entry a "
6998
+ "module names is registered as used, an entry registered as used is named or is a LAS the survey takes); every carried entry says so with the "
6999
+ "reason and no use; every entry carries its source, licence and kind"
7000
+ + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
7001
+
7002
+ meas = FP.measured(); env = FP.envelope()
7003
+ by = {m["entry"]: m for m in meas}
7004
+ cc = core_check()
7005
+ cc2 = core_check(brine_gcc=1.0)
7006
+ from .model_card import build_cards
7007
+ cards = build_cards()
7008
+ inv_card = next(c for c in cards if c.model_id == "rock_density_inventory")
7009
+ ev = [e for e in inv_card.evaluation if e["metric"] == "sandstone range against a real core"]
7010
+ c2 = {
7011
+ "friction_read": len(meas) == 7 and by["costa_rica_odp_friction_envelope"]["mu"]["n"] == 31 and by["costa_rica_odp_friction_envelope"]["mu"]["min"] == 0.21
7012
+ and by["costa_rica_odp_friction_envelope"]["mu"]["max"] == 0.88 and by["hikurangi_u1520_friction_insitu"]["mu_peak"]["n"] == 12
7013
+ and by["hikurangi_u1520_friction_insitu"]["a_minus_b"]["min"] < 0 and by["nankai_megasplay_shear_strength"]["mu_how"].startswith("shear strength / effective")
7014
+ and by["sumatra_362_cohesion"]["strength"]["unit"] == "kPa" and by["sumatra_362_cohesion"]["strength"]["max"] == 990.0
7015
+ and by["ktb_vb_rockmech_compress"]["strength"]["n"] == 113 and by["jfast_c0019_slow_slip_events"]["strength"]["n"] == 5
7016
+ and by["barbados_110_consolidation"]["strength"]["what"] == "vane shear strength",
7017
+ "envelope": env["n_entries"] == 3 and env["n_samples"] == 70 and env["min"] == 0.21 and env["max"] == 0.9 and env["byerlee"] == 0.6
7018
+ and "none from the Permian Basin" in env["statement"] and all(m["source"] and m["license"] and m["url"] for m in meas),
7019
+ "core_check": cc["status"] == "OK" and cc["n_plugs"] == 70 and cc["inside"] == 65 and cc["outside"] == 5 and cc["sandstone_range"] == [2.05, 2.55]
7020
+ and cc["bulk_density"]["min"] == 2.054 and "grain x (1 - phi) + 1.03 x phi" in cc["how"] and cc2["inside"] != cc["inside"] or (cc2["brine_gcc"] == 1.0 and cc2["inside"] <= 70),
7021
+ "in_model_card": len(ev) == 1 and "65 of 70 Volve 15/9-19 A core plugs inside 2.05-2.55" in ev[0]["value"] and "Equinor Volve" in ev[0]["method"],
7022
+ }
7023
+ failed2 = [k for k, v in c2.items() if not v]
7024
+ ok(not failed2,
7025
+ "BS2 the measured friction and strength read from seven catalogue entries with their sources and licences (Costa Rica 31 coefficients 0.21-0.88, Hikurangi "
7026
+ "peak and steady-state with a-b, Nankai as shear strength over effective stress, Sumatra cohesion, Barbados vane shear, JFAST peak strength, KTB "
7027
+ "compressive strength); the envelope 0.21-0.90 on 70 measurements from three datasets against Byerlee's 0.6, none from the Permian; the core check "
7028
+ "(70 Volve plugs, bulk from grain density and porosity with the brine stated, 65 inside the published sandstone range) in the rock inventory model card"
7029
+ + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
7030
+
7031
+ outcomes = {}
7032
+ for name in ("scorpio_e1_sa_excerpt", "university_6_17_no1_tx_excerpt", "kennetcook_2_p129_excerpt", "collingwood_1_28_ks_complete", "l07_01_nl_excerpt", "volve_15_9_19_sr_excerpt"):
7033
+ txt, m = run_survey(catalog=name)
7034
+ outcomes[name] = ("ESTIMATED" if "Vp (compressional velocity) estimate" in txt and "NOT ESTIMATED" not in txt else "NOT ESTIMATED", txt)
7035
+ not_las = None
7036
+ try:
7037
+ run_survey(catalog="volve_15_9_19a_core_excerpt")
7038
+ except SystemExit as e:
7039
+ not_las = str(e)
7040
+ no_entry = None
7041
+ try:
7042
+ run_survey(catalog="nope")
7043
+ except SystemExit as e:
7044
+ no_entry = str(e)
7045
+ r_list = _sp.run([sys.executable, "-m", "gea", "catalog", "--list"], capture_output=True, text=True)
7046
+ r_unused = _sp.run([sys.executable, "-m", "gea", "catalog", "--unused"], capture_output=True, text=True)
7047
+ r_check = _sp.run([sys.executable, "-m", "gea", "catalog", "--check"], capture_output=True, text=True)
7048
+ r_fr = _sp.run([sys.executable, "-m", "gea", "catalog", "--friction"], capture_output=True, text=True)
7049
+ r_core = _sp.run([sys.executable, "-m", "gea", "catalog", "--core"], capture_output=True, text=True)
7050
+ r_ent = _sp.run([sys.executable, "-m", "gea", "catalog", "--entry", "scorpio_e1_sa_excerpt", "--info", "--stream-csv", str(d / "scorpio.csv")], capture_output=True, text=True)
7051
+ r_sv = _sp.run([sys.executable, "-m", "gea", "survey", "--catalog", "l07_01_nl_excerpt"], capture_output=True, text=True)
7052
+ help_md = (pkg / "help" / "catalog.md").read_text(encoding="utf-8")
7053
+ c3 = {
7054
+ "surveys": outcomes["l07_01_nl_excerpt"][0] == "ESTIMATED" and "density 2.64 - 2.74 g/cc" in outcomes["l07_01_nl_excerpt"][1]
7055
+ and outcomes["scorpio_e1_sa_excerpt"][0] == "NOT ESTIMATED" and "no density (RHOB) and no gravity" in outcomes["scorpio_e1_sa_excerpt"][1]
7056
+ and outcomes["university_6_17_no1_tx_excerpt"][0] == "NOT ESTIMATED" and "fewer than 5 usable stations" in outcomes["university_6_17_no1_tx_excerpt"][1]
7057
+ and outcomes["collingwood_1_28_ks_complete"][0] == "NOT ESTIMATED" and outcomes["kennetcook_2_p129_excerpt"][0] == "NOT ESTIMATED"
7058
+ and outcomes["volve_15_9_19_sr_excerpt"][0] == "NOT ESTIMATED" and all("catalogue entry " in o[1] for o in outcomes.values()),
7059
+ "refusals": not_las and "not a LAS log" in not_las and no_entry and "no catalogue entry" in no_entry,
7060
+ "cli": r_list.returncode == 0 and f"catalogue: {len(reg)} entries, {len(used)} used, {len(carried)} carried with no band" in r_list.stdout
7061
+ and r_unused.returncode == 0 and "CARRIED, NO BAND" in r_unused.stdout and "USED" not in r_unused.stdout.split("\n", 1)[1].replace("UNUSED", "")
7062
+ and r_check.returncode == 0 and f"{len(reg)} of {len(reg)} entries read" in r_check.stdout
7063
+ and r_fr.returncode == 0 and "run from 0.21 to 0.9" in r_fr.stdout and r_core.returncode == 0 and "contains 65 of 70 plugs" in r_core.stdout
7064
+ and r_ent.returncode == 0 and "used by: gea survey --catalog" in r_ent.stdout and os.path.isfile(d / "scorpio.csv") and r_sv.returncode == 0 and "density -> RHOB" in r_sv.stdout,
7065
+ "help": any(t["topic"] == "catalog" for t in H.topics()) and not H.check("catalog") and "it does not give the fault's own" in help_md.split("will not call a measurement")[1],
7066
+ }
7067
+ failed3 = [k for k, v in c3.items() if not v]
7068
+ ok(not failed3,
7069
+ "BS3 every LAS entry through the strata survey with its catalogue provenance: L07-01 estimated (density 2.64-2.74 g/cc), Scorpio E1 NOT ESTIMATED "
7070
+ "(no density), University 6-17, Kennetcook, Collingwood and 15/9-19 SR NOT ESTIMATED on too little support, each with the reason; a core entry and "
7071
+ "an unknown name refused; `gea catalog --list --unused --check --friction --core --entry`; `gea survey --catalog`; the help"
7072
+ + (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
7073
+
7074
+
6969
7075
  def main() -> int:
6970
7076
  print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
6971
7077
  # a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
@@ -7039,6 +7145,7 @@ def main() -> int:
7039
7145
  section_bp_interval(tmp)
7040
7146
  section_bq_field_ports(tmp)
7041
7147
  section_br_logs_historian(tmp)
7148
+ section_bs_catalog(tmp)
7042
7149
  if _FAILS:
7043
7150
  print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
7044
7151
  for f in _FAILS:
@@ -0,0 +1,146 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ """catalog_register - what every shipped catalogue entry is for, and what reads it.
5
+
6
+ The catalogue ships 58 public entries with provenance sidecars. A sidecar says where an entry came from; it does
7
+ not say what in this program reads it. This register does: for each entry, the bands, commands and reports that
8
+ take it (USED BY), or the plain statement that nothing does yet (CARRIED, NO BAND). The gate holds the register
9
+ to the code - an entry a module names by its stem must be registered as used, an entry registered as used must
10
+ be named somewhere - and reads every entry through its own reader so a carried file is at least a readable one.
11
+
12
+ The measured-friction entries feed `friction_priors` (the envelope a slip-tendency statement discloses its
13
+ coefficient against); the Volve core feeds `rock_inventory.core_check` (the published sandstone range checked
14
+ against core-derived bulk density); every LAS entry runs through `gea survey --catalog`; the rest are stated.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import os
19
+ import re
20
+ from pathlib import Path
21
+ from typing import Dict, List
22
+
23
+ from .profile_catalog import CATALOG, CatalogEntry
24
+
25
+ # entry -> the places in this program that read it, in the user's terms
26
+ USES: Dict[str, List[str]] = {
27
+ 'volve_f12_f14_production_excerpt': ['gea quickstart (the Volve catalogue well)', 'gea dashboard --catalog-well', 'the drift report, well tests, alarms and SLA on the sample reports',
28
+ 'the Volve well-test validation samples'],
29
+ 'ktb_hb_complog_6020_excerpt': ['gea survey --demo (the bundled strata survey)', 'the KTB lithology validation and the rock inventory model card', 'the accuracy statement, blind harness, inverse engine'],
30
+ 'ktb_hb_bhgm_density': ['the ktb_hb assembly (gea wells): density'],
31
+ 'ktb_hb_hlog246_temperature': ['the ktb_hb assembly (gea wells): temperature'],
32
+ 'ktb_hb_tvd_0_9080_excerpt': ['the ktb_hb assembly (gea wells): the trajectory (CatalogEntry.survey)'],
33
+ 'ktb_hb_rockmech_compress': ['the ktb_hb assembly (gea wells): the strength attachment (strata_join)'],
34
+ 'dsdp_504b_physical_properties': ['the odp_504b assembly (gea wells): density'],
35
+ 'dsdp_504b_sound_velocity': ['the odp_504b assembly (gea wells): the measured Vp'],
36
+ 'odp_504b_dike_elastic_moduli': ['the odp_504b assembly (gea wells): the elastics attachment'],
37
+ 'odp_504b_leg137_borehole_fluids': ['the odp_504b assembly (gea wells): the fluids attachment'],
38
+ 'odp_1027c_cork_temperature': ['the site_1027 assembly (gea wells): the CORK temperature record'],
39
+ 'odp_1027b_thermal_conductivity': ['the site_1027 assembly (gea wells): the thermal-conductivity attachment'],
40
+ 'iodp_u1324_pore_pressure': ['the u1324 assembly (gea wells): pore pressure and overburden'],
41
+ 'gom_308_t2p_insitu': ['the u1324 assembly (gea wells): in-situ temperature'],
42
+ 'volve_15_9_19_sr_excerpt': ['gea gamma (lithology from GR)', 'the las2 port end-to-end (profile_catalog)', 'gea survey --catalog'],
43
+ 'ktb_vb_vlog251_temperature': ['gea gamma (lithology from GR)'],
44
+ 'l07_01_nl_excerpt': ['gea gamma (lithology from GR)', 'gea survey --catalog'],
45
+ # v0.25.0: the entries that now have a use
46
+ 'kennetcook_2_p129_excerpt': ['gea survey --catalog (a real Nova Scotia log through the strata survey)'],
47
+ 'collingwood_1_28_ks_complete': ['gea survey --catalog (a real Kansas log through the strata survey)'],
48
+ 'scorpio_e1_sa_excerpt': ['gea survey --catalog (a real South Australian log through the strata survey)'],
49
+ 'university_6_17_no1_tx_excerpt': ['gea survey --catalog (a real Texas log through the strata survey)'],
50
+ 'volve_15_9_19a_core_excerpt': ['rock_inventory.core_check: the published sandstone density range against core-derived bulk density (model card evaluation)'],
51
+ 'costa_rica_odp_friction_envelope': ['friction_priors: measured friction coefficient envelope (slip tendency discloses its coefficient against it)'],
52
+ 'hikurangi_u1520_friction_insitu': ['friction_priors: peak and steady-state friction per lithology, a-b'],
53
+ 'jfast_c0019_slow_slip_events': ['friction_priors: the Tohoku fault-zone friction at slow-slip rates'],
54
+ 'nankai_megasplay_shear_strength': ['friction_priors: shear strength over effective stress'],
55
+ 'sumatra_362_cohesion': ['friction_priors: cohesion of intact and powdered samples'],
56
+ 'ktb_vb_rockmech_compress': ['friction_priors: compressive strength of crystalline basement cores (the strength end of the envelope)'],
57
+ 'barbados_110_consolidation': ['friction_priors: vane shear strength over effective overburden of accretionary sediments'],
58
+ }
59
+ NO_BAND_REASON = ('a science-hole dataset gathered for the simulator\'s priors; no band of a gauge-monitoring and disposal-well program reads it. '
60
+ 'Carried with its provenance; dropping it from the wheel is the owner\'s call (gea catalog --unused).')
61
+
62
+
63
+ def _source_text() -> str:
64
+ """Every module of the package except this register and the gate, as one string."""
65
+ pkg = Path(__file__).parent
66
+ parts = []
67
+ for p in sorted(pkg.glob('*.py')):
68
+ if p.name in ('catalog_register.py', 'acceptance_tests.py'):
69
+ continue
70
+ parts.append(p.read_text(encoding='utf-8', errors='replace'))
71
+ for p in sorted((pkg.parent / 'tools').glob('*.py')) if (pkg.parent / 'tools').is_dir() else []:
72
+ parts.append(p.read_text(encoding='utf-8', errors='replace'))
73
+ return '\n'.join(parts)
74
+
75
+
76
+ def public() -> Dict[str, CatalogEntry]:
77
+ """The shipped tier only. Operator-tier entries (a private folder on one machine, never in the wheel) are not registered,
78
+ listed, audited or named by this module: their presence is counted and nothing more."""
79
+ return {n: e for n, e in CATALOG.items() if e.provenance.get('tier', 'public') == 'public'}
80
+
81
+
82
+ def n_operator() -> int:
83
+ return sum(1 for e in CATALOG.values() if e.provenance.get('tier', 'public') != 'public')
84
+
85
+
86
+ def referenced_in_code() -> Dict[str, int]:
87
+ """Public entry stems named in the package source (outside this register and the gate)."""
88
+ src = _source_text()
89
+ return {name: len(re.findall(re.escape(name), src)) for name in public() if re.search(re.escape(name), src)}
90
+
91
+
92
+ def register() -> List[dict]:
93
+ rows = []
94
+ for name, e in sorted(public().items()):
95
+ prov = e.provenance
96
+ uses = USES.get(name, [])
97
+ rows.append({'entry': name, 'kind': prov.get('kind', ''), 'tier': prov.get('tier', 'public'), 'file': e.las_path.name,
98
+ 'bytes': os.path.getsize(e.las_path), 'source': str(prov.get('source_database', ''))[:80], 'license': str(prov.get('license', ''))[:40],
99
+ 'used_by': uses, 'status': 'USED' if uses else 'CARRIED, NO BAND', 'why': '' if uses else NO_BAND_REASON})
100
+ return rows
101
+
102
+
103
+ def check_entry(e: CatalogEntry) -> dict:
104
+ """Read one entry through its own reader; the shape or the error."""
105
+ try:
106
+ if e.las_path.suffix.lower() == '.csv':
107
+ from .profile_catalog import _csv_kind
108
+ if _csv_kind(e.las_path) == 'survey':
109
+ sv = e.survey()
110
+ return {'entry': e.name, 'ok': True, 'shape': f'deviation survey, {len(sv.md_ft)} stations'}
111
+ st = e.stream()
112
+ return {'entry': e.name, 'ok': True, 'shape': f'{st.index_kind}, {len(st.index)} rows, {len(st.channels)} channels'}
113
+ except Exception as ex: # noqa: BLE001 - the point is to name it
114
+ return {'entry': e.name, 'ok': False, 'shape': f'{type(ex).__name__}: {ex}'}
115
+
116
+
117
+ def check_all() -> List[dict]:
118
+ return [check_entry(e) for _, e in sorted(public().items())]
119
+
120
+
121
+ def audit() -> dict:
122
+ """The register against the code: registered-as-used but never named; named in code but not registered."""
123
+ ref = referenced_in_code()
124
+ used = {n for n, u in USES.items() if u}
125
+ # an entry whose only use is this leg's own modules is named in those modules; check that too
126
+ unregistered = sorted(n for n in ref if n not in used)
127
+ # a LAS entry is reachable by `gea survey --catalog <entry>` without any module naming it
128
+ unnamed = sorted(n for n in used if n not in ref and CATALOG[n].las_path.suffix.lower() != '.las')
129
+ pub = public()
130
+ return {'referenced': ref, 'unregistered': unregistered, 'unnamed': unnamed, 'n_used': len(used), 'n_carried': len(pub) - len(used), 'n_total': len(pub),
131
+ 'n_operator': n_operator()}
132
+
133
+
134
+ def text(rows: List[dict], unused_only: bool = False) -> str:
135
+ out = []
136
+ n_used = sum(1 for r in rows if r['status'] == 'USED')
137
+ out.append(f"catalogue: {len(rows)} entries, {n_used} used, {len(rows) - n_used} carried with no band"
138
+ + (f"; operator tier: {n_operator()} entries present on this machine (private; not listed here)" if n_operator() else ''))
139
+ w = max(len(r['entry']) for r in rows)
140
+ for r in rows:
141
+ if unused_only and r['status'] == 'USED':
142
+ continue
143
+ out.append(f" {r['entry']:{w}s} {r['status']:<17s} {r['kind']}")
144
+ for u in r['used_by']:
145
+ out.append(f" {'':{w}s} - {u}")
146
+ return '\n'.join(out)
@@ -0,0 +1,133 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ """friction_priors - the measured friction and strength the catalogue holds, as the envelope a slip statement discloses.
5
+
6
+ A slip-tendency number needs a friction coefficient, and the one everyone uses (0.6, Byerlee) is a law from
7
+ crystalline rock at crustal stress - not a measurement on the fault in question. This module reads the
8
+ laboratory measurements the catalogue carries on natural fault and sediment samples - ODP Costa Rica friction
9
+ ladders (0.21-0.88 across 15-90 MPa and 19-212 C), IODP Hikurangi peak and steady-state friction per
10
+ lithology, the Tohoku (JFAST) fault-zone material at slow-slip rates, Nankai shear strength over effective
11
+ stress, Sumatra cohesion, Barbados vane shear over overburden, and the KTB pilot hole's compressive strength
12
+ of crystalline cores - and states them as what they are: the range of measured coefficients on real samples,
13
+ each with its provenance, none of them the Permian's. A slip-tendency statement built on 0.6 prints this
14
+ envelope beside it so the reader sees how far a measured coefficient can sit from the law.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ from typing import Dict, List, Optional
19
+
20
+ import numpy as np
21
+
22
+ from .profile_catalog import CATALOG
23
+
24
+ ENTRIES = ('costa_rica_odp_friction_envelope', 'hikurangi_u1520_friction_insitu', 'jfast_c0019_slow_slip_events', 'nankai_megasplay_shear_strength',
25
+ 'sumatra_362_cohesion', 'barbados_110_consolidation', 'ktb_vb_rockmech_compress')
26
+ BYERLEE = 0.6
27
+
28
+
29
+ def _vals(st, name: str) -> np.ndarray:
30
+ c = st.channels.get(name)
31
+ if c is None:
32
+ return np.array([])
33
+ v = np.asarray(c.values, dtype=float)
34
+ return v[~np.isnan(v)]
35
+
36
+
37
+ def _stat(v: np.ndarray) -> Optional[dict]:
38
+ if v.size == 0:
39
+ return None
40
+ return {'n': int(v.size), 'min': round(float(v.min()), 4), 'median': round(float(np.median(v)), 4), 'max': round(float(v.max()), 4)}
41
+
42
+
43
+ def measured() -> List[dict]:
44
+ """Per entry: the friction coefficient (or the strength the entry measures), the conditions, the provenance."""
45
+ out: List[dict] = []
46
+ for name in ENTRIES:
47
+ e = CATALOG.get(name)
48
+ if e is None:
49
+ continue
50
+ st = e.stream()
51
+ prov = e.provenance
52
+ row = {'entry': name, 'kind': prov.get('kind', ''), 'source': str(prov.get('source_database', ''))[:90], 'url': str(prov.get('source_url', '')),
53
+ 'license': str(prov.get('license', ''))[:60], 'material': '', 'mu': None, 'strength': None, 'conditions': ''}
54
+ if name == 'costa_rica_odp_friction_envelope':
55
+ row['material'] = 'ODP 170/205 Costa Rica margin sediments (Ikari et al. 2013/2014)'
56
+ row['mu'] = _stat(_vals(st, 'Coeff (of friction)'))
57
+ p, t = _vals(st, 'P (effective normal stress)'), _vals(st, 'T:temp')
58
+ row['conditions'] = f'effective normal stress {p.min():g}-{p.max():g} MPa, {t.min():g}-{t.max():g} C'
59
+ elif name == 'hikurangi_u1520_friction_insitu':
60
+ row['material'] = 'IODP U1520 Hikurangi input sediments, six lithologies (Eijsink & Ikari 2022)'
61
+ pk, ss = _vals(st, 'µ (peak)'), _vals(st, 'µ (steady-state)')
62
+ row['mu'] = _stat(np.concatenate([pk, ss]))
63
+ row['mu_peak'] = _stat(pk); row['mu_steady'] = _stat(ss)
64
+ ab = _vals(st, 'a-b')
65
+ row['a_minus_b'] = _stat(ab)
66
+ sn = _vals(st, 'SigmaN (eff)')
67
+ row['conditions'] = f'in-situ effective normal stress {sn.min() / 1000:g}-{sn.max() / 1000:g} MPa; a-b {ab.min():+.4f} to {ab.max():+.4f} (velocity weakening where negative)'
68
+ elif name == 'jfast_c0019_slow_slip_events':
69
+ row['material'] = 'IODP 343 JFAST Tohoku plate-boundary fault zone (Ikari et al. 2015)'
70
+ tau = _vals(st, 'Shear str max'); mu_inc = _vals(st, 'µ (increase)')
71
+ row['strength'] = {'what': 'peak shear strength during slow slip events', 'unit': 'kPa', **(_stat(tau) or {})}
72
+ row['mu_change_during_sse'] = _stat(mu_inc)
73
+ row['conditions'] = 'plate-rate shearing; five of seven experiments produced slow slip events'
74
+ elif name == 'nankai_megasplay_shear_strength':
75
+ row['material'] = 'IODP 315/316 Nankai megasplay slope sediments (Ikari et al. 2011)'
76
+ tau, sv = _vals(st, 'Tau'), _vals(st, 'SigmaV ef')
77
+ n = min(tau.size, sv.size)
78
+ mu = tau[:n] / np.where(sv[:n] > 0, sv[:n], np.nan)
79
+ row['mu'] = _stat(mu[~np.isnan(mu)])
80
+ row['mu_how'] = 'shear strength / effective vertical stress, per sample'
81
+ row['conditions'] = f'effective vertical stress {sv.min():g}-{sv.max():g} kPa'
82
+ elif name == 'sumatra_362_cohesion':
83
+ row['material'] = 'IODP 362 Sumatra input sediments (Stanislowski & Ikari 2025)'
84
+ c = _vals(st, 'C'); cc = _vals(st, 'C coef')
85
+ row['strength'] = {'what': 'cohesion', 'unit': 'kPa', **(_stat(c) or {})}
86
+ row['cohesion_coefficient'] = _stat(cc)
87
+ row['conditions'] = 'effective stresses 10.7-14.0 MPa; intact and powdered samples'
88
+ elif name == 'barbados_110_consolidation':
89
+ row['material'] = 'ODP 110 Barbados accretionary prism sediments (Taylor & Leonard 1990)'
90
+ vane = _vals(st, 'Shear str (vane)')
91
+ ob = next((_vals(st, k) for k in st.channels if k.startswith('Overb press')), np.array([0.0]))
92
+ row['strength'] = {'what': 'vane shear strength', 'unit': 'kPa', **(_stat(vane) or {})}
93
+ row['conditions'] = f'effective overburden {ob.min():g}-{ob.max():g} kPa'
94
+ elif name == 'ktb_vb_rockmech_compress':
95
+ row['material'] = 'KTB pilot hole crystalline cores, 190-3,832 m (gneisses, amphibolites)'
96
+ cs = _vals(st, 'COMPRESSIVE_STRENGTH'); em = _vals(st, 'E_MODUL')
97
+ row['strength'] = {'what': 'uniaxial compressive strength', 'unit': 'MPa', **(_stat(cs) or {})}
98
+ row['youngs_modulus_GPa'] = _stat(em)
99
+ row['conditions'] = 'laboratory, cores by depth; foliated rocks anisotropic'
100
+ out.append(row)
101
+ return out
102
+
103
+
104
+ def envelope() -> dict:
105
+ """The union of the measured friction coefficients, against Byerlee's 0.6."""
106
+ rows = measured()
107
+ mus = [r['mu'] for r in rows if r.get('mu')]
108
+ if not mus:
109
+ return {'n_entries': 0}
110
+ lo = min(m['min'] for m in mus); hi = max(m['max'] for m in mus)
111
+ return {'n_entries': len(mus), 'n_samples': sum(m['n'] for m in mus), 'min': lo, 'max': hi, 'byerlee': BYERLEE,
112
+ 'entries': [r['entry'] for r in rows if r.get('mu')],
113
+ 'statement': (f"measured friction coefficients on natural samples in this program's catalogue run from {lo:g} to {hi:g} "
114
+ f"({sum(m['n'] for m in mus)} measurements, {len(mus)} datasets; none from the Permian Basin); Byerlee's law gives {BYERLEE:g}. "
115
+ f"A slip-tendency statement that assumes {BYERLEE:g} is one point in that range, and the reader should know it.")}
116
+
117
+
118
+ def text() -> str:
119
+ out = ['Measured friction and strength in the catalogue (each with its provenance; none from the site):']
120
+ for r in measured():
121
+ out.append(f" {r['entry']}: {r['material']}")
122
+ if r.get('mu'):
123
+ m = r['mu']; out.append(f" friction coefficient {m['min']:g}-{m['max']:g} (median {m['median']:g}, n={m['n']})" + (f"; {r['mu_how']}" if r.get('mu_how') else ''))
124
+ if r.get('strength'):
125
+ sg = r['strength']; out.append(f" {sg['what']} {sg.get('min', '?'):g}-{sg.get('max', '?'):g} {sg['unit']} (n={sg.get('n', 0)})")
126
+ if r.get('a_minus_b'):
127
+ ab = r['a_minus_b']; out.append(f" a-b {ab['min']:+.4f} to {ab['max']:+.4f} (n={ab['n']})")
128
+ out.append(f" conditions: {r['conditions']}")
129
+ out.append(f" source: {r['source']} [{r['license']}]")
130
+ env = envelope()
131
+ out.append('')
132
+ out.append(env.get('statement', 'no friction coefficients found'))
133
+ return '\n'.join(out)
@@ -0,0 +1,11 @@
1
+ # The catalogue
2
+
3
+ > The program ships 52 public datasets, each with a provenance sidecar saying where it came from, under what licence, and what it covers. A sidecar does not say what in this program reads the entry; the register does. `gea catalog --list` prints every entry with the bands, commands and reports that take it, or the plain statement that nothing does yet - CARRIED, NO BAND - and the gate holds that register to the code. The entries with a use since this page was written: every LAS log runs through the strata survey; seven measured-friction and strength datasets become the envelope a slip statement discloses its coefficient against; the Volve core checks the published sandstone range.
4
+
5
+ **The command**: `gea catalog --list` (the register), `--unused` (the carried entries, with the reason), `--check` (every entry read through its own reader, the shape or the error), `--entry <name> --info` (the provenance in full and how it reads), `--entry <name> --stream-csv out.csv` (the entry as a stream file any other command ingests), `--friction` (the measured friction and strength, each with its source, and the envelope against Byerlee's 0.6), `--core` (the Volve 15/9-19 A core plugs against the published sandstone range). `gea survey --catalog <entry>` runs the strata survey on any LAS entry - Scorpio E1 (South Australia), University 6-17 (Texas), Kennetcook #2 (Nova Scotia), Collingwood 1-28 (Kansas), L07-01 (Dutch North Sea), 15/9-19 SR (Volve) - and says what it found or why it did not estimate.
6
+
7
+ **What it writes**: the register - entry, kind, tier, file size, USED or CARRIED, and each use in the user's terms; the check - 52 of 52 entries read; the friction envelope - friction coefficients 0.21 to 0.90 on 70 measurements from three datasets (ODP Costa Rica, IODP Hikurangi, IODP Nankai), cohesion 188-990 kPa (Sumatra), vane shear 19.5-290 kPa (Barbados), fault-zone peak shear strength 1.7-1.9 MPa at slow slip (JFAST), uniaxial compressive strength 3-265 MPa on crystalline cores (KTB pilot hole) - none from the Permian, and the page says so; the core check - bulk density per plug as grain density x (1 - porosity) + brine x porosity, the brine stated, 65 of 70 Volve plugs inside the published 2.05-2.55 g/cc sandstone range, written into the rock inventory model card's evaluation.
8
+
9
+ **The number to check**: `--check` must read every entry; `--list` must show no entry registered as used that no module names (the gate checks both ways); the core check's count against the model card's evaluation line.
10
+
11
+ **What this page will not call a measurement**: a friction coefficient for the site - the envelope is what was measured on other rocks elsewhere, with each source named; it bounds how far a law can sit from a measurement, it does not give the fault's own. A use an entry does not have - a carried entry is said to be carried, and whether to drop it from the wheel is the owner's call, not this page's. A survey estimate from too little support - a log excerpt with fewer than five usable stations is NOT ESTIMATED with the reason, as the real excerpts above show. A core bulk density the core did not report - it is derived from grain density and porosity with the brine density stated, and labelled as derived.
@@ -39,6 +39,7 @@ INDEX: List[tuple] = [
39
39
  ('files', 'Files', 'import and export roots, detection by content, the evidence pack'),
40
40
  ('notifications', 'Notifications', 'rules, channels, the delivery log'),
41
41
  ('structure', 'Mapped structure', 'the nearest fault and fold to a well from a structure layer the site brought, by distance and bearing'),
42
+ ('catalog', 'The catalogue', 'every shipped public dataset, what in this program reads it or that nothing does; the measured friction envelope; the core check; any log through the survey'),
42
43
  ('dlis', 'The DLIS log', 'a well log as it is delivered (API RP66 V1), read as the standard lays it out: the frames, the channels, what was skipped; into the strata survey'),
43
44
  ('historian', 'The historian pull', 'an operator\'s gauge history out of the PI System through PI Web API, read-only, every value with its archive time and flags'),
44
45
  ('field-ports', 'The field ports', 'Modbus RTU on the serial line, DNP3 from the pad RTU, HART-IP from the transmitter itself - read-only, polled, with the stand-ins to rehearse against'),
@@ -110,7 +110,7 @@ def build_cards(monitor_log_dir: Optional[str] = None, program_version: str = ''
110
110
  from .accuracy_statement import library_backtest, MIN_TRIALS, N_BOOT, SEED
111
111
  from .sample_record import DEFAULT_TAG_CLASSES
112
112
  from .well_test_validation import DEFAULT_CRITERIA
113
- from .rock_inventory import rock_inventory
113
+ from .rock_inventory import core_check, rock_inventory
114
114
  from . import strata_join as SJ
115
115
  from .reconciler import ReconcilerConfig
116
116
  ver = program_version or _v
@@ -203,7 +203,9 @@ def build_cards(monitor_log_dir: Optional[str] = None, program_version: str = ''
203
203
  inputs=[{'name': f"{k} ({v['tier']})", 'unit': f"g/cc, anchor {v['anchor']}, range {v['lo']}-{v['hi']}", 'source': str(v['citation'])[:120]} for k, v in inv.items()],
204
204
  settings=[{'setting': 'anchors', 'value': str(len(inv)), 'basis': 'standard geophysics density tables (Telford et al. 1990; Schoen 2015)'}],
205
205
  calibration_data=[{'dataset': 'published density tables', 'records': len(inv), 'database': 'Telford, Geldart & Sheriff (1990); Schoen (2015)', 'url': '', 'licence': 'published reference values', 'fetch_date': ''}],
206
- evaluation=[{'metric': 'anchor reproduction', 'value': f"worst anchor residual {max(abs(float(v['residual_pct'])) for v in inv.values()):.3f} %", 'method': 'each anchor re-derived at gate time'}],
206
+ evaluation=[{'metric': 'anchor reproduction', 'value': f"worst anchor residual {max(abs(float(v['residual_pct'])) for v in inv.values()):.3f} %", 'method': 'each anchor re-derived at gate time'},
207
+ {'metric': 'sandstone range against a real core', 'value': (lambda c: f"{c['inside']} of {c['n_plugs']} Volve 15/9-19 A core plugs inside {c['sandstone_range'][0]}-{c['sandstone_range'][1]} g/cc (core bulk {c['bulk_density']['min']}-{c['bulk_density']['max']})" if c.get('status') == 'OK' else c.get('status', '?'))(core_check()),
208
+ 'method': 'core grain density x (1 - porosity) + brine x porosity per plug, the catalogue core entry (Equinor Volve, open licence)'}],
207
209
  limitations=['Ranges overlap; the classifier returns ranked candidates, never one confident name.'],
208
210
  components=[{'role': 'inventory and classifier', 'sha256': _sha('rock_inventory.py')}],
209
211
  generated_utc=now))