Repository navigation
WP5: walkaway VSP anisotropy and the gamma -> (eps, delta) calibration - #6
Merged
Merged
Conversation
- iwt.raytrace: exact qP phase velocity, vertical slowness q(p) and dq/dp, polarization (Christoffel eigenvector) in VTI incl. fluids; two-point direct rays in layered VTI, excluding rays steeper than max_angle (85 deg) in any layer (refraction regime). - iwt.vsp.walkaway: synthetic walkaway (azimuths, source statics, noise), slowness/polarization measurement with the joint covariance propagated from the picks, (Vp0, Vs0, eps, delta) inversion on V(theta) and psi(theta) with the exact Christoffel equation (or Thomsen's weak form), Gaussian priors, frozen effective-variance covariance and Laplace posterior with data weights; azimuthal chi2 consistency test and a polarization check for lateral heterogeneity. - iwt.calibration: Backus upscaling of the sonic gamma, Bayesian straight line with extra scatter (type-II ML), leave-one-out predictions. - examples/wp5_walkaway.py and docs/figures/wp5_*.png: six levels at 30-60 degrees, five inversion variants, near-angle trade-off, checks, sub-array heterogeneity, and the calibrated eps/delta curves. - Tests (17 new), README and plan updated; version 0.5.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
Calibration leakage, uncertainty diagnostics, and kinematic boundary errors remain unresolved.
6 open findings
Preserve input length when running window exceeds log · New Re-estimate scatter separately for each leave-one-out fold · New Treat q=0 as valid horizontal propagation endpoint · New Handle zero horizontal qP eigenvector at q=0 · New Avoid claiming full data weight for infinite posterior variance · New Account for correlated errors in polarization chi-square · New
What changed in this PR
Implements WP5, connecting walkaway VSP anisotropy estimates with the existing sonic calibration workflow.
Changes:
- Adds exact VTI ray tracing, walkaway measurements, inversion, and consistency checks.
- Adds gamma upscaling and Bayesian calibration to epsilon and delta.
- Adds tests, a synthetic example, documentation, and version 0.5.0.
| File | Description |
|---|---|
| tests/test_walkaway.py | Tests ray tracing and walkaway inversion. |
| tests/test_calibration.py | Tests upscaling and linear calibration. |
| README.md | Documents WP5 usage, results, and limitations. |
| pyproject.toml | Updates package version. |
| iwt/vsp/walkaway.py | Implements survey processing, inversion, and checks. |
| iwt/vsp/__init__.py | Documents the walkaway module. |
| iwt/raytrace.py | Adds exact qP kinematics and layered rays. |
| iwt/calibration.py | Adds gamma upscaling and Bayesian regression. |
| iwt/__init__.py | Exposes ray tracing and updates version. |
| examples/wp5_walkaway.py | Demonstrates inversion and calibration. |
| docs/IMPLEMENTATION_PLAN.md | Records WP5 completion and deviations. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+241
to
+243
| n = max(1, int(round(length / dz)) | 1) | ||
| c44m = 1.0 / _running_mean(1.0 / np.asarray(c44, float), n) | ||
| c66m = _running_mean(np.asarray(c66, float), n) |
Comment on lines
+301
to
+322
| def log_evidence(tau): | ||
| var = s ** 2 + tau ** 2 | ||
| G = np.column_stack([np.ones_like(x), x]) | ||
| C = np.diag(var) + G @ np.linalg.inv(P0) @ G.T | ||
| r = y - G @ m0 | ||
| sign, logdet = np.linalg.slogdet(C) | ||
| return -0.5 * (logdet + r @ np.linalg.solve(C, r)) | ||
|
|
||
| if scatter is None: | ||
| spread = max(float(np.std(y)), float(np.max(s)), 1e-6) | ||
| grid = np.concatenate([[0.0], np.geomspace(1e-4 * spread, 3.0 * spread, 200)]) | ||
| scatter = float(grid[np.argmax([log_evidence(t) for t in grid])]) | ||
| var = s ** 2 + scatter ** 2 | ||
| mean, cov = _line_posterior(x, y, var, m0, P0) | ||
| loo_m = np.empty(x.size) | ||
| loo_s = np.empty(x.size) | ||
| for i in range(x.size): | ||
| keep = np.arange(x.size) != i | ||
| mi, ci = _line_posterior(x[keep], y[keep], var[keep], m0, P0) | ||
| g = np.array([1.0, x[i]]) | ||
| loo_m[i] = g @ mi | ||
| loo_s[i] = np.sqrt(g @ ci @ g + scatter ** 2) |
| Q_s = np.where(b < 0, 2.0 * c / (-b + disc), (-b - disc) / (2.0 * a)) | ||
| Q_f = 1.0 / a33 - P | ||
| Q = np.where(fluid, Q_f, Q_s) | ||
| q = np.where(Q > 0, np.sqrt(np.where(Q > 0, Q, 1.0)), np.nan) |
Comment on lines
+104
to
+105
| ux = (a13 + a44) * p * q | ||
| uz = 1.0 - a11 * p * p - a44 * q * q |
Comment on lines
+307
to
+308
| return np.where(np.isfinite(self.prior_std), | ||
| 1.0 - np.diag(self.cov) / self.prior_std ** 2, 1.0) |
| e[j] = 1e-6 * max(abs(x[j]), 1.0) | ||
| G[:, j] = (_forward(x + e, data.theta)[1] - _forward(x - e, data.theta)[1]) / (2 * e[j]) | ||
| cov = np.where(np.outer(ok, ok), posterior.cov, 0.0) | ||
| R = R + G @ cov @ G.T |
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.

Implements work package 5 of
docs/IMPLEMENTATION_PLAN.md: the walkaway-VSP ε and δ of Lewis et al. (2016), following Leaney & Hornby (2007), and the calibration of the sonic γ with them.What is added
iwt.raytrace(exact qP kinematics in VTI, fluids included; Tsvankin, 2012):iwt.vsp.walkaway:data_weightper parameter.iwt.calibration:upscale_gamma: Backus upscaling, with C66 averaged arithmetically and C44 harmonically.bayes_linear: straight-line fit with an extra scatter term (type-II maximum likelihood), leave-one-out predictions and predictive bands.examples/wp5_walkaway.pyanddocs/figures/wp5_*.pngcover:Main findings (synthetic well)
Validation
🤖 Generated with Claude Code
https://claude.ai/code/session_019vaUDUPicoFeQaUhfhnoYq
Generated by Claude Code