Repository navigation
WP7: the integrated loop, discrepancy register, multiples and the Fig. 2/4/5 analogues - #8
Merged
Merged
Conversation
…. 2/4/5 analogues - iwt.welltie: least-squares wavelet estimation, phase rotation, tie metrics from the complex cross-correlation of analytic signals (shift and constant phase separated) - iwt.workflow: model_from_logs (dispersion with Q, anisotropy and Q curves, gap layer from the VSP), versioned models, discrepancy register, acceptance criteria, Markdown - iwt.multiples: CMP gathers with physics switched off step by step - iwt.avo.linear_resolution: identifiability (posterior std, data weight, correlation) - iwt.synthetic.dipping_reservoir_models: wedge, dipping reservoir, flat OWC - iwt.modeling.reflection.exact_pp_slowness; zero-offset fast path in reflection_table - examples/reproduce_paper.py runs logs -> ZO-VSP -> walkaway -> surface seismic on estimated models and writes docs/discrepancy_register.md and docs/figures/wp7_*.png - tests/test_workflow.py (11 tests); README, plan; version 0.7.0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019vaUDUPicoFeQaUhfhnoYq
There was a problem hiding this comment.
🟡 Changes recommended
Numerical errors, ground-truth leakage, and inconsistent model history and scoring undermine the workflow’s reliability.
8 open findings
Model registration retains mutable caller state · New Acceptance residual scores an inconsistent velocity model · New Anisotropy inversion uses true-earth Q instead of estimated Q · New RMS denominator ignores shared NaN masking · New Sorting hides reservoir contact order violations · New np.roll causes circular boundary artifacts · New Fractional shifts use stale phase and peak correlation · New Q averaging loses attenuation across finite and infinite Q · New
What changed in this PR
Implements WP7, connecting the existing modelling and calibration tools into an integrated synthetic-well workflow with an auditable discrepancy register.
Changes:
- Adds well-tie metrics, model versioning, physics comparisons, and identifiability analysis.
- Adds the reproduction script and dipping-reservoir experiment.
- Documents results, adds regression tests, and bumps the package version.
| File | Description |
|---|---|
| tests/test_workflow.py | Tests WP7 helpers and numerical behaviour. |
| README.md | Documents workflow, results, and limitations. |
| pyproject.toml | Bumps version to 0.7.0. |
| iwt/workflow.py | Adds log-derived models and discrepancy register. |
| iwt/welltie.py | Adds wavelet estimation and tie metrics. |
| iwt/synthetic.py | Adds dipping-reservoir model pairs. |
| iwt/raytrace.py | Optimizes zero-offset reflection tables. |
| iwt/multiples.py | Compares physics variants and relative errors. |
| iwt/modeling/reflection.py | Exposes PP reflection coefficients by slowness. |
| iwt/avo.py | Adds linear parameter-resolution analysis. |
| iwt/__init__.py | Exports new modules and updates version. |
| examples/reproduce_paper.py | Runs the integrated workflow and generates outputs. |
| docs/IMPLEMENTATION_PLAN.md | Records WP7 completion and deviations. |
| docs/discrepancy_register.md | Records generated discrepancies and acceptance results. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| criteria: List[Criterion] = field(default_factory=list) | ||
|
|
||
| def new_version(self, name: str, model: ElasticModel1D, changes: str) -> ModelVersion: | ||
| v = ModelVersion(len(self.versions), name, model, changes) |
Comment on lines
+147
to
+148
| reg.check("VSP first-break residual after calibration", 1e3 * np.sqrt(np.nanmean(d1 ** 2)), 1.0, | ||
| "<=", "ms") |
|
|
||
| def anisotropy_step(model, logs, reg, zo): | ||
| z = logs.depth | ||
| g_sonic, g_up = wp5.sonic_gamma(model, logs) |
Comment on lines
+71
to
+74
| a, b = np.asarray(a, dtype=float), np.asarray(b, dtype=float) | ||
| if mask is not None: | ||
| a, b = a[mask], b[mask] | ||
| return float(np.sqrt(np.nanmean((a - b) ** 2) / np.nanmean(b * b))) |
Comment on lines
+294
to
+297
| units.sort(key=lambda u: u.top) | ||
| below = units[units.index(water) + 1:] | ||
| if below and below[0].top <= water.top: | ||
| raise ValueError("the dip moves the base of the reservoir above the contact") |
| L = int(round(max_shift / dt)) | ||
| lags = np.arange(-L, L + 1) | ||
| # |analytic| norms are twice the real ones (equal energy in the quadrature part) | ||
| cc = np.array([np.vdot(np.roll(sa, k), oa) for k in lags]) / (2.0 * no * ns) |
| a, b, c = env[i - 1], env[i], env[i + 1] | ||
| den = a - 2 * b + c | ||
| off = 0.5 * (a - c) / den if den != 0 else 0.0 | ||
| phi = float(-np.angle(cc[i])) |
Comment on lines
+71
to
+72
| curves = {k: mid(_at(v, n)) for k, v in (("eps", eps), ("delta", delta), ("gamma", gamma), | ||
| ("qp", qp), ("qs", qs))} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Work package 7 of
docs/IMPLEMENTATION_PLAN.md. This runs the article's integrated loop (Lewis et al., 2016, Fig. 1) end to end on the synthetic well, using estimated models only:New code
iwt/welltie.py:iwt/workflow.py:model_from_logs: sonic and dipole moved to the seismic frequency with Q (Kjartansson, 1979); ε, δ, γ and Q curves; a gap layer above the logs, with its velocity from the VSP;Register: versions, discrepancies, criteria, Markdown output.iwt/multiples.py: CMP gathers with the physics switched off step by step (full, primaries with conversions, no mode conversion, P primaries, Born).iwt/avo.py:linear_resolutionfor the identifiability study.iwt/synthetic.py:dipping_reservoir_models(wedge, dipping reservoir, flat OWC, all-brine twin).iwt/modeling/reflection.py:exact_pp_slowness.iwt/raytrace.py: an exact zero-offset fast path inreflection_table.examples/reproduce_paper.py: the loop (about 6 min with 4 workers). It writesdocs/discrepancy_register.mdanddocs/figures/wp7_{tie,ava,section}.png.tests/test_workflow.py(11 tests), README and plan updates, version 0.7.0.Results (synthetic well)
The time tie closes:
The AVA does not close, as in the article. After migration:
Synthetic-only attribution:
Identifiability:
Fig. 5 analogue: VTI places the fluid signal inside the oil column, while isotropic imaging puts it 17 m deep. Q compensation barely sharpens the signal in 1D.
Deviations from the plan (documented in the plan's as-built notes)
Test plan
pytest -q -W error::RuntimeWarning -W error::DeprecationWarning(Python 3.13 venv): 154 passedpytest -q(Python 3.9 venv): 150 passed, 1 skipped (no matplotlib)pyflakes iwt tests examplespython examples/reproduce_paper.py --workers 4completes and regenerates the register and figures🤖 Generated with Claude Code
https://claude.ai/code/session_019vaUDUPicoFeQaUhfhnoYq
Generated by Claude Code