Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions .github/workflows/seismic-to-rms-notebook-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: Validate seismic to RMS notebook

on:
workflow_dispatch:
pull_request:
paths:
- notebooks/reservoir/seismic_to_rms_input_workflow.ipynb
- notebooks/examples_of_NeqSim_in_Colab.ipynb
- notebooks/maintenance_ledger/seismic_to_rms_inputs_20260901.json
- notebooks/notebook_maintenance_ledger.json
- scripts/generate_seismic_to_rms_notebook.py
- .github/workflows/seismic-to-rms-notebook-validation.yml
- README.md

permissions:
contents: read

jobs:
execute-and-validate:
runs-on: ubuntu-latest
timeout-minutes: 45

steps:
- name: Check out NeqSim-Colab
uses: actions/checkout@v4

- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

- name: Install the notebook runtime
run: |
python -m pip install --quiet \
nbformat==5.10.4 \
nbconvert==7.17.1 \
ipykernel==7.2.0 \
matplotlib \
numpy \
pandas \
scipy \
xtgeo==4.25.1 \
segyio==1.9.14 \
lasio==0.32

- name: Validate and generate notebook source
run: |
python -m py_compile scripts/generate_seismic_to_rms_notebook.py
python scripts/generate_seismic_to_rms_notebook.py

- name: Execute every cell in a clean process
env:
MPLCONFIGDIR: /tmp/matplotlib-seismic-to-rms
IPYTHONDIR: /tmp/ipython-seismic-to-rms
run: |
python scripts/execute_notebook_inprocess.py \
notebooks/reservoir/seismic_to_rms_input_workflow.ipynb

- name: Validate retained execution evidence
run: |
python scripts/check_notebook.py \
notebooks/reservoir/seismic_to_rms_input_workflow.ipynb
python - <<'PY'
from pathlib import Path
import nbformat

path = Path(
"notebooks/reservoir/seismic_to_rms_input_workflow.ipynb"
)
notebook = nbformat.read(path, as_version=4)
code_cells = [
cell for cell in notebook.cells if cell.cell_type == "code"
]
errors = []
stderr = []
figures = 0
for cell in code_cells:
for output in cell.get("outputs", []):
if output.output_type == "error":
errors.append(output)
if output.output_type == "stream" and output.name == "stderr":
stderr.append(output.text)
if "image/png" in output.get("data", {}):
figures += 1

assert len(code_cells) == 35
assert [cell.execution_count for cell in code_cells] == list(
range(1, 36)
)
assert not errors
assert not stderr
assert figures == 15
notebook_text = str(notebook)
assert "checks_passed" in notebook_text
assert "checks_total" in notebook_text
assert "porosity_trend_accepted" in notebook_text
assert "False" in notebook_text
print(
{
"code_cells": len(code_cells),
"retained_png_outputs": figures,
"stored_errors": len(errors),
}
)
PY

- name: Render HTML for visual review
run: |
jupyter nbconvert \
--to html \
--output seismic_to_rms_input_workflow.html \
notebooks/reservoir/seismic_to_rms_input_workflow.ipynb

- name: Upload executed evidence and RMS package
uses: actions/upload-artifact@v4
with:
name: seismic-to-rms-executed-notebook
path: |
notebooks/reservoir/seismic_to_rms_input_workflow.ipynb
notebooks/reservoir/seismic_to_rms_input_workflow.html
seismic_to_rms_outputs/reek_seismic_to_rms_inputs.zip
if-no-files-found: error
retention-days: 14
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Advanced notebooks use the released Python distribution only as the JPype bridge

* [LNG process simulation and benchmark comparison](notebooks/process/LNG_Process_Benchmark_Comparison.ipynb) – Run closed-loop SMR, C3MR, DMR, and nitrogen-expander models with common KPIs, literature checks, and an exchanger grid-convergence study.
* [IoT and Industry 4.0 with NeqSim](notebooks/AI/IoT_and_Industry4.0_with_NeqSim.ipynb) – Build an instrumented digital twin, stream dynamic simulation data, and explore Industry 4.0 workflows backed by NeqSim measurements.
* [Seismic acquisition to RMS-ready subsurface inputs](notebooks/reservoir/seismic_to_rms_input_workflow.ipynb) – Calculate CMP moveout and stacking, interpret public Reek seismic and wells, validate horizons and faults, screen seismic attributes, and export a checked RMS import package.
* [RMS-origin reservoir to OPM Flow, ERT, and NeqSim](notebooks/reservoir/rms_to_opm_flow_agent_ert.ipynb) – Audit public Reek ROFF exports, demonstrate blocking and property spreading, run OPM Flow and ERT, and define a governed RMS-agent contract.

