Input/Output

For reading and writing SEG-Y data, JUDI uses the SegyIO.jl package. JUDI supports reading SEG-Y from disk into memory, as well as working with out-of-core (OOC) data containers. In the latter case, judiVectors contain look-up tables that allow accessing the underlying data in constant time.

Reading SEG-Y files into memory

To read a single SEG-Y file into memory, use the segy_read function:

using SegyIO

block = segy_read("data.segy")

From a SegyIO data block, you can create an in-core judiVector, as well as a Geometry object for the source:

# judiVector for observed data
d_obs = judiVector(block; segy_depth_key="RecGroupElevation")

# Source geometry
src_geometry = Geometry(block; key="source", segy_depth_key="SourceDepth")

The optional keyword segy_depth_key specifies which SEG-Y header stores the depth coordinate. After reading a block, you can check block.traceheaders to see which trace headers are set and where to find the depth coordinates for sources or receivers.

The d_obs vector constains the receiver geometry in d_obs.geometry, so there is no need to set up a separate geometry object manually. However, in principle we can set up a receiver Geometry object as follows:

rec_geometry = Geometry(block; key="receiver", segy_depth_key="RecGroupElevation")

Writing SEG-Y files

To write a judiVector as a SEG-Y file, we need a judiVector containing the receiver data and geometry, as well as a judiVector with the source coordinates. From the judiVectors, we first create a SegyIO block:

block = judiVector_to_SeisBlock(d_obs, q)

where d_obs and q are judiVectors for receiver and source data respectively. To save only the source q, we can do

block = src_to_SeisBlock(q)

Next, we can write a SEG-Y file from a SegyIO block:

segy_write("new_file.segy", block)  # writes a SEG-Y file called new_file.segy

Reading out-of-core SEG-Y files

For SEG-Y files that do not fit into memory, JUDI provides the possibility to work with OOC data containers. First, SegyIO scans also available files and then creates a lookup table, including a summary of the most important SEG-Y header values. See SegyIO's documentation for more information.

First we provide the path to the directory that we want to scan, as well as a string that appears in all the files we want to scan. For example, here we want to scan all files that contain the string "bp_observed_data". The third argument is a list of SEG-Y headers for which we create a summary. For creating OOC judiVectors, always include the "GroupX", "GroupY" and "dt" keyworkds, as well as the keywords that carry the source and receiver depth coordinates:

# Specify direcotry to scan
path_to_data = "/home/username/data_directory/"

# Scan files in given directory and create OOC data container
container = segy_scan(path_to_data, "bp_observed_data", ["GroupX", "GroupY", 
    "RecGroupElevation", "SourceDepth", "dt"])

Depending of the number and size of the underlying files, this process can take multiple hours, but it only has to be executed once! Furthermore, parallel scanning is supported as well.

Once we have scanned all files in the directory, we can create an OOC judiVector and source Geometry object as follows:

# Create OOC judiVector
d_obs = judiVector(container; segy_depth_key="RecGroupElevation")

# Create OOC source geometry object
src_geometry = Geometry(container; key="source", segy_depth_key="SourceDepth")

Reading and writing velocity models

JUDI does not require velocity models to be read or saved in any specific format. Any file format that allows reading the velocity model as a two or three-dimensional Julia array will work.

In our examples, we often use the JLD or HDF5 packages to read/write velocity models and the corresponing meta data (i.e. grid spacings and origins). If your model is a SEG-Y file, use the segy_read function from SegyIO as shown above.

  • Create an example model to write and read:
n = (120, 100)
d = (10.0, 10.0)
o = (0.0, 0.0)
v = ones(Float32, n) .* 1.5f0
m = 1f0 ./ v.^2
  • Write a model as a .jld file:
using JLD

save("my_model.jld", "n", n, "d", d, "o", o, "m", m)
  • Read a model from a .jld file:
# Returns a Julia dictionary
M = load("my_model.jld")

n = M["n"]
d = M["d"]
o = M["o"]
m = M["m"]

# Set up a Model object
model = Model(n, d, o, m)