Repository navigation
WP8: SEG-Y and LAS adapters, the iwt command, and the critical assessment - #9
Merged
Merged
Conversation
…ment - iwt.io: numpy SEG-Y reader/writer (rev 1/2, fixed-length traces, IBM/IEEE/int samples, both byte orders, scaled header words), ZO-VSP and gather files, LAS via lasio (mnemonics, us/ft-us/m, g/cc-kg/m3, TVDSS or MD - KB), CSV logs, layer models and time-depth tables - iwt.vsp.processing: the WP3 ZO-VSP chain in one call; the stratigraphic t* is driven by the recorded first arrival (a peak-frequency Ricker biased Q by 20 %) - iwt.cli: iwt demo / vsp / model / tie, python -m iwt, console entry point - tests/test_io_cli.py (14 tests): IBM floats, byte layout, segyio cross-check both ways, LAS units and depths, processing chain, CLI end to end - README: command line, WP8 results, using real data, the article's claims tested, critical assessment, errata; plan marked done; version 0.8.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
Recording-delay, geometry-unit and Q/datum handling can corrupt results, while accepted input cases can cause command failures.
11 open findings
Convert SEG-Y feet-based depths and offsets to metres · New Convert read_gather header distances from feet to metres · New Align synthetic ZOVSP data with delayed recording axes · New Require intrinsic Q for VSP inversion without logs · New Require datum-corrected times for VSP JSON input · New Handle receiver depths outside the usable model range · New Handle or reject negative VSP recording delays · New Reject wavelet half-lengths exceeding the estimation window · New Reject unequal per-trace recording delays · New Preserve nonzero VSP recording delay when writing SEG-Y · New Correct deconvolution shift for nonzero recording origin · New
What changed in this PR
Completes WP8 by connecting file-based data to the existing well-tie workflow and documenting the synthetic results and limitations.
Changes:
- Adds SEG-Y, LAS and CSV adapters.
- Introduces the ZO-VSP processing chain and
iwtcommands. - Adds interoperability tests and consolidates the article assessment.
| File | Description |
|---|---|
tests/test_io_cli.py |
Adapter, processing and CLI tests. |
README.md |
Usage, results and critical assessment. |
pyproject.toml |
CLI entry point, test dependency and version. |
iwt/vsp/processing.py |
Integrated ZO-VSP processing chain. |
iwt/vsp/__init__.py |
Documents the processing module. |
iwt/io.py |
SEG-Y, LAS and CSV adapters. |
iwt/cli.py |
Demo, VSP, model and tie commands. |
iwt/__main__.py |
Enables python -m iwt. |
iwt/__init__.py |
Exports adapters and updates version. |
docs/IMPLEMENTATION_PLAN.md |
Records WP8 completion and limitations. |
🧠 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
+345
to
+348
| depths = depth_sign * sg.headers[depth_field] + depth_shift | ||
| order = np.argsort(depths, kind="stable") | ||
| zs = float(np.median(sg.headers["source_depth"])) if source_depth is None else source_depth | ||
| xs = float(np.median(np.abs(sg.headers["offset"]))) if source_offset is None else source_offset |
Comment on lines
+379
to
+382
| off = np.abs(sg.headers["offset"]).astype(float) | ||
| order = np.argsort(off, kind="stable") | ||
| return Gather(sg.t, off[order], sg.data[order], float(np.median(sg.headers["source_depth"])), | ||
| float(np.median(-sg.headers["receiver_elevation"]))) |
Comment on lines
+133
to
+136
| syn = Z.synthetic_zovsp(strat_model, vsp.depths, vsp.source_depth, dt, t.size, | ||
| source_wavelet(t, down, pk), f_max=f_max, attenuation=False, | ||
| source="downgoing", workers=workers) | ||
| cs_strat = _chain(syn.t, syn.data, f_seismic, band)[4] |
| if args.vsp: | ||
| vsp = json.loads(Path(args.vsp).read_text()) | ||
| if qp is None: | ||
| q = vsp["q"] |
| qv = np.where(inv > 0, 1.0 / np.where(inv > 0, inv, 1.0), np.inf) | ||
| qp = _q_curve(z, q["top"], q["bottom"], qv) | ||
| note.append(f"{q['kind']} Q from {args.vsp}") | ||
| dz, tz = np.asarray(vsp["depths"], float), np.asarray(vsp["vertical_time"], float) |
| sg = IO.read_segy(args.seismic) | ||
| obs = sg.data[args.trace] | ||
| t, dt = sg.t, sg.dt | ||
| i0 = int(round(sg.t0 / dt)) |
| else: | ||
| spike = (np.array([0.0, dt]), np.array([1.0, 0.0])) | ||
| refl = normal_incidence(model, dt, nt, spike, **kw)[1][i0:] | ||
| tw, w = estimate_wavelet(obs[win], refl[win], dt, args.half_length, args.damping) |
| samples = np.ascontiguousarray(raw[:, 240:]).view(order + kind).reshape(n_traces, ns) | ||
| data = ibm_to_ieee(samples) if fmt == 1 else samples.astype(np.float64) | ||
| dt_us = binary["interval"] & 0xFFFF or int(headers["sample_interval"][0]) | ||
| t0 = float(headers["delay"][0]) * 1e-3 if n_traces else 0.0 |
| write_segy(path, vsp.data, vsp.dt, dict( | ||
| receiver_elevation=-vsp.depths, source_depth=np.full(n, vsp.source_depth), | ||
| offset=np.full(n, vsp.source_offset), field_record=np.ones(n), | ||
| trace_number=np.arange(1, n + 1)), text=text or "ZERO-OFFSET VSP WRITTEN BY IWT", fmt=fmt) |
| q = A.interval_q(vsp.depths, tv, dts, q_blocks) | ||
| corridor = None | ||
| if corridor_peak is not None: | ||
| dec = Z.deconvolve(t, up, down, tv, ricker(corridor_peak, vsp.dt)) |
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 8 of
docs/IMPLEMENTATION_PLAN.md, the last one. It adds three things:iwtcommand, which runs the ZO-VSP → model → tie chain on files;New code
iwt/io.py:iwt/vsp/processing.py: the WP3 ZO-VSP chain in one call (picks, separation, 30 Hz times, interval velocities, t*, interval Q, corridor stack). The stratigraphic synthetic is driven by the recorded first arrival.iwt/cli.py:iwt demo | vsp | model | tie, pluspython -m iwtand a console entry point.tests/test_io_cli.py(14 tests):devextras only; wheels exist for cp39 and cp313);Findings
Intrinsic Q depends on the wavelet driving the stratigraphic synthetic:
The recorded arrival beats even the true source wavelet.
iwt model: the model's times are within 0.83 ms RMS of the VSP. What remains is the bias of the reference pick plus the ray-theory against effective-medium scale effect.iwt tie:Not built (documented)
DLIS, deviation surveys, 3C rotation, walkaway picking, and command-line access to walkaway inversion and CMP migration (library only). Whether the Hanssen data are released was not checked.
Test plan
pytest -q -W error::RuntimeWarning -W error::DeprecationWarning(Python 3.13): 168 passedpytest -q(Python 3.9, without lasio and segyio): 161 passed, 4 skippedpyflakes iwt tests examplespytest -W error tests/test_io_cli.py: cleanpip install -e .gives a workingiwtcommand (--version, every--help)iwt demo → vsp → model → tiereproduces the README numbers🤖 Generated with Claude Code
https://claude.ai/code/session_019vaUDUPicoFeQaUhfhnoYq
Generated by Claude Code