Seismic Volumes (SEG-Y)
This guide covers loading, displaying, and tuning SEG-Y seismic data in VRGS. The seismic volume object understands the SEG-Y rev 2.1 specification, handles arbitrarily large 3D post-stack cubes through an out-of-core tile cache and a brick-paged GPU atlas, and renders inline / crossline / time-slice sections, wiggle traces, and full 3D ray-marched volume views.
Real-world post-stack volumes are routinely 5–50 GB. VRGS never loads the entire cube into RAM: it scans the file once to build a small on-disk index, decodes individual traces on demand, and pages GPU-resident bricks based on what's currently in view. A 50 GB cube is no different in workflow from a 50 MB one — only the wait at first scan.
What is SEG-Y?
SEG-Y is the Society of Exploration Geophysicists' standard for exchanging seismic data. A SEG-Y file consists of:
| Block | Bytes | Purpose |
|---|---|---|
| Textual header | 3200 | Free-form EBCDIC (or ASCII) survey description |
| Binary header | 400 | Sample format, sample interval, sample count, rev 2.1 extensions |
| Extended text headers | 3200 each (optional) | Additional metadata stanzas |
| Trace records | 240 + N×4 each | Per-trace header + sample data |
The trace header carries the geometry — inline number, crossline number, CDP X/Y, scalars — that lets us position the trace in the world. Every step of the import pipeline depends on those values being where the spec says they are, which is why the byte-location override controls (described below) exist.
Importing a SEG-Y file
Use any of the standard import paths:
- Right-click the Seismic Volumes group node in the Data Tree ➝
Import. The file dialog is filtered for
.sgy/.segyand supports multi-select. - Drag-and-drop a
.sgy/.segyfile onto the project window - File ➝ Import (when available)
VRGS recognises the file by extension (.sgy / .segy) and routes it
to the SEG-Y importer. The importer immediately:
- Creates an empty Seismic Volume object in the Data Tree under the Seismic Volumes group.
- Launches a background scan thread.
- Returns control to you.
The scan walks every trace in the file once, building a sidecar index file that records:
- Inline / crossline grid extent and step
- The (inline, crossline) → (CDP-X, CDP-Y) affine fit (handles skewed surveys; needs only ≥3 non-collinear corner traces)
- A 512-bin amplitude histogram + p1 / p99 percentiles for default clipping
- Per-trace file offsets (for variable-length traces) or a fixed stride (for the standard fixed-length case)
- Sample format, sample interval, recording delay
The sidecar lives at:
<project folder>/SEISMIC_INDEXES/<basename>.segyidx
so it travels with the project. The original SEG-Y file is not copied — it stays where you put it. If you move the project to another machine, copy the SEG-Y alongside it (or somewhere VRGS can re-resolve the recorded path).
What you'll see while the scan runs
- The volume appears in the Data Tree immediately.
- Its checkbox is unchecked (no display yet — the geometry isn't known).
- Selecting the volume and opening its Properties shows a Status row
with
Scanning XX%. This refreshes when you re-click the object.
For a 5 GB cube on a fast SSD, expect the scan to finish in 30–90 seconds. The scan does two passes: the first computes geometry + amplitude min/max + mean; the second walks the histogram for accurate percentiles. If you re-import the same file later and the sidecar's recorded size + mtime still match, the scan is skipped entirely and the volume binds in milliseconds.
Z axis: time vs depth
SEG-Y files come in two flavours:
- Time files store amplitudes against two-way travel time (ms TWT).
- Depth files store amplitudes against depth (metres or feet).
VRGS infers the kind from the binary header's measurement_system
field (1 = metres, 2 = feet, otherwise time). You can override this
later in the Properties panel under Geometry → Z axis.
The volume renders downward in world space (sample 0 at the top,
last sample at the bottom), shifted by the per-trace
delay_recording_time.
Per-volume origin
Every volume carries its own (x, y, z) origin in world
coordinates, defaulted to the centre of the cube during the first scan.
Internally, all OpenGL math runs in origin-relative float
precision, so VRGS can render surveys located 500 km from the world
origin without the typical "z-fighting at depth" precision artefacts.
You normally don't need to touch the origin. If you're co-rendering multiple cubes with very disparate locations and want them all sharing one float-precision frame, set them to a common origin.
Display modes
Inline / crossline / time-slice sections
The default display. Each visible section is rendered as a single textured quad whose pixels come from a per-section R32F texture; trace amplitudes are sampled per-pixel and mapped through the active colormap.
To enable / disable sections, expand the Sections group in the Properties panel and edit the Inline, Crossline, and Time slice fields. Set a section field to its current value to leave it on; clear (delete) the value or pick the volume in the tree without properties open to leave the default mid-cube position.
Wiggle overlay
When Wiggle overlay is enabled, every trace on each visible inline/crossline section is drawn as a single line strip whose vertices are offset along the across-trace axis by the (gain × polarity × amplitude) at each sample. Time-slices have no time axis and are not overlaid.
- Wiggle scale — fraction of one trace-spacing the wiggle swings by; default 0.5 (max excursion = half a trace spacing). Increase for more visible wiggles; decrease in dense surveys to avoid crossover.
- Wiggle color — line colour. Default black; use white over a dark colormap.
3D volume render
Toggle 3D volume render in the Sections group to enable a full front-to-back ray-marched composite of the entire cube. The renderer is brick-paged: the cube is conceptually divided into 64³-voxel bricks, a fixed-size GPU atlas holds as many bricks as the budget allows, and the page table lookup determines which atlas slot owns each brick.
What you'll see immediately after enabling:
- Bricks page in over several frames, prioritised front-to-back relative to your viewpoint.
- Bricks not yet resident render as transparent (no tinting).
- Panning towards a previously-far region brings new bricks in; long-untouched bricks get evicted from the LRU.
For a 1024 × 1024 × 2000 cube at 4 bricks per frame upload, the visible facing slab fills in well under two seconds; the full cube would take much longer but is rarely needed all at once.
Display controls
Found in the Display group:
- Clip min / Clip max — amplitude values mapped to the bottom and top of the colormap. Defaults are derived from the index's p1 / p99 percentiles, centred on zero.
- Gain — multiplier applied before clipping. Useful for one-shot brightening without touching the clip range.
- Polarity flip — multiplies amplitudes by −1 before colormap lookup. Sometimes needed to match a different shop's polarity convention.
- Opacity — section opacity, 0–1.
- Reset clip to amplitudes — checkbox trigger; toggling re-derives the clip from p01 / p99 of the indexed amplitudes. Use when the current clip looks washed out or saturated.
- Colormap — built-ins: Diverging RWB (default; signed amplitudes), Grayscale (linear black-to-white), Seismic (gray midband + red/blue tails — common interpretation default), Viridis (perceptually uniform, useful for absolute-value attributes).
Trace header byte locations
Real-world SEG-Y files frequently disagree with the rev 2.1 spec on where to put inline, crossline, and CDP X/Y. The Trace header bytes group lets you tell VRGS where to look:
- Inline byte / size — where the inline number lives (rev 2.1: 189, size 4)
- Crossline byte / size — where the crossline number lives (rev 2.1: 193, size 4)
- CDP X byte / Y byte — ensemble coordinates (rev 2.1: 181 / 185)
- Scalar byte — coordinate scalar (rev 2.1: 71); positive multiplies, negative divides
A Preset dropdown fills the byte values for common conventions:
| Preset | Inline | Crossline | CDP X | CDP Y |
|---|---|---|---|---|
| Rev 2.1 standard | 189 | 193 | 181 | 185 |
| Legacy (5/9 inline-shotpoint) | 5 | 9 | 73 | 77 |
| OpendTect (9/13) | 9 | 13 | 181 | 185 |
After picking a preset (or hand-editing values), tick Apply field map. The volume re-scans asynchronously with the new locations; the sidecar is rebuilt.
If the Geometry group shows nonsense — inline range like
536870912 — 536936448, or "no traces parsed" — it's almost always
wrong byte locations. Try the Legacy or OpendTect presets first; if
neither works, open the SEG-Y file in a hex editor and inspect a few
trace headers (offset 3600 + N × stride) to find where the integers
look like sane inline numbers.
Memory budgets
The Memory group exposes three knobs:
- Tile cache (MB) — decoded-trace LRU cache budget. Default 64 MB. Hot sections benefit from a bigger cache; very wide cubes with rapid pan/scroll benefit from 256 MB or more.
- Volume atlas (MB) — GPU brick atlas size for 3D rendering. Default 512 MB. Capped to whole bricks per axis. Larger atlas = more of the cube resident on the GPU = less paging when you pan. Takes effect on the next 3D toggle (or after toggling the Linear atlas filter checkbox).
- Bricks per frame — cap on per-frame GPU brick uploads. Default 4 (≈4 MB / frame). Higher = faster fill but more frame stutter during heavy paging.
- Linear atlas filter — on (default) for smooth interpolated sampling; minor 1-voxel bleed at brick boundaries against unrelated atlas slots is sometimes visible. Off for blocky-but-exact rendering.
Picking & info
Click on a section in the 3D view: the volume becomes the picked object, and its Properties shows a Last pick group with:
- Inline number
- Crossline number
- Sample index
- Amplitude at that voxel
- World position
The pick goes through every visible section quad and picks the nearest hit. Time-slices, inlines, and crosslines are all pickable.
Diagnostics
The Diagnostics group shows live state:
- Tile cache —
used / budget MB (count traces) - Brick atlas —
resident / total slots (atlas voxel dims) - Brick grid — number of 64³ bricks along each axis
- Indexed traces — total trace count
- Amplitudes —
[min, max] p1/p99 [low, high]
A Clear tile cache trigger checkbox drops every cached trace; the next read reaches disk again. Useful when you've changed something on disk or just want to free memory for another task.
Project persistence
The volume's complete state — file path, sidecar path, origin, Z
kind, field map, all display settings, memory budgets — serialises
into the project database as a JSON blob. The trace data itself stays
in the SEG-Y file on disk; the sidecar stays under SEISMIC_INDEXES/.
When you reopen a project containing seismic volumes:
- The volume rows appear in the Data Tree immediately.
- Each volume launches an async re-bind to its recorded SEG-Y path.
- If the sidecar is still valid (file size + mtime unchanged), the bind completes in milliseconds. Otherwise a fresh scan runs.
- If the SEG-Y file is missing, the volume becomes a "broken link" — it stays in the project but doesn't render. Open Properties to see the error. To repair, edit the SEG-Y path in the project database or re-import.
Limitations
- 2D-line files (single-line collections of traces with no inline/crossline grid) are scanned and indexed but render only as a single inline section because the grid logic assumes a 3D cube.
- Pre-stack gathers are not currently supported. The scanner reads them but the display assumes one trace per (inline, crossline) cell.
- Trace identification codes other than "live" are ignored when building the cube.
- Wiggle on time-slices is intentionally not drawn (no time axis).
- Brick-edge artefacts with linear atlas filtering: switch to Linear atlas filter = off for exact (nearest-neighbour) sampling if the bleed bothers you.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Volume in tree but never renders | Bind failed — check Properties → Status for the error | Verify the SEG-Y path is reachable; re-import if missing |
| "no traces parsed" or absurd inline range | Wrong byte locations | Try the Legacy or OpendTect presets, then Apply field map |
| Sections look uniformly grey/white | Clip range way too wide | Reset clip to amplitudes in the Display group |
| 3D render shows nothing | 3D toggle off, or atlas budget hasn't allocated | Toggle 3D off and on after raising the atlas budget |
| Frame rate drops while panning | Per-frame brick upload throttle being saturated | Lower Bricks per frame, or raise the atlas budget so fewer evictions occur |
| Brick boundary stripes in 3D render | Linear filter bleed against neighbour bricks | Toggle Linear atlas filter off, or accept the artefact |
| Re-import scans every time | Sidecar can't be written (permissions?) | Verify the project folder is writable; check for SEISMIC_INDEXES/ |
Reference
- See Seismic Volumes Properties for the full per-property reference.
- See Seismic Volumes Context Menu for the right-click commands available on a seismic volume in the Data Tree.
- The SEG-Y rev 2.1 specification is the authoritative reference for byte layouts and field semantics; it's published by the SEG.