Skip to main content

sweep-io

File and dataset I/O utilities for seismic full-waveform inversion (FWI). Designed to be independent of the sweep core — you can use it in any FWI / migration / imaging project, with or without the wave-equation engine.

The emphasis is on fast hot-path reads with overlap-with-compute: your FWI loop should never sit blocking on a SEG-Y read when the GPU has useful work to do.

What's in it

Module Purpose Extra deps
sweep_io.models Load/save velocity models (.npy, .npz, raw binary, .h5) none / h5py
sweep_io.geometry Acquisition geometry dataclasses (sources, receivers, dt, dh) and the UTM ↔ model-frame rotation (RotatedFrame) none
sweep_io.prefetch Background-thread prefetchers (Prefetcher, ThreadPoolPrefetcher, TimingPrefetcher) stdlib only
sweep_io.segy SEG-Y byte-offset readers (SEGYReader, MultiFileSEGYReader) + IBM↔IEEE codecs; high-level read_segy / write_segy defer segyio import numpy / segyio (lazy)
sweep_io.segy_index Header catalog built once over many SEG-Y files (build_segy_index, SEGYIndex) + a lazy shot-gather dataset none
sweep_io.seismic_plan Shot- (CSG) or receiver-grouped (CRG) plans (build_seismic_plan, SeismicPlan), the lazy PlanReader, and the shared-shot / per-CRG samplers none
sweep_io.plan DataPlan / ModelPlan: pick shots, receivers and the model window before FWI sees the data none
sweep_io.crg_build, sweep_io.crg_plan Build and load the CRG plan cache (crg_fwi_plan_v1) none / mpi4py for the parallel build
sweep_io.crg_dataset Dataset over a CRGPlan, padded collate, per-trace LRU cache torch
sweep_io.wavelet Read a source wavelet from an .npz container none
sweep_io.datasets torch.utils.data.Dataset for shot gathers, with iter_prefetched(...) torch
sweep_io.cuda_prefetch CUDA-aware CUDAPrefetcher with pinned memory + side-stream H2D torch

All optional backends are lazy-imported — you only need what you use.

Install

pip install sweep-io                  # numpy core + prefetch + low-level SEG-Y
pip install sweep-io[segy]            # + segyio (for read_segy / write_segy)
pip install sweep-io[hdf5]            # + h5py
pip install sweep-io[torch]           # + torch (Dataset + CUDAPrefetcher)
pip install sweep-io[segy,hdf5,torch]

Or with the rest of the sweep stack: pip install sweepx.

Quick example — fast SEG-Y reads

from sweep_io.segy import MultiFileSEGYReader

reader = MultiFileSEGYReader(["line_001.sgy", "line_002.sgy"])
print(reader.n_samples, reader.dt, reader.sample_format)

# Pre-built index: which (file_id, byte_offset) belongs to which shot.
file_ids, byte_offsets = my_shot_index[shot_idx]
traces = reader.read_traces(file_ids, byte_offsets, coalesce_gap=4096)
# -> (n_receivers, n_samples) float32, in caller order

SEGYReader uses mmap + sorted-offset coalescing so a batch of random-looking offsets turns into a small number of large sequential reads — typical 5-10× speedup on Lustre vs. one pread per trace.

Quick example — prefetched FWI loop

from sweep_io.prefetch import Prefetcher

def load_shot(i):
    return reader.read_traces(*my_index[i])

with Prefetcher((load_shot(i) for i in range(n_shots)), queue_depth=2) as pf:
    for shot in pf:
        # I/O for the next shot happens in a background thread
        # while we run forward + backward + optimizer.step() here.
        pred = solver(wavelet, sources, receivers, models=[vp])
        loss = misfit(pred, shot)
        loss.backward()
        optim.step(); optim.zero_grad()

Want parallel reads (many independent files, NVMe, Lustre wide stripe)? Use ThreadPoolPrefetcher:

from sweep_io.prefetch import ThreadPoolPrefetcher

with ThreadPoolPrefetcher(load_shot, range(n_shots),
                          num_workers=4, queue_depth=4) as pf:
    for shot in pf:
        ...

