gea-program 0.6.0__tar.gz → 0.7.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 (218) hide show
  1. {gea_program-0.6.0 → gea_program-0.7.0}/PKG-INFO +75 -7
  2. {gea_program-0.6.0 → gea_program-0.7.0}/README.md +74 -6
  3. {gea_program-0.6.0 → gea_program-0.7.0}/gea/__init__.py +1 -1
  4. {gea_program-0.6.0 → gea_program-0.7.0}/gea/__main__.py +136 -4
  5. {gea_program-0.6.0 → gea_program-0.7.0}/gea/acceptance_tests.py +355 -5
  6. {gea_program-0.6.0 → gea_program-0.7.0}/gea/cli.py +18 -12
  7. {gea_program-0.6.0 → gea_program-0.7.0}/gea/client_reports.py +82 -0
  8. {gea_program-0.6.0 → gea_program-0.7.0}/gea/doctor.py +45 -6
  9. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/TESTER_GUIDE.md +1 -1
  10. gea_program-0.7.0/gea/help/audit-update.md +13 -0
  11. gea_program-0.7.0/gea/help/seismic.md +13 -0
  12. {gea_program-0.6.0 → gea_program-0.7.0}/gea/helplib.py +2 -1
  13. {gea_program-0.6.0 → gea_program-0.7.0}/gea/jobs.py +11 -4
  14. gea_program-0.7.0/gea/permits.py +222 -0
  15. gea_program-0.7.0/gea/seismic_film.py +303 -0
  16. gea_program-0.7.0/gea/seismic_track.py +435 -0
  17. {gea_program-0.6.0 → gea_program-0.7.0}/gea/service.py +121 -6
  18. {gea_program-0.6.0 → gea_program-0.7.0}/gea/web/app.html +225 -5
  19. {gea_program-0.6.0 → gea_program-0.7.0}/gea/workspace.py +257 -4
  20. {gea_program-0.6.0 → gea_program-0.7.0}/gea_program.egg-info/PKG-INFO +75 -7
  21. {gea_program-0.6.0 → gea_program-0.7.0}/gea_program.egg-info/SOURCES.txt +4 -0
  22. {gea_program-0.6.0 → gea_program-0.7.0}/pyproject.toml +1 -1
  23. gea_program-0.6.0/gea/help/seismic.md +0 -13
  24. {gea_program-0.6.0 → gea_program-0.7.0}/LICENSE +0 -0
  25. {gea_program-0.6.0 → gea_program-0.7.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
  26. {gea_program-0.6.0 → gea_program-0.7.0}/gea/accuracy_statement.py +0 -0
  27. {gea_program-0.6.0 → gea_program-0.7.0}/gea/alarm_engine.py +0 -0
  28. {gea_program-0.6.0 → gea_program-0.7.0}/gea/bench.py +0 -0
  29. {gea_program-0.6.0 → gea_program-0.7.0}/gea/blind_harness.py +0 -0
  30. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
  31. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
  32. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
  33. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
  34. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
  35. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
  36. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
  37. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
  38. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
  39. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
  40. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
  41. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
  42. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
  43. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
  44. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
  45. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
  46. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
  47. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
  48. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
  49. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
  50. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
  51. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
  52. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
  53. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
  54. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
  55. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
  56. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
  57. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
  58. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
  59. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
  60. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
  61. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
  62. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
  63. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
  64. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
  65. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
  66. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
  67. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
  68. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
  69. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
  70. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
  71. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
  72. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
  73. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
  74. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
  75. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
  76. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
  77. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
  78. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
  79. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
  80. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
  81. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
  82. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
  83. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
  84. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
  85. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
  86. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
  87. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
  88. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
  89. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
  90. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
  91. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
  92. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
  93. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
  94. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
  95. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
  96. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
  97. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/med_160_sapropels.txt +0 -0
  98. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
  99. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
  100. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
  101. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
  102. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
  103. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
  104. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
  105. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
  106. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
  107. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
  108. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
  109. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
  110. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
  111. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
  112. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
  113. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
  114. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
  115. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
  116. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
  117. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
  118. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
  119. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
  120. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
  121. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
  122. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
  123. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
  124. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
  125. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
  126. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
  127. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
  128. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
  129. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
  130. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
  131. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
  132. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
  133. {gea_program-0.6.0 → gea_program-0.7.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
  134. {gea_program-0.6.0 → gea_program-0.7.0}/gea/certificates.py +0 -0
  135. {gea_program-0.6.0 → gea_program-0.7.0}/gea/config_versioning.py +0 -0
  136. {gea_program-0.6.0 → gea_program-0.7.0}/gea/correlation.py +0 -0
  137. {gea_program-0.6.0 → gea_program-0.7.0}/gea/dashboard.py +0 -0
  138. {gea_program-0.6.0 → gea_program-0.7.0}/gea/deviation.py +0 -0
  139. {gea_program-0.6.0 → gea_program-0.7.0}/gea/downhole_engine.py +0 -0
  140. {gea_program-0.6.0 → gea_program-0.7.0}/gea/drift_monitor.py +0 -0
  141. {gea_program-0.6.0 → gea_program-0.7.0}/gea/earth_model.py +0 -0
  142. {gea_program-0.6.0 → gea_program-0.7.0}/gea/example_register_map.json +0 -0
  143. {gea_program-0.6.0 → gea_program-0.7.0}/gea/fat_sat.py +0 -0
  144. {gea_program-0.6.0 → gea_program-0.7.0}/gea/files.py +0 -0
  145. {gea_program-0.6.0 → gea_program-0.7.0}/gea/follower.py +0 -0
  146. {gea_program-0.6.0 → gea_program-0.7.0}/gea/forward_model.py +0 -0
  147. {gea_program-0.6.0 → gea_program-0.7.0}/gea/gamma.py +0 -0
  148. {gea_program-0.6.0 → gea_program-0.7.0}/gea/gauge_aging.py +0 -0
  149. {gea_program-0.6.0 → gea_program-0.7.0}/gea/gauge_specs.py +0 -0
  150. {gea_program-0.6.0 → gea_program-0.7.0}/gea/gravity_reference.py +0 -0
  151. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/alarms.md +0 -0
  152. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/data-in.md +0 -0
  153. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/doctor.md +0 -0
  154. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/drift.md +0 -0
  155. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/files.md +0 -0
  156. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/instruments.md +0 -0
  157. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/notifications.md +0 -0
  158. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/patches.md +0 -0
  159. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/quality.md +0 -0
  160. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/site.md +0 -0
  161. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/start.md +0 -0
  162. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/transients.md +0 -0
  163. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/upkeep.md +0 -0
  164. {gea_program-0.6.0 → gea_program-0.7.0}/gea/help/well-tests.md +0 -0
  165. {gea_program-0.6.0 → gea_program-0.7.0}/gea/housekeeping.py +0 -0
  166. {gea_program-0.6.0 → gea_program-0.7.0}/gea/inverse_engine.py +0 -0
  167. {gea_program-0.6.0 → gea_program-0.7.0}/gea/live_ports.py +0 -0
  168. {gea_program-0.6.0 → gea_program-0.7.0}/gea/loadtest.py +0 -0
  169. {gea_program-0.6.0 → gea_program-0.7.0}/gea/matplotlib_demo.py +0 -0
  170. {gea_program-0.6.0 → gea_program-0.7.0}/gea/modbus.py +0 -0
  171. {gea_program-0.6.0 → gea_program-0.7.0}/gea/model_card.py +0 -0
  172. {gea_program-0.6.0 → gea_program-0.7.0}/gea/mqtt_port.py +0 -0
  173. {gea_program-0.6.0 → gea_program-0.7.0}/gea/notify.py +0 -0
  174. {gea_program-0.6.0 → gea_program-0.7.0}/gea/opcua_port.py +0 -0
  175. {gea_program-0.6.0 → gea_program-0.7.0}/gea/operator_app.py +0 -0
  176. {gea_program-0.6.0 → gea_program-0.7.0}/gea/patches.py +0 -0
  177. {gea_program-0.6.0 → gea_program-0.7.0}/gea/ports.py +0 -0
  178. {gea_program-0.6.0 → gea_program-0.7.0}/gea/profile_catalog.py +0 -0
  179. {gea_program-0.6.0 → gea_program-0.7.0}/gea/project.py +0 -0
  180. {gea_program-0.6.0 → gea_program-0.7.0}/gea/qt6_downhole_app.py +0 -0
  181. {gea_program-0.6.0 → gea_program-0.7.0}/gea/reconciler.py +0 -0
  182. {gea_program-0.6.0 → gea_program-0.7.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
  183. {gea_program-0.6.0 → gea_program-0.7.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
  184. {gea_program-0.6.0 → gea_program-0.7.0}/gea/reference/libmseed_steim.provenance.json +0 -0
  185. {gea_program-0.6.0 → gea_program-0.7.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
  186. {gea_program-0.6.0 → gea_program-0.7.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
  187. {gea_program-0.6.0 → gea_program-0.7.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
  188. {gea_program-0.6.0 → gea_program-0.7.0}/gea/rock_inventory.py +0 -0
  189. {gea_program-0.6.0 → gea_program-0.7.0}/gea/sample_record.py +0 -0
  190. {gea_program-0.6.0 → gea_program-0.7.0}/gea/sample_well_profile.csv +0 -0
  191. {gea_program-0.6.0 → gea_program-0.7.0}/gea/sbom.py +0 -0
  192. {gea_program-0.6.0 → gea_program-0.7.0}/gea/segy.py +0 -0
  193. {gea_program-0.6.0 → gea_program-0.7.0}/gea/seismic.py +0 -0
  194. {gea_program-0.6.0 → gea_program-0.7.0}/gea/seismic_array.py +0 -0
  195. {gea_program-0.6.0 → gea_program-0.7.0}/gea/seismic_detect.py +0 -0
  196. {gea_program-0.6.0 → gea_program-0.7.0}/gea/seismic_response.py +0 -0
  197. {gea_program-0.6.0 → gea_program-0.7.0}/gea/sensor_swap.py +0 -0
  198. {gea_program-0.6.0 → gea_program-0.7.0}/gea/service_life.py +0 -0
  199. {gea_program-0.6.0 → gea_program-0.7.0}/gea/shell.py +0 -0
  200. {gea_program-0.6.0 → gea_program-0.7.0}/gea/shut_in.py +0 -0
  201. {gea_program-0.6.0 → gea_program-0.7.0}/gea/sla_report.py +0 -0
  202. {gea_program-0.6.0 → gea_program-0.7.0}/gea/store_forward.py +0 -0
  203. {gea_program-0.6.0 → gea_program-0.7.0}/gea/strata_join.py +0 -0
  204. {gea_program-0.6.0 → gea_program-0.7.0}/gea/survey_cmd.py +0 -0
  205. {gea_program-0.6.0 → gea_program-0.7.0}/gea/survey_view.py +0 -0
  206. {gea_program-0.6.0 → gea_program-0.7.0}/gea/telemetry.py +0 -0
  207. {gea_program-0.6.0 → gea_program-0.7.0}/gea/tool_library.py +0 -0
  208. {gea_program-0.6.0 → gea_program-0.7.0}/gea/transient.py +0 -0
  209. {gea_program-0.6.0 → gea_program-0.7.0}/gea/well_assembler.py +0 -0
  210. {gea_program-0.6.0 → gea_program-0.7.0}/gea/well_test_validation.py +0 -0
  211. {gea_program-0.6.0 → gea_program-0.7.0}/gea/wits0.py +0 -0
  212. {gea_program-0.6.0 → gea_program-0.7.0}/gea/witsml.py +0 -0
  213. {gea_program-0.6.0 → gea_program-0.7.0}/gea_program.egg-info/dependency_links.txt +0 -0
  214. {gea_program-0.6.0 → gea_program-0.7.0}/gea_program.egg-info/entry_points.txt +0 -0
  215. {gea_program-0.6.0 → gea_program-0.7.0}/gea_program.egg-info/requires.txt +0 -0
  216. {gea_program-0.6.0 → gea_program-0.7.0}/gea_program.egg-info/top_level.txt +0 -0
  217. {gea_program-0.6.0 → gea_program-0.7.0}/setup.cfg +0 -0
  218. {gea_program-0.6.0 → gea_program-0.7.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.6.0
3
+ Version: 0.7.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
@@ -110,7 +110,10 @@ reaches a client document. Nothing unmeasured is ever reported as met.
110
110
  leg lives on the dashboard: a Seismic page where a station or an array is
111
111
  added by upload with its rigs list and station file, refreshed as a job,
112
112
  and read - spectrum, lines, verdicts, bearing - with its Seismic Station
113
- Report under Reports. See *The second leg*.
113
+ Report under Reports; and the SAR panel on that page, a control panel and a
114
+ screen that plays the leg's arithmetic forward in time on the labelled
115
+ synthetic scene (`seismic_film.py`), every frame stamped SIMULATION_SELF_TEST.
116
+ See *The second leg*.
114
117
 
115
118
  ## Quick start
116
119
 
@@ -122,8 +125,8 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
122
125
  gea client-report --report accuracy --out client_report
123
126
  gea model-cards --out model_cards
124
127
  gea sbom --out sbom
125
- gea accept # the product gate (258 checks)
126
- gea help drift # the help library, by the job (15 pages; the same text is on every dashboard page)
128
+ gea accept # the product gate (266 checks)
129
+ gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
127
130
  gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
128
131
  gea gui # the desktop window (pip install "gea-program[desktop]")
129
132
  gea workspace --path C:\site --action init --name "Pad 3" # a site folder
@@ -251,10 +254,10 @@ text: JSON, JSON lines, CSV, Markdown, HTML.
251
254
 
252
255
  ### The help library
253
256
 
254
- `gea help` lists fifteen pages indexed by the job a reader arrives with -
257
+ `gea help` lists sixteen pages indexed by the job a reader arrives with -
255
258
  start, bring data in, quality rules, drift, well tests, alarms and the month,
256
259
  the site, instruments, shut-ins and build-ups, seismic (the second leg),
257
- patches, files, notifications, which code is running, upkeep. Each page carries four lines and stops: the
260
+ patches, files, notifications, which code is running, audit / update, upkeep. Each page carries four lines and stops: the
258
261
  command, what it writes, the one number to check, and what the page will not
259
262
  call a measurement. The pages ship inside the package (`gea/help/`), and the
260
263
  same text is what `/api/help` serves and what the dashboard shows under every
@@ -394,6 +397,70 @@ a rig not on the list, and any quantity in physical units until a station's
394
397
  response has been applied and named. `--action selftest` runs the test on a
395
398
  synthetic scene and labels its output SIMULATION_SELF_TEST.
396
399
 
400
+ The SAR panel at the foot of the Seismic page is the control panel and the
401
+ screen. "Run the scene" is `gea workspace --action sar-film` as a job: the
402
+ labelled synthetic array scene, one frame per window, written under
403
+ `reports/seismic/SIMULATION/`. The screen plays it - the trace, the
404
+ spectrogram column arriving, the beam power map on the slowness grid swinging
405
+ onto the working rig, the map with the bearing and the array's tolerance
406
+ wedge against the rigs where the scene put them, the tally per rig, and at
407
+ the end the array detectability test's verdict on the whole scene, the same
408
+ function a real record goes through. Every frame carries SIMULATION_SELF_TEST
409
+ and the line "not a measurement of any ground"; a real record is refreshed on
410
+ its station and the page shows what it earned, never a film. `gea seismic
411
+ --action sar-film --out film.json` writes the same film from the command line.
412
+
413
+ ### Tracks - the time dimension
414
+
415
+ The array step gives one bearing for one window. `seismic_track.py` runs it
416
+ window after window: a bearing history per array (a bearing with the array's
417
+ own tolerance where the beam was coherent, a gap where it was not, change
418
+ points where the bearing moved beyond the tolerance), a position history from
419
+ two or more arrays crossed window by window (a position only where two or
420
+ more arrays were coherent, the bearings crossed at 15 degrees or more and the
421
+ point lies in front of every array - every other window a gap with its
422
+ reason), and the track: the principal line through the longest continuous
423
+ segment of positions, with its heading, length and rate, the ellipses beside
424
+ every point, and segments listed apart where positions jump farther than
425
+ their ellipses allow (a coherent background crossing in a quiet hour is not
426
+ the rig an hour later). The verdict against ground truth - the lateral's
427
+ surveyed points or a permit's surface hole with its date, interpolated to
428
+ each position's time - is TRACKED, PARTIAL, NOT_TRACKED or INSUFFICIENT, with
429
+ the fraction and the heading difference printed. The labelled scene behind
430
+ `--action track-selftest` is a bit advancing along a straight lateral past
431
+ two arrays. On a site a track is two or more array stations and an optional
432
+ truth CSV, refreshed as a job into the Seismic Track Report; the track view
433
+ shows the map with every position's ellipse, a slider through time and the
434
+ bearings over time, and the SAR panel's second scene plays the same thing
435
+ forward with the track drawn as it is earned.
436
+
437
+ Ground truth from a permit export: `gea permits --file export.csv --out
438
+ rigs.csv --within LAT LON KM` finds the columns of a regulator's query (an
439
+ identifier, a surface position, a spud or approval date) by name, with a
440
+ mapping file when the guesses are wrong, and writes the rigs CSV the tests
441
+ read beside an import note that says which columns were used, how many rows
442
+ were dropped and why, and how many end dates it assumed (a permit rarely says
443
+ when drilling stopped). The Seismic page's add form takes a permit export in
444
+ place of the rigs CSV and keeps both.
445
+
446
+ ### Audit / Update
447
+
448
+ The Audit / Update tab holds three things. The whole audit log
449
+ (`records/audit.jsonl`) with filters by who, by action and since a date, and
450
+ a CSV download - Administration keeps the last hundred lines and points here.
451
+ The program card: the running version and code path, the newest release on
452
+ PyPI (`current`, `behind`, or `PyPI not reachable` when the machine is
453
+ offline), which extras are installed here, and links to PyPI, the releases
454
+ with the install kits, and the CHANGELOG; "Update the program from PyPI"
455
+ (admin) is `gea update` as a job - pip --upgrade from the same Python, after
456
+ which the service must be restarted; the program never restarts itself, and
457
+ an offline kit is updated by installing the newer kit. The data card: every
458
+ report against its source - `current` or `stale` when the source changed
459
+ after the report was written - and "Update every report from its source"
460
+ (operator), which is `gea workspace --action refresh-all` as a job: the
461
+ dashboard for every well, then every seismic station, errors collected and
462
+ listed, never hidden.
463
+
397
464
  ### Before a site goes live
398
465
 
399
466
  `deploy/README.md` is the checklist: keep the service on the loopback
@@ -446,7 +513,8 @@ docs/report_samples/ one rendered example of every client report, from this bui
446
513
  docs/ TESTER_GUIDE.md, REQUIREMENTS_MATRIX.md (the scope-of-work mirror that shaped the reports), examples/ (port configs),
447
514
  SESSION_LOG.md (the working record, session by session),
448
515
  commercial/ (pilot proposal, bench readiness, commercial use), HISTORY.md (the ship-by-ship record)
449
- tools/ standalone_check.py (the self-contained guard; run by ci and ship.ps1), build_installer.py (the kit)
516
+ tools/ standalone_check.py (the self-contained guard; run by ci and ship.ps1), build_installer.py (the kit),
517
+ render_report_samples.py (docs/report_samples), seismic_reader_check.py (the reader against libmseed)
450
518
  CHANGELOG.md per-release summary (a tag ships only with its section); SHIP_LOG.md is written by ship.ps1
451
519
  tests/ pytest wrapper around the acceptance suite and the standalone check
452
520
  ```
@@ -71,7 +71,10 @@ reaches a client document. Nothing unmeasured is ever reported as met.
71
71
  leg lives on the dashboard: a Seismic page where a station or an array is
72
72
  added by upload with its rigs list and station file, refreshed as a job,
73
73
  and read - spectrum, lines, verdicts, bearing - with its Seismic Station
74
- Report under Reports. See *The second leg*.
74
+ Report under Reports; and the SAR panel on that page, a control panel and a
75
+ screen that plays the leg's arithmetic forward in time on the labelled
76
+ synthetic scene (`seismic_film.py`), every frame stamped SIMULATION_SELF_TEST.
77
+ See *The second leg*.
75
78
 
76
79
  ## Quick start
77
80
 
@@ -83,8 +86,8 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
83
86
  gea client-report --report accuracy --out client_report
84
87
  gea model-cards --out model_cards
85
88
  gea sbom --out sbom
86
- gea accept # the product gate (258 checks)
87
- gea help drift # the help library, by the job (15 pages; the same text is on every dashboard page)
89
+ gea accept # the product gate (266 checks)
90
+ gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
88
91
  gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
89
92
  gea gui # the desktop window (pip install "gea-program[desktop]")
90
93
  gea workspace --path C:\site --action init --name "Pad 3" # a site folder
@@ -212,10 +215,10 @@ text: JSON, JSON lines, CSV, Markdown, HTML.
212
215
 
213
216
  ### The help library
214
217
 
215
- `gea help` lists fifteen pages indexed by the job a reader arrives with -
218
+ `gea help` lists sixteen pages indexed by the job a reader arrives with -
216
219
  start, bring data in, quality rules, drift, well tests, alarms and the month,
217
220
  the site, instruments, shut-ins and build-ups, seismic (the second leg),
218
- patches, files, notifications, which code is running, upkeep. Each page carries four lines and stops: the
221
+ patches, files, notifications, which code is running, audit / update, upkeep. Each page carries four lines and stops: the
219
222
  command, what it writes, the one number to check, and what the page will not
220
223
  call a measurement. The pages ship inside the package (`gea/help/`), and the
221
224
  same text is what `/api/help` serves and what the dashboard shows under every
@@ -355,6 +358,70 @@ a rig not on the list, and any quantity in physical units until a station's
355
358
  response has been applied and named. `--action selftest` runs the test on a
356
359
  synthetic scene and labels its output SIMULATION_SELF_TEST.
357
360
 
361
+ The SAR panel at the foot of the Seismic page is the control panel and the
362
+ screen. "Run the scene" is `gea workspace --action sar-film` as a job: the
363
+ labelled synthetic array scene, one frame per window, written under
364
+ `reports/seismic/SIMULATION/`. The screen plays it - the trace, the
365
+ spectrogram column arriving, the beam power map on the slowness grid swinging
366
+ onto the working rig, the map with the bearing and the array's tolerance
367
+ wedge against the rigs where the scene put them, the tally per rig, and at
368
+ the end the array detectability test's verdict on the whole scene, the same
369
+ function a real record goes through. Every frame carries SIMULATION_SELF_TEST
370
+ and the line "not a measurement of any ground"; a real record is refreshed on
371
+ its station and the page shows what it earned, never a film. `gea seismic
372
+ --action sar-film --out film.json` writes the same film from the command line.
373
+
374
+ ### Tracks - the time dimension
375
+
376
+ The array step gives one bearing for one window. `seismic_track.py` runs it
377
+ window after window: a bearing history per array (a bearing with the array's
378
+ own tolerance where the beam was coherent, a gap where it was not, change
379
+ points where the bearing moved beyond the tolerance), a position history from
380
+ two or more arrays crossed window by window (a position only where two or
381
+ more arrays were coherent, the bearings crossed at 15 degrees or more and the
382
+ point lies in front of every array - every other window a gap with its
383
+ reason), and the track: the principal line through the longest continuous
384
+ segment of positions, with its heading, length and rate, the ellipses beside
385
+ every point, and segments listed apart where positions jump farther than
386
+ their ellipses allow (a coherent background crossing in a quiet hour is not
387
+ the rig an hour later). The verdict against ground truth - the lateral's
388
+ surveyed points or a permit's surface hole with its date, interpolated to
389
+ each position's time - is TRACKED, PARTIAL, NOT_TRACKED or INSUFFICIENT, with
390
+ the fraction and the heading difference printed. The labelled scene behind
391
+ `--action track-selftest` is a bit advancing along a straight lateral past
392
+ two arrays. On a site a track is two or more array stations and an optional
393
+ truth CSV, refreshed as a job into the Seismic Track Report; the track view
394
+ shows the map with every position's ellipse, a slider through time and the
395
+ bearings over time, and the SAR panel's second scene plays the same thing
396
+ forward with the track drawn as it is earned.
397
+
398
+ Ground truth from a permit export: `gea permits --file export.csv --out
399
+ rigs.csv --within LAT LON KM` finds the columns of a regulator's query (an
400
+ identifier, a surface position, a spud or approval date) by name, with a
401
+ mapping file when the guesses are wrong, and writes the rigs CSV the tests
402
+ read beside an import note that says which columns were used, how many rows
403
+ were dropped and why, and how many end dates it assumed (a permit rarely says
404
+ when drilling stopped). The Seismic page's add form takes a permit export in
405
+ place of the rigs CSV and keeps both.
406
+
407
+ ### Audit / Update
408
+
409
+ The Audit / Update tab holds three things. The whole audit log
410
+ (`records/audit.jsonl`) with filters by who, by action and since a date, and
411
+ a CSV download - Administration keeps the last hundred lines and points here.
412
+ The program card: the running version and code path, the newest release on
413
+ PyPI (`current`, `behind`, or `PyPI not reachable` when the machine is
414
+ offline), which extras are installed here, and links to PyPI, the releases
415
+ with the install kits, and the CHANGELOG; "Update the program from PyPI"
416
+ (admin) is `gea update` as a job - pip --upgrade from the same Python, after
417
+ which the service must be restarted; the program never restarts itself, and
418
+ an offline kit is updated by installing the newer kit. The data card: every
419
+ report against its source - `current` or `stale` when the source changed
420
+ after the report was written - and "Update every report from its source"
421
+ (operator), which is `gea workspace --action refresh-all` as a job: the
422
+ dashboard for every well, then every seismic station, errors collected and
423
+ listed, never hidden.
424
+
358
425
  ### Before a site goes live
359
426
 
360
427
  `deploy/README.md` is the checklist: keep the service on the loopback
@@ -407,7 +474,8 @@ docs/report_samples/ one rendered example of every client report, from this bui
407
474
  docs/ TESTER_GUIDE.md, REQUIREMENTS_MATRIX.md (the scope-of-work mirror that shaped the reports), examples/ (port configs),
408
475
  SESSION_LOG.md (the working record, session by session),
409
476
  commercial/ (pilot proposal, bench readiness, commercial use), HISTORY.md (the ship-by-ship record)
410
- tools/ standalone_check.py (the self-contained guard; run by ci and ship.ps1), build_installer.py (the kit)
477
+ tools/ standalone_check.py (the self-contained guard; run by ci and ship.ps1), build_installer.py (the kit),
478
+ render_report_samples.py (docs/report_samples), seismic_reader_check.py (the reader against libmseed)
411
479
  CHANGELOG.md per-release summary (a tag ships only with its section); SHIP_LOG.md is written by ship.ps1
412
480
  tests/ pytest wrapper around the acceptance suite and the standalone check
413
481
  ```
@@ -122,7 +122,7 @@ from .profile_catalog import (
122
122
  read_pangaea_txt,
123
123
  )
124
124
 
125
- __version__ = "0.6.0"
125
+ __version__ = "0.7.0"
126
126
  __all__ = [
127
127
  "aging_rate", "rate_psi_yr", "accuracy_psi",
128
128
  "Sensor", "SimulatorConfig", "DownholeEngine",
@@ -280,7 +280,16 @@ def main(argv=None) -> int:
280
280
  p_ws.add_argument("--path", type=str, required=True, help="the workspace folder")
281
281
  p_ws.add_argument("--action", type=str, default="list",
282
282
  choices=["init", "add-file", "add-catalog", "add-live", "remove", "list", "migrate", "refresh", "audit",
283
- "add-seismic", "refresh-seismic", "remove-seismic"])
283
+ "add-seismic", "refresh-seismic", "remove-seismic", "sar-film", "refresh-all", "add-track", "refresh-track", "remove-track"])
284
+ p_ws.add_argument("--stations", type=str, nargs="+", default=None, help="add-track: two or more array station ids of this workspace")
285
+ p_ws.add_argument("--truth", type=str, default=None, help="add-track: ground truth CSV (point_id, lat, lon, utc[, note])")
286
+ p_ws.add_argument("--track", type=str, default=None, help="refresh-track / remove-track: the track id")
287
+ p_ws.add_argument("--win", type=float, default=600.0, help="add-track: the window length, s (default 600)")
288
+ p_ws.add_argument("--hours", type=float, default=8.0, help="sar-film: the synthetic scene's length, h")
289
+ p_ws.add_argument("--step", type=float, default=600.0, help="sar-film: seconds per frame")
290
+ p_ws.add_argument("--seed", type=int, default=5, help="sar-film: the scene's seed")
291
+ p_ws.add_argument("--method", type=str, default="bartlett", choices=["bartlett", "capon"], help="sar-film: the beamformer")
292
+ p_ws.add_argument("--scene", type=str, default="rigs", choices=["rigs", "lateral"], help="sar-film: fixed rigs, or a bit advancing along a lateral past two arrays")
284
293
  p_ws.add_argument("--files", type=str, nargs="+", default=None, help="add-seismic: the station's record (or one record per sensor of an array, in the sensors CSV's order)")
285
294
  p_ws.add_argument("--lat", type=float, default=None, help="add-seismic: the station's latitude")
286
295
  p_ws.add_argument("--lon", type=float, default=None, help="add-seismic: the station's longitude")
@@ -288,6 +297,7 @@ def main(argv=None) -> int:
288
297
  p_ws.add_argument("--sensors", type=str, default=None, help="add-seismic: sensors CSV (sensor_id, lat, lon) - makes the station an array")
289
298
  p_ws.add_argument("--sources", type=str, default=None, help="add-seismic: the rigs CSV (source_id, lat, lon, start_utc, end_utc[, kind, note])")
290
299
  p_ws.add_argument("--band", type=float, nargs=2, default=None, metavar=("LO", "HI"), help="add-seismic: the band, Hz (default 1 50)")
300
+ p_ws.add_argument("--permits", type=str, default=None, help="add-seismic: a permit export to turn into the rigs CSV (instead of --sources)")
291
301
  p_ws.add_argument("--station", type=str, default=None, help="refresh-seismic / remove-seismic: the station id")
292
302
  p_ws.add_argument("--name", type=str, default=None, help="init: site name; add-*: display name")
293
303
  p_ws.add_argument("--file", type=str, default=None, help="add-file: the client's data file; add-live: the port configuration JSON")
@@ -348,6 +358,19 @@ def main(argv=None) -> int:
348
358
  p_dr.add_argument("--port", type=int, default=8765)
349
359
  p_dr.add_argument("--json", action="store_true")
350
360
 
361
+ p_pm = sub.add_parser("permits", help="a drilling-permit export (CSV/TSV) to the rigs CSV the seismic tests judge against, with an import note")
362
+ p_pm.add_argument("--file", type=str, required=True, help="the permit export (a regulator's query CSV, an operator's schedule)")
363
+ p_pm.add_argument("--out", type=str, required=True, help="the rigs CSV to write (an .import.json note is written beside it)")
364
+ p_pm.add_argument("--mapping", type=str, default=None, help='JSON {"lat": "<column>", "lon": ..., "start": ..., "end": ..., "id": ..., "name": ...} when the guesses are wrong')
365
+ p_pm.add_argument("--default-days", type=float, default=30.0, help="a row without an end date works this many days from its start (default 30)")
366
+ p_pm.add_argument("--within", type=float, nargs=3, default=None, metavar=("LAT", "LON", "KM"), help="keep only rigs within KM of LAT, LON")
367
+ p_pm.add_argument("--json", action="store_true")
368
+
369
+ p_up = sub.add_parser("update", help="the program update: compare the running version with PyPI and, unless --check, run pip --upgrade for it from this Python")
370
+ p_up.add_argument("--check", action="store_true", help="only report the running and the newest version")
371
+ p_up.add_argument("--extras", type=str, default="live,plotting,xls,desktop", help="the extras to carry through the upgrade (default live,plotting,xls,desktop)")
372
+ p_up.add_argument("--json", action="store_true")
373
+
351
374
  p_nt = sub.add_parser("notify", help="notification rules: validate the configuration, send a test message, show the delivery log")
352
375
  p_nt.add_argument("--workspace", type=str, default=None)
353
376
  p_nt.add_argument("--test", type=str, default=None, help="send a test message through this channel name")
@@ -357,7 +380,14 @@ def main(argv=None) -> int:
357
380
 
358
381
  p_se = sub.add_parser("seismic", help="the second leg's ingest: miniSEED/SAC in, spectra and persistent lines out, an FDSN fetch, and the detectability test against known rigs")
359
382
  p_se.add_argument("--action", choices=["info", "spectrum", "lines", "fetch", "stations", "detect", "selftest", "convert", "response", "remove-response",
360
- "beam", "array-detect", "locate", "array-selftest"], default="info")
383
+ "beam", "array-detect", "locate", "array-selftest", "sar-film", "bearings", "track", "track-selftest"], default="info")
384
+ p_se.add_argument("--histories", type=str, nargs="+", default=None, help="track: two or more bearing-history JSONs (from --action bearings), one per array")
385
+ p_se.add_argument("--truth", type=str, default=None, help="track: ground truth CSV (point_id, lat, lon, utc[, note]) - the lateral's points in time")
386
+ p_se.add_argument("--name", type=str, default=None, help="bearings: a name for the array in the history")
387
+ p_se.add_argument("--scene", type=str, default="rigs", choices=["rigs", "lateral"], help="sar-film: the labelled scene - fixed rigs, or a bit advancing along a lateral past two arrays")
388
+ p_se.add_argument("--hours", type=float, default=8.0, help="sar-film: the synthetic scene's length, h (default 8: four rigs, each working alone for an hour)")
389
+ p_se.add_argument("--step", type=float, default=600.0, help="sar-film: one frame per this many seconds (default 600)")
390
+ p_se.add_argument("--seed", type=int, default=5, help="sar-film: the scene's random seed")
361
391
  p_se.add_argument("--files", type=str, nargs="+", default=None, help="beam/array-detect: one record per sensor, in the order of --sensors")
362
392
  p_se.add_argument("--sensors", type=str, default=None, help="beam/array-detect: CSV of the array's sensors (sensor_id, lat, lon[, elevation_m])")
363
393
  p_se.add_argument("--bearings", type=str, default=None, help="locate: CSV of arrays' bearings (lat, lon, back_azimuth_deg, sigma_deg)")
@@ -760,6 +790,18 @@ def main(argv=None) -> int:
760
790
  print(f"seismic: response of {chan.id} removed ({chan.sensor or 'sensor unnamed'}); the record is now in {note['unit']}", file=sys.stderr)
761
791
  return trs, tr
762
792
  band = (float(a.band[0]), float(a.band[1]))
793
+ if a.action == "sar-film":
794
+ from . import seismic_film as FM
795
+ film = FM.sar_film(seed=a.seed, hours=a.hours, step_s=a.step, band=(float(a.band[0]), float(a.band[1])) if a.band != [1.0, 50.0] else (1.0, 20.0), method=a.method, scene=a.scene)
796
+ if a.out:
797
+ FM.write_film(film, a.out)
798
+ if a.json:
799
+ print(_json.dumps(FM.film_summary(film), indent=1))
800
+ else:
801
+ print(FM.report_text(film))
802
+ if a.out:
803
+ print(f"film: {a.out} ({len(film['frames'])} frames)")
804
+ return 0
763
805
  if a.action == "array-selftest":
764
806
  from . import seismic_array as AR
765
807
  r = AR.selftest()
@@ -772,7 +814,37 @@ def main(argv=None) -> int:
772
814
  print(f" three arrays' bearings cross {c['miss_km']:.2f} km from the rig; 1-sigma ellipse {c['ellipse_1sigma']['major_km']} x {c['ellipse_1sigma']['minor_km']} km; "
773
815
  f"crossing angle {c['crossing_angle_deg']} deg; in front of every array: {c['in_front_of_every_array']}")
774
816
  return 0 if r["ok"] else 1
775
- if a.action in ("beam", "array-detect"):
817
+ if a.action == "track-selftest":
818
+ from . import seismic_track as T
819
+ r = T.selftest()
820
+ if a.json:
821
+ print(_json.dumps({k: v for k, v in r.items() if k != "bearing_histories"}, indent=1, default=str))
822
+ else:
823
+ print(f"seismic track-selftest: {r['status']} ok={r['ok']}")
824
+ for h in r["bearing_histories"]:
825
+ print(f" {h['array']['name']}: {h['n_coherent']} coherent of {h['n_windows']} windows, tolerance {h['tolerance_deg']} deg, span {h['span_deg']} deg, {len(h['change_points'])} change point(s)")
826
+ print(T.report_text(r["positions"], r["verdict"]))
827
+ return 0 if r["ok"] else 1
828
+ if a.action == "track":
829
+ from . import seismic_track as T
830
+ if not a.histories or len(a.histories) < 2:
831
+ raise SystemExit("seismic track needs --histories (two or more bearing-history JSONs)")
832
+ hists = []
833
+ for hp in a.histories:
834
+ with open(hp, encoding="utf-8") as fh:
835
+ hists.append(_json.load(fh))
836
+ pos = T.position_history(hists)
837
+ ver = T.track_verdict(pos, T.load_truth_csv(a.truth)) if a.truth else None
838
+ res = {"positions": pos, "verdict": ver}
839
+ if a.out:
840
+ with open(a.out, "w", encoding="utf-8") as fh:
841
+ _json.dump(res, fh, indent=1, default=str)
842
+ if a.json:
843
+ print(_json.dumps(res, indent=1, default=str))
844
+ else:
845
+ print(T.report_text(pos, ver))
846
+ return 0
847
+ if a.action in ("beam", "array-detect", "bearings"):
776
848
  from . import seismic_array as AR
777
849
  if not a.files or not a.sensors:
778
850
  raise SystemExit(f"seismic {a.action} needs --files (one per sensor) and --sensors CSV")
@@ -788,6 +860,22 @@ def main(argv=None) -> int:
788
860
  if a.start or a.end:
789
861
  tr = tr.slice(S.parse_time(a.start) if a.start else tr.starttime, S.parse_time(a.end) if a.end else tr.endtime)
790
862
  trs.append(tr)
863
+ if a.action == "bearings":
864
+ from . import seismic_track as T
865
+ h = T.bearing_history(trs, sensors, band, a.win or 600.0, None, a.seg, a.smax, 41, a.method)
866
+ h["array"]["name"] = a.name or sensors[0].sensor_id
867
+ if a.out:
868
+ with open(a.out, "w", encoding="utf-8") as fh:
869
+ _json.dump(h, fh, indent=1)
870
+ if a.json:
871
+ print(_json.dumps(h, indent=1))
872
+ else:
873
+ print(f"seismic bearings: {h['array']['name']}, {h['n_coherent']} coherent of {h['n_windows']} windows of {h['win_s']:g} s, tolerance {h['tolerance_deg']} deg"
874
+ + (f", span {h['span_deg']} deg" if h['span_deg'] is not None else "") + f", {len(h['change_points'])} change point(s)")
875
+ for w in h["windows"]:
876
+ print(f" {w['start_utc']} " + (f"{w['back_azimuth_deg']:7.2f} deg coherence {w['coherence_max_bin']}" if w.get("back_azimuth_deg") is not None else "no beam")
877
+ + ("" if w["coherent"] else " (gap: not coherent)"))
878
+ return 0
791
879
  if a.action == "beam":
792
880
  b = AR.beam(trs, sensors, band, a.seg, a.smax, 61, a.method)
793
881
  b = {k: v for k, v in b.items() if not k.startswith("_")}
@@ -993,6 +1081,22 @@ def main(argv=None) -> int:
993
1081
  elif a.cmd == "doctor":
994
1082
  from .doctor import run as _doctor
995
1083
  return _doctor(a.workspace, a.host, a.port, a.json)
1084
+ elif a.cmd == "permits":
1085
+ import json as _json
1086
+ from . import permits as PM
1087
+ mapping = None
1088
+ if a.mapping:
1089
+ with open(a.mapping, encoding="utf-8") as fh:
1090
+ mapping = _json.load(fh)
1091
+ try:
1092
+ note = PM.import_permits(a.file, a.out, mapping=mapping, default_days=a.default_days, within=tuple(a.within) if a.within else None)
1093
+ except ValueError as e:
1094
+ raise SystemExit(f"permits: {e}")
1095
+ print(_json.dumps(note, indent=1) if a.json else PM.report_text(note))
1096
+ return 0
1097
+ elif a.cmd == "update":
1098
+ from .doctor import update as _update
1099
+ return _update(check_only=a.check, extras=a.extras, as_json=a.json)
996
1100
  elif a.cmd == "serve":
997
1101
  from .service import Service
998
1102
  from .workspace import WorkspaceError
@@ -1090,7 +1194,7 @@ def main(argv=None) -> int:
1090
1194
  if not (a.name and a.files):
1091
1195
  raise SystemExit("add-seismic needs --name and --files (one record, or one per sensor with --sensors)")
1092
1196
  st = ws.add_seismic_station(a.name, a.files, a.lat, a.lon, actor=a.actor, stationxml=a.stationxml, sensors_csv=a.sensors,
1093
- sources_csv=a.sources, band=a.band)
1197
+ sources_csv=a.sources, band=a.band, permits_csv=a.permits)
1094
1198
  print("seismic station:", st["id"], f"({st['kind']}, {len(st['files'])} record(s))"); return 0
1095
1199
  elif a.action == "refresh-seismic":
1096
1200
  ids = [a.station] if a.station else [x["id"] for x in ws.seismic_stations()]
@@ -1103,6 +1207,34 @@ def main(argv=None) -> int:
1103
1207
  + (f"; beam {r['beam_back_azimuth_deg']} deg, pointed at {r['pointed']}" if r["beam_back_azimuth_deg"] is not None else "")
1104
1208
  + f"\n report: {r['report']}")
1105
1209
  return 0
1210
+ elif a.action == "add-track":
1211
+ if not (a.name and a.stations):
1212
+ raise SystemExit("add-track needs --name and --stations (two or more array station ids)")
1213
+ tk = ws.add_track(a.name, a.stations, actor=a.actor, truth_csv=a.truth, band=a.band, win_s=a.win)
1214
+ print("track:", tk["id"], f"({len(tk['stations'])} arrays" + (f", truth {tk['truth']}" if tk["truth"] else ", no ground truth") + ")"); return 0
1215
+ elif a.action == "refresh-track":
1216
+ ids = [a.track] if a.track else [x["id"] for x in ws.tracks()]
1217
+ if not ids:
1218
+ raise SystemExit("refresh-track: no track in the workspace")
1219
+ for tid in ids:
1220
+ r = ws.refresh_track(tid, actor=a.actor)
1221
+ print(f"track {tid}: {r['arrays']} arrays, {r['positions']} positions of {r['windows']} windows"
1222
+ + (f", {r['segments']} segment(s), heading {r['heading_deg']} deg, length {r['length_km']} km" if r["heading_deg"] is not None else "")
1223
+ + (f"; verdict {r['verdict']} ({r['hit_fraction']:.0%})" if r["verdict"] else "; no ground truth") + f"\n report: {r['report']}")
1224
+ return 0
1225
+ elif a.action == "remove-track":
1226
+ if not a.track:
1227
+ raise SystemExit("remove-track needs --track <id>")
1228
+ ws.remove_track(a.track, actor=a.actor); print("removed (folder kept):", a.track); return 0
1229
+ elif a.action == "sar-film":
1230
+ r = ws.sar_film(actor=a.actor, seed=a.seed, hours=a.hours, step_s=a.step, band=tuple(a.band) if a.band else (1.0, 20.0), method=a.method, scene=a.scene)
1231
+ print(f"sar-film: {r['label']}, {r['frames']} frames over {r['hours']} h; verdicts {r['verdicts']}\n film: {r['path']}"); return 0
1232
+ elif a.action == "refresh-all":
1233
+ r = ws.refresh_all(actor=a.actor)
1234
+ print(f"refresh-all: {r['wells']} well(s) refreshed, {r['seismic']} seismic station(s) refreshed, {len(r['errors'])} error(s)")
1235
+ for e in r["errors"]:
1236
+ print(" error:", e)
1237
+ return 0 if not r["errors"] else 1
1106
1238
  elif a.action == "remove-seismic":
1107
1239
  if not a.station:
1108
1240
  raise SystemExit("remove-seismic needs --station <id>")