API reference¶
Generated from the source docstrings. Everything here is also importable from the
package root, e.g. from sweep_nn import VelocityINR.
Velocity networks¶
sweep_nn.velocity_inr.VelocityINR ¶
VelocityINR(
base_velocity: Tensor,
*,
vp_mean: float = 0.0,
vp_std: float = 50.0,
hidden_features: int = 64,
hidden_layers: int = 3,
first_omega0: float = 30.0,
hidden_omega0: float = 30.0,
use_bias: bool = False,
use_hash_encoding: bool = True,
hash_levels: int = 16,
hash_features_per_level: int = 2,
hash_log2_size: int = 15,
hash_base_resolution: int | list[int] = 4,
hash_finest_resolution: int | list[int] = 512,
hash_c2f: bool = False,
hash_c2f_base_levels: int = 2,
hash_c2f_ramp: str = "cosine",
hash_growing: bool = False,
hash_backend: str = "pytorch",
use_fourier_encoding: bool = False,
fourier_levels: int = 6,
fourier_include_input: bool = True,
direct_velocity: bool = False,
coord_min: float = 0.0,
coord_max: float = 1.0,
bounds: Tuple[float, float] | None = None,
water_mask: Tensor | None = None,
water_vp: float = 1500.0,
lateral_downsample: Tuple[int, int] | int = 1,
compile_render: bool = False
)
Bases: torch.nn.modules.module.Module
Hash-encoded SIREN representation of a 2-D or 3-D velocity field.
Parameters:
-
base_velocity(Tensor) –Tensor
(nz, nx)(2-D) or(nz, ny, nx)(3-D). Treated as a non-trainable buffer — the network learns the perturbation on top (delta mode) or replaces it entirely (direct_velocity=True). -
vp_mean(float, default:0.0) –Added to the scaled network output:
velocity = base + (mlp_out * vp_std + vp_mean). -
vp_std(float, default:50.0) –Scales the network output, so it sets the typical perturbation in m/s: the network's natural output range is ~[-1, 1], so
vp_std=50gives ±50 m/s typical updates. -
use_hash_encoding(bool, default:True) –Wrap coordinates with :class:
MultiResHashGridbefore the SIREN head. Required for high-frequency velocity detail; without it the SIREN must do all the spatial-frequency work alone (slower, less expressive). -
hash_levels(int, default:16) –Number of hash-grid levels. See :class:
MultiResHashGrid. -
hash_features_per_level(int, default:2) –Features stored per level.
-
hash_log2_size(int, default:15) –log2 of the hash-table size of each level.
-
hash_base_resolution(int | list[int], default:4) –Grid resolution of the coarsest level (one int, or one per axis).
-
hash_finest_resolution(int | list[int], default:512) –Grid resolution of the finest level (one int, or one per axis).
-
hash_c2f(bool, default:False) –If True, build a :class:
CoarseToFineHashGridinstead: only thehash_c2f_base_levelscoarsest levels are open at init, and the training loop drives the unfreeze schedule viaself.encoder.set_progress(...). Same hash hyperparameters. -
hash_c2f_base_levels(int, default:2) –Levels open at init when
hash_c2f=True. -
hash_c2f_ramp(str, default:'cosine') –Shape of the unfreeze ramp when
hash_c2f=True. -
hidden_features(int, default:64) –SIREN width. See :class:
SirenMLP. -
hidden_layers(int, default:3) –Number of hidden sine layers after the first one.
-
first_omega0(float, default:30.0) –Sine frequency of the first layer.
-
hidden_omega0(float, default:30.0) –Sine frequency of the hidden layers.
-
direct_velocity(bool, default:False) –If True, ignore the base and return
mlp_out * vp_std + vp_mean. Useful for from-scratch reconstruction. -
coord_min(float, default:0.0) –Lower end of the coordinate range. Coordinates span
[coord_min, coord_max), which must match the convention the hash encoder expects. -
coord_max(float, default:1.0) –Upper end of the coordinate range (exclusive).
-
bounds(Tuple[float, float] | None, default:None) –Optional
(vp_min, vp_max)clamp applied at render time. Set toNone(default) to let the caller clamp. -
water_mask(Tensor | None, default:None) –Optional boolean tensor with the SAME shape as
base_velocity. Voxels whereTrueare pinned towater_vpat render time — the SIREN's output for those cells is ignored entirely. This is the right tool for "I know the water column is 1500 m/s, do NOT let SIREN init noise contaminate it" cases: the SIREN at init has ~std=0.08 raw output, so withvp_std=500the water layer would otherwise sit at 1500±40 m/s of garbage from epoch 0. Because the rendered output doesn't depend on SIREN params at masked voxels, gradients there are exactly zero — equivalent to freezing those cells AND giving SIREN free model capacity to spend on the rest of the model. -
water_vp(float, default:1500.0) –Velocity in m/s used at water-mask voxels. Default
1500.0.
Notes
Multi-stage FWI usage: net = VelocityINR(init_vp_75m, vp_std=50.0, ...) # ... train at stage 0 ... net.update_base_velocity(init_vp_37p5m) # resample base, keep params # ... train at stage 1 ...
update_base_velocity ¶
Swap in a new base (possibly different shape); rebuild coords.
When the new base has a different shape than the old, any
previously installed water_mask becomes stale. Pass a
water_mask matched to new_base.shape to refresh; leave
None to clear the existing mask (and warn loudly that a
stale mask was dropped).
render_shape ¶
Render at an arbitrary grid shape (bilinear/trilinear-resample the base).
render_window ¶
Render a rectangular window on the base grid.
Bounds layout:
2-D: (z0, z1, x0, x1)
3-D: (z0, z1, y0, y1, x0, x1)
backward_velocity_gradient ¶
Back-propagate a full-grid velocity gradient row-by-row.
Use this when the full-grid render() + .backward() would OOM:
e.g. a 3-D model with millions of voxels and a deep SIREN. The
method renders one slab of rows at a time, calls backward()
on that slab with the corresponding slice of velocity_grad,
and accumulates gradients onto the trainable parameters without
ever holding the full graph in memory.
Parameters:
-
velocity_grad(Tensor) –Tensor with the same shape as :attr:
base_velocity. -
chunk_rows(int, default:64) –Rows along the slow axis (axis 0) per chunk. Smaller = less peak memory, more overhead. 64 is a sensible default for 2-D; for 3-D models start with 4-8.
sweep_nn.multi_param_inr.MultiParamINR ¶
MultiParamINR(
base_models: Sequence[Tensor],
*,
means: Sequence[float],
stds: Sequence[float],
bounds: Sequence[Tuple[float, float] | None],
water_mask: Tensor | None = None,
water_values: Sequence[float] | None = None,
hidden_features: int = 64,
hidden_layers: int = 3,
first_omega0: float = 30.0,
hidden_omega0: float = 30.0,
use_bias: bool = False,
use_hash_encoding: bool = True,
hash_levels: int = 16,
hash_features_per_level: int = 2,
hash_log2_size: int = 15,
hash_base_resolution: int | List[int] = 4,
hash_finest_resolution: int | List[int] = 512,
hash_c2f: bool = False,
hash_c2f_base_levels: int = 2,
hash_c2f_ramp: str = "cosine",
hash_growing: bool = False,
hash_backend: str = "pytorch",
direct_velocity: bool = False,
coord_min: float = 0.0,
coord_max: float = 1.0
)
Bases: torch.nn.modules.module.Module
Shared-trunk INR with one output channel per FWI model parameter.
Parameters:
-
base_models(Sequence[Tensor]) –List of
n_paramsinitial-model tensors, all the same shape ((nz, nx)or(nz, ny, nx)).base_models[0]is the primary parameter (vp). Each is kept as a (non-persistent) buffer; the channel rendersbase_i + delta_i. -
means(Sequence[float]) –Per-channel offset in
delta_i = raw_i * stds[i] + means[i]. Lengthn_params. -
stds(Sequence[float]) –Per-channel scale in the same affine, length
n_params. It is the per-parameter "scale" (its effective learning rate islr * stds[i]); pick it per parameter's magnitude (vp ~ 500, impedance z ~ 2). -
bounds(Sequence[Tuple[float, float] | None]) –Per-channel
(min, max)clamp, orNoneto leave a channel unbounded. Lengthn_params. -
water_mask(Tensor | None, default:None) –Optional shared boolean water mask (shape = model shape). Masked voxels of channel
iare pinned towater_values[i](gradient there is 0, so the SIREN never spends capacity on the water column). -
water_values(Sequence[float] | None, default:None) –Per-channel value at the masked voxels, length
n_params(e.g.[1500.0, 1.5]for vp and Gardner-water impedance z).
Notes
The remaining arguments mirror :class:VelocityINR (shared SIREN + hash
encoder hyperparameters).
base_velocity
property
¶
Primary-parameter (channel-0) base — mirrors VelocityINR.base_velocity.
update_base_models ¶
update_base_models(
new_bases: Sequence[Tensor],
water_mask: Tensor | None = None,
water_values: Sequence[float] | None = None,
) -> None
Swap in new per-channel bases (possibly a different grid) + rebuild coords — multi-parameter analogue of VelocityINR.update_base_velocity.
The shared encoder + SIREN parameters are KEPT (the whole point of
carrying the net across multiscale stages); only base_stack / coords /
water mask are refreshed. new_bases is one tensor per channel (same
order as construction), each resampled to the new grid. Pass a
water_mask matched to the new shape to refresh the water pin (a stale
mask on a shape change is dropped with a warning).
render_all ¶
Render every parameter -> (n_params, *shape) (channel 0 = vp).
chunk_rows bounds peak memory by rendering z-slabs (bit-identical,
pointwise). Under no_grad the caller controls the graph.
render_param ¶
Render parameter i alone -> *shape.
render ¶
Render the PRIMARY parameter (vp, channel 0) — VelocityINR-compatible.
render_window ¶
Render a rectangular window over ALL channels -> (n_params, *win).
Bounds: 2-D (z0, z1, x0, x1), 3-D (z0, z1, y0, y1, x0, x1) — the
N-channel analogue of VelocityINR.render_window, used by the DD tile
render. coords/base_stack may live on CPU for huge global grids; only
this window's slices move to the compute device.
backward_gradients ¶
Back-propagate a per-parameter gradient list onto the shared trunk.
grads[i] is dL/d(field_i) (same shape as the model). Renders one
z-slab of ALL channels at a time and backwards them together, so the
shared trunk accumulates every parameter's contribution while peak
memory stays O(chunk_rows) — the multi-parameter analogue of
VelocityINR.backward_velocity_gradient.
Encoders and SIREN¶
sweep_nn.hash_encoding.MultiResHashGrid ¶
MultiResHashGrid(
dim: int,
*,
n_levels: int = 16,
n_features_per_level: int = 2,
log2_hashmap_size: int = 15,
base_resolution: int | List[int] = 2,
finest_resolution: int | List[int] = 16,
dtype: dtype = torch.float32,
backend: str = "pytorch"
)
Bases: torch.nn.modules.module.Module
Anisotropic multi-resolution hash-grid encoder.
forward ¶
Encode normalized coords (..., dim) -> features (..., L*F).
sweep_nn.siren.SirenMLP ¶
SirenMLP(
in_features: int,
out_features: int = 1,
*,
hidden_features: int = 64,
hidden_layers: int = 3,
first_omega0: float = 30.0,
hidden_omega0: float = 30.0,
bias: bool = False
)
Bases: torch.nn.modules.module.Module
Generic SIREN MLP: (..., in_features) -> (..., out_features).
Unlike :class:SIREN (which caches a coord grid and ties to an output
shape), SirenMLP is a pure functional MLP. It is the building block
used by :class:~sweep_nn.velocity_inr.VelocityINR (where the input
comes from a hash encoder) and :class:~sweep_nn.wavelet.SirenWavelet.
First layer uses first_omega0; hidden/output layers use
hidden_omega0. The final layer is a plain nn.Linear (no sin),
SIREN-style.
sweep_nn.siren.SIREN ¶
SIREN(
out_shape: Tuple[int, ...],
*,
hidden_features: int = 128,
hidden_layers: int = 4,
w0: float = 30.0,
vp_min: float = 1500.0,
vp_max: float = 4500.0,
squash: str = "tanh"
)
Bases: sweep_nn.reparam.Reparameterizer
SIREN reparameterizer.
Parameters:
-
out_shape(Tuple[int, ...]) –(nz, nx)2-D or(nz, ny, nx)3-D output grid. -
hidden_features(int, default:128) –Width of the MLP.
-
hidden_layers(int, default:4) –Depth of the MLP.
-
w0(float, default:30.0) –Initial-layer frequency. The paper recommends 30 for image-scale tasks; higher values fit higher spatial frequencies at the cost of slower convergence.
sweep_nn.siren.SineLayer ¶
SineLayer(
in_features: int,
out_features: int,
*,
w0: float = 30.0,
is_first: bool = False,
bias: bool = True
)
Bases: torch.nn.modules.module.Module
Linear + sin(w0 * x), with paper-faithful initialization.
First-layer init uses U(-1/in, 1/in); hidden/output layers use
U(-sqrt(6/in)/w0, +sqrt(6/in)/w0) (Sitzmann et al. 2020 sec. 3.2).
Priors¶
sweep_nn.priors.TVPrior ¶
TVPrior(
*,
order: str = "first",
x_weight: float = 1.0,
z_weight: float = 1.0,
y_weight: float = 1.0,
velocity_scale_m_s: float = 1000.0
)
Bases: torch.nn.modules.module.Module
Total-variation-style smoothness penalty on a velocity volume.
Computes a derivative-L2 (Sobolev) penalty along the lateral (x and, in 3-D, y) and depth (z) axes. Supports first-order, second-order, or both. Used as a soft regularizer in the FWI loss::
L_total = L_data + weight * TVPrior(...)(velocity)
The velocity tensor is internally normalized by velocity_scale_m_s
so the weight stays interpretable across surveys with different vp
magnitudes (m/s).
In 2-D the model is (nz, nx); in 3-D it is (nz, ny, nx). The
depth axis is always axis 0.
Parameters:
-
order(str, default:'first') –"first"(default) — sum of squared first differences."second"— sum of squared second differences (curvature)."both"/"mixed"— both first and second. -
x_weight(float, default:1.0) –Multiplier for the lateral (x) differences.
-
z_weight(float, default:1.0) –Multiplier for the depth (z) differences.
-
y_weight(float, default:1.0) –Multiplier for the y differences; ignored on 2-D inputs.
-
velocity_scale_m_s(float, default:1000.0) –Normalization for vp before differentiation (m/s). Default
1000.0.
sweep_nn.priors.SeabedFreezeMask ¶
Mask that zeros gradients above the seabed (water column).
For marine surveys the water-column vp is essentially constant at
~1500 m/s and well known a priori — letting FWI update those cells
introduces noise that doesn't help the inversion. Multiplying the
gradient by mask = (depth_idx >= floor(seabed_idx)) before the
optimizer step keeps the water column frozen at its initial value
while letting everything below the seabed update normally.
Parameters:
-
seabed_depth_m(Tensor | ndarray) –(ny, nx)(3-D) or(nx,)(2-D) per-trace seabed depths in meters from the model's top edge (z = 0). -
dz_m(float) –Grid spacing along the depth axis (m).
-
buffer_cells(int, default:0) –Optional integer pad — keep the first
buffer_cellsrows below the seabed also frozen. Useful when the wavelet has a non-zero rise time and the seabed reflection straddles a few cells.
Use
Build the mask once, store on the optimizer's device, and call
apply_to(grad) (in-place) after backward and before optim.step.
The mask broadcasts: a 2-D (nx,) seabed against a 2-D (nz, nx)
vp; a 2-D (ny, nx) seabed against a 3-D (nz, ny, nx) vp.
sweep_nn.diffusion.prior.DiffusionVelocityPrior ¶
DiffusionVelocityPrior(
ckpt_path: str,
device: str = "cuda",
mode: str = "patch",
strength: float = 0.3,
ddim_steps: int = 10,
patch: int = 64,
stride: int = 32,
vmin: float | None = None,
vmax: float | None = None,
use_ema: bool = True,
)
red_loss ¶
RED term computed in NORMALISED [-1,1] space so its magnitude is O(1) and comparable to a normalised data misfit.
L = 0.5 * mean((x_norm(vp) - D(vp).detach())^2), with x_norm = to_norm(vp) differentiable in vp (linear in-range), so grad_vp carries the correct 2/(vmax-vmin) chain-rule factor automatically.
residual ¶
vp - D(vp) in physical units (the raw prior descent direction).
sds_loss ¶
Surrogate whose grad w.r.t. vp is the SDS prior gradient (score-matching distillation of the diffusion model into whatever produces vp — pixels or an INR). Computed in normalised space; magnitude O(1).
Other¶
sweep_nn.wavelet.SirenWavelet ¶
SirenWavelet(
nt: int,
*,
hidden_features: int = 64,
hidden_layers: int = 3,
first_omega0: float = 30.0,
hidden_omega0: float = 30.0,
bias: bool = True
)
Bases: torch.nn.modules.module.Module
1-D SIREN parameterization of a time-domain source wavelet.
Parameters:
-
nt(int) –Number of time samples in the output wavelet.
-
hidden_features(int, default:64) –SIREN width. See :class:
SirenMLP. -
hidden_layers(int, default:3) –Number of hidden sine layers after the first one.
-
first_omega0(float, default:30.0) –Sine frequency of the first layer.
-
hidden_omega0(float, default:30.0) –Sine frequency of the hidden layers.
-
bias(bool, default:True) –Per the docstring: keep this True.
Falseis exposed only for completeness (e.g. fitting an explicitly odd wavelet).
sweep_nn.dip.DIPReparam ¶
DIPReparam(
out_shape: Tuple[int, int],
*,
latent_channels: int = 8,
base_ch: int = 32,
depth: int = 4,
vp_min: float = 1500.0,
vp_max: float = 4500.0,
squash: str = "tanh"
)
Bases: sweep_nn.reparam.Reparameterizer
Deep Image Prior reparameterizer (2-D).
Parameters:
-
out_shape(Tuple[int, int]) –(nz, nx). -
latent_channels(int, default:8) –Number of channels in the fixed input noise.
-
base_ch(int, default:32) –U-Net width: channels of the first level.
-
depth(int, default:4) –U-Net depth: number of levels.
sweep_nn.reparam.Reparameterizer ¶
Reparameterizer(
out_shape: Tuple[int, ...],
*,
vp_min: float = 1500.0,
vp_max: float = 4500.0,
squash: str = "tanh"
)
Bases: torch.nn.modules.module.Module
Abstract base: net() -> vp_tensor in physical units.
Subclasses implement :meth:_raw_forward, which must return a tensor
with shape out_shape whose values lie roughly in [-1, 1] (or
any range — see :meth:_to_physical).
Parameters:
-
out_shape(Tuple[int, ...]) –Spatial shape of the velocity model, e.g.
(nz, nx)for 2-D. -
vp_min(float, default:1500.0) –Lower end of the physical-unit range.
-
vp_max(float, default:4500.0) –Upper end. The raw output is rescaled and (by default, when
squash="tanh") tanh-squashed to live in[vp_min, vp_max]. -
squash(str, default:'tanh') –How the raw output is mapped to
[vp_min, vp_max]: -"tanh"—vp_min + (vp_max-vp_min) * 0.5*(tanh(raw)+1)-"sigmoid"—vp_min + (vp_max-vp_min) * sigmoid(raw)-"linear"— no squashing; raw values used directly (loss must enforce bounds).