## Getting Started
Expand Down
4 changes: 3 additions & 1 deletion notebooks/examples_of_NeqSim_in_Colab.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## RMS-origin reservoir automation\n",
"## Seismic-to-simulation reservoir automation\n",
"\n",
"* [Seismic acquisition to RMS-ready Reek inputs](reservoir/seismic_to_rms_input_workflow.ipynb): CMP/NMO/stack calculations, SEG-Y and well QC, ties, horizons, faults, uncertainty, attribute validation, and a governed RMS import package.\n",
"\n",
"* [RMS-origin Reek to OPM Flow, ERT, and NeqSim](reservoir/rms_to_opm_flow_agent_ert.ipynb): blocking, property spreading, real simulation, uncertainty, and a governed RMS-agent contract.\n"
]
Expand Down
106 changes: 106 additions & 0 deletions notebooks/maintenance_ledger/seismic_to_rms_inputs_20260901.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{
"schema_version": 1,
"shard": "seismic-to-rms-inputs-20260901",
"updated_at": "2026-09-01T06:41:37Z",
"notebooks": [
{
"path": "notebooks/reservoir/seismic_to_rms_input_workflow.ipynb",
"verified_date": "2026-09-01",
"verified_at_utc": "2026-09-01T06:41:37Z",
"neqsim_version": "not applicable; upstream geophysics companion notebook",
"python_version": "3.12.13",
"numpy_version": "2.3.5",
"pandas_version": "2.2.3",
"matplotlib_version": "3.10.8",
"scipy_version": "1.17.0",
"xtgeo_version": "4.25.1",
"segyio_version": "1.9.14",
"lasio_version": "0.32",
"execution_status": "passed",
"execution_method": "Clean isolated Python 3.12 process; all 35 code cells executed top-to-bottom with retained stdout, rich displays, tables, and inline figures.",
"code_cells": 35,
"substantive_code_cells": 35,
"markdown_cells": 22,
"git_blob_sha1": "30aeace5216c1ce5406be09d30e67d276c923794",
"notebook_bytes": 6396233,
"publication": {
"branch": "codex/seismic-to-rms-input-notebook",
"mode": "focused draft pull request",
"files": [
"notebooks/reservoir/seismic_to_rms_input_workflow.ipynb",
"scripts/generate_seismic_to_rms_notebook.py",
".github/workflows/seismic-to-rms-notebook-validation.yml",
"notebooks/maintenance_ledger/seismic_to_rms_inputs_20260901.json",
"notebooks/notebook_maintenance_ledger.json",
"notebooks/examples_of_NeqSim_in_Colab.ipynb",
"README.md"
]
},
"open_data": {
"repository": "equinor/xtgeo-testdata",
"commit": "cad17f24e22c19c6cefe6f647185395cc0a11add",
"license": "LGPL-3.0",
"dataset": "Public synthetic Reek depth-stack SEG-Y, RMS surfaces, fault polygons, and wells",
"integrity": "Thirteen immutable public inputs verified by embedded SHA-256 digests and byte counts."
},
"capabilities_demonstrated": [
"fully calculated synthetic common-midpoint gather, normal-moveout correction, and stack",
"SEG-Y geometry, amplitude, footprint, dead-trace, and outlier QC",
"RMS well and log ingestion, marker extraction, and well-to-seismic event-phase ties",
"sparse-control top/base horizon tracking with withheld-reference validation",
"fault support from a calculated lateral-discontinuity proxy",
"illustrative checkshot-calibrated time-to-depth conversion",
"residual-scaled structural realizations and gross-rock-volume calculation",
"interval attributes with blind-well porosity acceptance gating",
"RMS-ready SEG-Y, IRAP ASCII, polygon, RMS well, LAS, JSON, and CSV export",
"independent readback, manifest hashing, ZIP integrity, and licensed-worker contract"
],
"engineering_validation": {
"named_assertions_passed": 34,
"assertions_failed": 0,
"repository_checker_errors": 0,
"repository_checker_warnings": 0,
"retained_png_figures": 15,
"display_equations": 7
},
"result_summary": {
"public_input_files": 13,
"cube_dimensions": [
408,
280,
70
],
"seismic_traces": 114240,
"seismic_sample_interval_m": 5.0,
"zero_energy_traces": 8634,
"outlier_traces_repaired": 6,
"property_wells": 8,
"top_phase_shift_m": 10.0,
"base_phase_shift_m": -10.0,
"top_horizon_rmse_m": 14.243662,
"base_horizon_rmse_m": 14.062305,
"fault_support_ratio": 2.160662,
"illustrative_depth_conversion_rmse_m": 1.1165,
"structural_realizations": 6,
"grv_p50_million_m3": 3005.382,
"baseline_porosity_loo_rmse": 0.02745,
"best_seismic_porosity_loo_rmse": 0.02773,
"porosity_trend_accepted": false,
"package_files": 47,
"package_zip_mb": 30.811374,
"validation_checks_passed": 34,
"validation_checks_total": 34
},
"rendered_visual_validation": {
"renderer": "nbconvert 7.17.1 HTML with MathJax source and 15 retained Matplotlib PNG outputs",
"display_equations_inspected": 7,
"figures_inspected": 15,
"result": "passed",
"notes": "Every retained figure was inspected at original resolution for titles, units, legends, color scales, clipping, overlap, masking, and consistency with stored numerical tables. Visual QA caught and corrected masked-array fill values that initially broke the interpreted seismic-section axis. All display equations use Colab-safe compact dollar delimiters."
},
"documentation_impact": "Adds the missing upstream seismic-to-RMS companion to README.md and the notebook catalog; the downstream RMS-to-OPM-Flow-to-ERT-to-NeqSim notebook remains unchanged.",
"known_upstream_issue": null,
"issue_handling": "No actionable NeqSim defect was found. The notebook explicitly separates public teaching calculations from licensed RMS work and decision-grade interpretation."
}
]
}
4 changes: 2 additions & 2 deletions notebooks/notebook_maintenance_ledger.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schema_version": 3,
"updated_at": "2026-08-31T17:15:07Z",
"active_notebook_count": 295,
"updated_at": "2026-09-01T06:41:37Z",
"active_notebook_count": 296,
"shards_glob": "maintenance_ledger/*.json",
"retired_notebooks": [
{
Expand Down
Loading
Loading