Large-scale 3D velocity models for deep-learning full waveform inversion (FWI) and other seismic processing workflows.
GeoFWI3D provides many synthetic 3D Earth models, each stored as raw float32 (little-endian) binaries. Per model you get:
| File | Contents |
|---|---|
vp3d.bin |
P-wave velocity |
image3d.bin |
Synthetic p-reflectivity |
rgt3d.bin |
Relative geologic time (RGT) |
fault3d.bin |
Fault index mask |
Each volume has shape 96 × 96 × 96 in (X, Y, Z) order. On disk the layout is contiguous C-order over those dimensions.
Compressed archives are hosted on Box:
Each models_batch_*.tar.gz contains 1000 models. Place the archive files in the same directory as this repository, then extract.
From the repository root:
./extract_models.shThis creates allmodels/ and extracts every models_batch_*.tar.gz into it.
After extraction, models look like:
allmodels/
├── model_0000/
│ ├── image3d.bin
│ ├── vp3d.bin
│ ├── rgt3d.bin
│ └── fault3d.bin
├── model_0001/
│ └── ...
└── ...
Folder names use four-digit zero padding: model_0000, model_0001, …
- Install Python dependencies used by the example notebook: NumPy, Matplotlib, and scikit-image (for
marching_cubes). - Run Jupyter with working directory
quick_start/sofrom plotting import plot3dworks. Openread_data.ipynb: it definesread_modelsandplot_all_models, setsdata_root/model_folders/shape, and walks through loading and plotting.
The repository includes parameters.csv, with one row per model and a key sample_index column matching folder names like model_{sample_index:04d}.
Useful label columns for categorization:
yn_fault: 1 if model contains faultsyn_salt: 1 if model contains a salt body
Example (from quick_start/read_data.ipynb) to build category index lists and select models:
import csv
from pathlib import Path
with Path("../parameters.csv").open(newline="") as f:
rows = list(csv.DictReader(f))
for r in rows:
r["sample_index"] = int(r["sample_index"])
r["yn_fault"] = int(float(r["yn_fault"]))
r["yn_salt"] = int(float(r["yn_salt"]))
def select_indices(rows, **flag_equals):
return [
r["sample_index"]
for r in rows
if all(int(r[k]) == int(v) for k, v in flag_equals.items())
]
layered_indices = select_indices(rows, yn_fault=0, yn_salt=0)
fault_indices = select_indices(rows, yn_fault=1, yn_salt=0)
salt_indices = select_indices(rows, yn_salt=1, yn_fault=0)
fault_and_salt_indices = select_indices(rows, yn_fault=1, yn_salt=1)
idx = salt_indices[0]
image, vp, rgt, fault, salt = read_models(data_root, model_folders, idx)plot_all_models(
data_root,
model_folders,
9177,
"Salt model with faults",
save_path="../gallery/salt_fault_model.png"
)fault3d.bin stores a fault index per voxel. To plot a single fault (here index 5):
image, vp, rgt, fault, salt = read_models(data_root, model_folders, 9177)
fault_mask = fault.T == 5
plot3d(
fault_mask.astype(np.float32),
cmap='Reds',
frames=[45, 45, 46],
ifnewfig=True,
showf=False,
close=False,
ifinside=False,
figname="../gallery/fault_mask_5.png"
)
plt.show()Salt bodies have RGT = 0 in rgt3d.bin. Mask and plot with:
salt_mask = rgt == 0
salt_mask = salt_mask.astype(np.float32)
plot3d(
salt_mask.T,
cmap='Reds',
frames=[45, 45, 46],
ifnewfig=True,
figname="../gallery/salt_mask.png"
)
plt.show()Plotting helpers in quick_start/plotting.py are adapted from pyseistr (https://github.com/aaspip/pyseistr) utilities.