Quick example — GPU pipeline with pinned memory + side stream

For multi-GB-per-batch workloads the host→device transfer is itself a bottleneck. CUDAPrefetcher overlaps it with both I/O and compute:

from sweep_io.cuda_prefetch import CUDAPrefetcher

def load_shot(i):
    arr = reader.read_traces(*my_index[i])    # CPU numpy
    return {"obs": arr, "shot_index": i}

with CUDAPrefetcher((load_shot(i) for i in range(N)),
                    device="cuda:0", queue_depth=2) as pf:
    for sample in pf:
        # sample["obs"] is already on cuda:0; the H2D was issued on a
        # side stream, and the current stream waits on its event before
        # the next kernel touches it.
        loss = forward_and_loss(sample["obs"])
        loss.backward()
        ...

Quick example — torch Dataset with prefetch baked in

from sweep_io.datasets import ShotGatherDataset

ds = ShotGatherDataset(geometry, obs=load_shot)   # callable for OOC
for sample in ds.iter_prefetched(queue_depth=2, num_workers=2):
    pred = solver(sample["sources"], sample["receivers"], ...)
    ...

Demo

examples/prefetch_demo.py writes a few synthetic SEG-Y files and benchmarks blocking vs. prefetched reads:

$ python examples/prefetch_demo.py
[blocking ] total   751.6 ms   io_wait   107.6 ms  compute 640.0 ms
[prefetch ] total   652.8 ms   io_wait     7.4 ms  compute 640.0 ms
speedup ≈ 1.15x; io_wait dropped from 107.6 ms to 7.4 ms

(Real FWI numbers depend on shot size and storage — the I/O wait reduction is what matters; it's the wall-clock you get back when compute would otherwise be twiddling its thumbs.)

Design principles

  • Framework-agnostic core. numpy is the only required dep. segyio, h5py, torch are optional extras and lazy-imported.
  • Byte-offset over headers. The hot path takes a (file_id, byte_offset) catalog you build once and reuse forever — no per-iteration header parse, no Python loop per trace.
  • Sort-and-coalesce reads. Adjacent reads merge into one pread; random reads become sequential. Bandwidth, not seek time, dominates.
  • Overlap I/O with compute. Prefetchers run a worker that reads ahead by queue_depth items; consumer's next() only blocks if the worker hasn't caught up. Pair with CUDAPrefetcher for GPU pipelines.
  • Thread-safe readers. SEGYReader uses pread / mmap-views, so one reader shared across N prefetch threads is safe.

Caveats

  • SEGYReader assumes fixed-length traces (all traces have the same n_samples). Variable-length SEG-Y is rare in production datasets but not supported here.
  • mmap_mode=True (default) can misbehave on flaky network filesystems (SIGBUS if a node disappears mid-read). Pass mmap_mode=False to fall back to pread.
  • The Prefetcher worker is a thread, not a process — fine for I/O-bound work (most of our hot path) but not for CPU-bound transforms that don't release the GIL. For heavy decoding, do it inside numpy / C extensions.

License

MIT.

Metadata

Release files for sweep-io 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sweep-io 0.1.1
File Size Uploaded
sweep_io-0.1.1.tar.gz 100.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sweep-io 0.1.1
File Interpreter ABI Platform
sweep_io-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 180.8 kB

Release files / sweep_io-0.1.1.tar.gz

Download URL sweep_io-0.1.1.tar.gz
Size 100.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3da73399d66f7dd7a7624cd983b45f4d02ff925d37c0a725a3c59b34abbb4e08
BLAKE2b-256 checksum
How to use checksums
83f215e1158f403b34dd673fa0c2c2754724066717e80936c632351e40271fe8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.5

Release files / sweep_io-0.1.1-py3-none-any.whl

Download URL sweep_io-0.1.1-py3-none-any.whl
Size 79.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7e8c04e2544d8d8b35cefd5a14666fb9336c7682fc53d7452a7d6af97593c391
BLAKE2b-256 checksum
How to use checksums
99f60d5898578a61a8fe00df7f5e78b63550da9b0a31594d3605ebdcfb716b1c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.5

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page