OBN Data Import

This guide covers the ObnReceiverGathers3D template for importing Ocean Bottom Node (OBN) seismic data into MDIO.

Template Overview

The ObnReceiverGathers3D template organizes data with the following dimensions:

Dimension

Description

component

Sensor component (e.g., 1=X, 2=Y, 3=Z, 4=Hydrophone)

receiver

Ocean bottom node receiver ID

shot_line

Shot line identifier

gun

Gun identifier for multi-gun sources

shot_index

Calculated dense index for shots (see Required Grid Overrides)

time/depth

Vertical sample axis

Coordinates

  • Logical coordinates: shot_point (original values), orig_field_record_num

  • Physical coordinates: group_coord_x, group_coord_y, source_coord_x, source_coord_y

Note

The shot_index dimension is calculated (0 to N-1) from shot_point values during ingestion. Original shot_point values are preserved as a coordinate indexed by (shot_line, gun, shot_index).

Required Grid Overrides

CalculateShotIndex (Required)

The CalculateShotIndex grid override is required for the ObnReceiverGathers3D template. It calculates the shot_index dimension from shot_point values. Without this override, the import will fail with an error:

Required computed fields [‘shot_index’] for template ObnReceiverGathers3D not found after grid overrides.

This override handles multi-gun acquisition where shot points are interleaved across guns, calculating a dense shot_index from sparse shot_point values:

Before (interleaved shot_point):
  Gun 1: 1, 3, 5, 7, ...
  Gun 2: 2, 4, 6, 8, ...

After (dense shot_index):
  Gun 1: 0, 1, 2, 3, ...
  Gun 2: 0, 1, 2, 3, ...

For ObnReceiverGathers3D, the override uses shot_line as the line field and requires shot_line, gun, and shot_point headers.

Special Behaviors

Component Synthesis

When the SEG-Y spec does not include a component field, MDIO automatically synthesizes it with value 1 for all traces. This allows single-component data (e.g., hydrophone-only) to use the same template without modification.

Note

A warning is logged when component is synthesized:

SEG-Y headers do not contain ‘component’ field required by template ‘ObnReceiverGathers3D’. Synthesizing ‘component’ dimension with constant value 1 for all traces.

Usage

Basic Import

 1from segy.schema import HeaderField
 2from segy.standards import get_segy_standard
 3
 4from mdio import segy_to_mdio
 5from mdio.builder.template_registry import get_template
 6
 7# Define SEG-Y header mapping
 8obn_headers = [
 9    HeaderField(name="orig_field_record_num", byte=9, format="int32"),
10    HeaderField(name="receiver", byte=13, format="int32"),
11    HeaderField(name="shot_point", byte=17, format="int32"),
12    HeaderField(name="shot_line", byte=133, format="int16"),
13    HeaderField(name="gun", byte=171, format="int16"),
14    HeaderField(name="component", byte=189, format="int16"),
15    HeaderField(name="coordinate_scalar", byte=71, format="int16"),
16    HeaderField(name="source_coord_x", byte=73, format="int32"),
17    HeaderField(name="source_coord_y", byte=77, format="int32"),
18    HeaderField(name="group_coord_x", byte=81, format="int32"),
19    HeaderField(name="group_coord_y", byte=85, format="int32"),
20]
21
22obn_spec = get_segy_standard(1.0).customize(trace_header_fields=obn_headers)
23
24segy_to_mdio(
25    input_path="obn_data.sgy",
26    output_path="obn_data.mdio",
27    segy_spec=obn_spec,
28    mdio_template=get_template("ObnReceiverGathers3D"),
29    grid_overrides={"CalculateShotIndex": True},
30    overwrite=True,
31)

Single-Component Data

For data without a component header field, simply omit it from the spec:

 1# Same as above, but without the component field
 2obn_headers = [
 3    HeaderField(name="orig_field_record_num", byte=9, format="int32"),
 4    HeaderField(name="receiver", byte=13, format="int32"),
 5    HeaderField(name="shot_point", byte=17, format="int32"),
 6    HeaderField(name="shot_line", byte=133, format="int16"),
 7    HeaderField(name="gun", byte=171, format="int16"),
 8    # component omitted - will be synthesized
 9    HeaderField(name="coordinate_scalar", byte=71, format="int16"),
10    HeaderField(name="source_coord_x", byte=73, format="int32"),
11    HeaderField(name="source_coord_y", byte=77, format="int32"),
12    HeaderField(name="group_coord_x", byte=81, format="int32"),
13    HeaderField(name="group_coord_y", byte=85, format="int32"),
14]

Exploring the Data

 1from mdio import open_mdio
 2
 3ds = open_mdio("obn_data.mdio")
 4
 5# View dimensions
 6print(ds.sizes)
 7# {'component': 4, 'receiver': 100, 'shot_line': 10, 'gun': 2, 'shot_index': 500, 'time': 2001}
 8
 9# Access original shot_point values (preserved as coordinate)
10print(ds["shot_point"].dims)   # ('shot_line', 'gun', 'shot_index')
11
12# Select a receiver gather
13receiver_gather = ds.sel(receiver=150, component=4)
14receiver_gather["amplitude"].plot()

Required Header Fields

Field

Required

Notes

receiver

Yes

shot_line

Yes

gun

Yes

shot_point

Yes

component

No

Synthesized with value 1 if missing

coordinate_scalar

Yes

source_coord_x

Yes

source_coord_y

Yes

group_coord_x

Yes

group_coord_y

Yes

orig_field_record_num

Yes

See Also