Simple & fast IO for SEG-Y files
—
Access to binary header fields and trace header fields using meaningful enumeration constants instead of raw byte offsets. Headers contain essential metadata about SEG-Y file structure and individual trace properties.
Access to file-level binary header fields that describe the overall file structure, sample format, and acquisition parameters.
class BinField:
"""Binary header field byte offset constants."""
# Job and line identification
JobID = 3201 # Job identification number
LineNumber = 3205 # Line number (for 2D), reel number (for 3D)
ReelNumber = 3209 # Reel number
# Trace counts and geometry
Traces = 3213 # Number of data traces per ensemble
AuxTraces = 3215 # Number of auxiliary traces per ensemble
EnsembleFold = 3227 # Ensemble fold
# Sample format and timing
Interval = 3217 # Sample interval in microseconds
IntervalOriginal = 3219 # Sample interval original recording
Samples = 3221 # Number of samples per data trace
SamplesOriginal = 3223 # Number of samples original recording
Format = 3225 # Data sample format code
# Extended fields for large files
ExtTraces = 3261 # Extended number of data traces per ensemble
ExtAuxTraces = 3265 # Extended number of auxiliary traces per ensemble
ExtSamples = 3269 # Extended number of samples per data trace
ExtSamplesOriginal = 3289 # Extended number of samples original recording
ExtEnsembleFold = 3293 # Extended ensemble fold
# SEG-Y revision and format
SEGYRevision = 3501 # SEG Y format revision number
SEGYRevisionMinor = 3502 # SEG Y format revision minor
TraceFlag = 3503 # Fixed length trace flag
ExtendedHeaders = 3505 # Number of 3200-byte extended textual headers
# Processing and sorting
SortingCode = 3229 # Trace sorting code
VerticalSum = 3231 # Vertical sum code
CorrelatedTraces = 3249 # Correlated data traces
BinaryGainRecovery = 3251 # Binary gain recovered
AmplitudeRecovery = 3253 # Amplitude recovery method
MeasurementSystem = 3255 # Measurement system
# Sweep parameters (for vibroseis)
SweepFrequencyStart = 3233 # Sweep frequency at start (Hz)
SweepFrequencyEnd = 3235 # Sweep frequency at end (Hz)
SweepLength = 3237 # Sweep length (ms)
Sweep = 3239 # Sweep type code
SweepChannel = 3241 # Trace number of sweep channel
SweepTaperStart = 3243 # Sweep trace taper length at start (ms)
SweepTaperEnd = 3245 # Sweep trace taper length at end (ms)
Taper = 3247 # Taper type
# Signal polarity
ImpulseSignalPolarity = 3257 # Impulse signal polarity
VibratoryPolarity = 3259 # Vibratory polarity codeUsage Example:
with segyio.open('data.sgy') as f:
# Read binary header fields
sample_count = f.bin[segyio.BinField.Samples]
sample_rate = f.bin[segyio.BinField.Interval]
data_format = f.bin[segyio.BinField.Format]
trace_count = f.bin[segyio.BinField.Traces]
print(f"File contains {trace_count} traces")
print(f"Sample rate: {sample_rate} microseconds")
print(f"Samples per trace: {sample_count}")
print(f"Data format code: {data_format}")
# Modify binary header (if file opened for writing)
if not f.readonly:
f.bin[segyio.BinField.JobID] = 12345
f.bin[segyio.BinField.LineNumber] = 100Access to trace-level header fields that contain positioning information, acquisition parameters, and trace-specific metadata.
class TraceField:
"""Trace header field byte offset constants."""
# Trace sequencing
TRACE_SEQUENCE_LINE = 1 # Trace sequence number within line
TRACE_SEQUENCE_FILE = 5 # Trace sequence number within file
FieldRecord = 9 # Original field record number
TraceNumber = 13 # Trace number within field record
EnergySourcePoint = 17 # Energy source point number
# CDP/CMP information
CDP = 21 # CDP ensemble number
CDP_TRACE = 25 # Trace number within CDP ensemble
CDP_X = 181 # CDP X coordinate
CDP_Y = 185 # CDP Y coordinate
# 3D geometry
INLINE_3D = 189 # Inline number (3D surveys)
CROSSLINE_3D = 193 # Crossline number (3D surveys)
# Source and receiver positions
SourceX = 73 # Source coordinate X
SourceY = 77 # Source coordinate Y
GroupX = 81 # Group coordinate X
GroupY = 85 # Group coordinate Y
offset = 37 # Distance from source to receiver group
# Timing and sampling
TRACE_SAMPLE_COUNT = 115 # Number of samples in this trace
TRACE_SAMPLE_INTERVAL = 117 # Sample interval for this trace (microseconds)
DelayRecordingTime = 109 # Delay recording time (ms)
# Trace identification and type
TraceIdentificationCode = 29 # Trace identification code
# Elevations and corrections
SourceElevation = 45 # Source elevation
GroupElevation = 41 # Receiver group elevation
SourceDepth = 49 # Source depth below surface
GroupWaterDepth = 61 # Water depth at receiver group
SourceWaterDepth = 57 # Water depth at source
# Scaling factors
ElevationScalar = 69 # Elevation scalar
CoordinateScalar = 71 # Coordinate scalar
# Additional fields available (80+ total constants)
# Including: timing, filtering, processing, measurement units,
# transduction constants, and extended 3D geometry fieldsUsage Example:
with segyio.open('3d_data.sgy') as f:
# Read trace header for first trace
header = f.header[0]
inline = header[segyio.TraceField.INLINE_3D]
crossline = header[segyio.TraceField.CROSSLINE_3D]
cdp = header[segyio.TraceField.CDP]
print(f"First trace: IL={inline}, XL={crossline}, CDP={cdp}")
# Read multiple trace headers
headers = f.header[0:10]
for i, hdr in enumerate(headers):
il = hdr[segyio.TraceField.INLINE_3D]
xl = hdr[segyio.TraceField.CROSSLINE_3D]
print(f"Trace {i}: IL={il}, XL={xl}")
# Read coordinates
source_x = header[segyio.TraceField.SourceX]
source_y = header[segyio.TraceField.SourceY]
cdp_x = header[segyio.TraceField.CDP_X]
cdp_y = header[segyio.TraceField.CDP_Y]
# Apply coordinate scaling if needed
coord_scalar = header[segyio.TraceField.CoordinateScalar]
if coord_scalar < 0:
scale_factor = -1.0 / coord_scalar
else:
scale_factor = coord_scalar
actual_x = cdp_x * scale_factor
actual_y = cdp_y * scale_factorEnumeration of data sample format codes used in the binary header Format field.
class SegySampleFormat:
"""Data sample format codes."""
IBM_FLOAT_4_BYTE = 1 # 4-byte IBM floating point (most common legacy)
SIGNED_INTEGER_4_BYTE = 2 # 4-byte two's complement integer
SIGNED_SHORT_2_BYTE = 3 # 2-byte two's complement integer
FIXED_POINT_WITH_GAIN_4_BYTE = 4 # 4-byte fixed-point with gain
IEEE_FLOAT_4_BYTE = 5 # 4-byte IEEE floating point (most common modern)
IEEE_FLOAT_8_BYTE = 6 # 8-byte IEEE floating point
SIGNED_CHAR_3_BYTE = 7 # 3-byte two's complement integer
SIGNED_CHAR_1_BYTE = 8 # 1-byte two's complement integer
SIGNED_INTEGER_8_BYTE = 9 # 8-byte two's complement integer
UNSIGNED_INTEGER_4_BYTE = 10 # 4-byte unsigned integer
UNSIGNED_SHORT_2_BYTE = 11 # 2-byte unsigned integer
UNSIGNED_INTEGER_8_BYTE = 12 # 8-byte unsigned integer
UNSIGNED_INTEGER_3_BYTE = 15 # 3-byte unsigned integer
UNSIGNED_CHAR_1_BYTE = 16 # 1-byte unsigned integerEnumeration of trace sorting format codes used in the binary header SortingCode field.
class TraceSortingFormat:
"""Trace sorting format codes."""
UNKNOWN_SORTING = 0 # Unknown or unsorted
CROSSLINE_SORTING = 1 # Crossline sorted (fast crossline, slow inline)
INLINE_SORTING = 2 # Inline sorted (fast inline, slow crossline)Usage Example:
with segyio.open('data.sgy') as f:
format_code = f.bin[segyio.BinField.Format]
if format_code == segyio.SegySampleFormat.IBM_FLOAT_4_BYTE:
print("IBM floating point data")
elif format_code == segyio.SegySampleFormat.IEEE_FLOAT_4_BYTE:
print("IEEE floating point data")
sorting = f.bin[segyio.BinField.SortingCode]
if sorting == segyio.TraceSortingFormat.INLINE_SORTING:
print("File is inline sorted")
elif sorting == segyio.TraceSortingFormat.CROSSLINE_SORTING:
print("File is crossline sorted")Access to EBCDIC textual headers containing human-readable file description and processing history.
with segyio.open('data.sgy') as f:
# Read main textual header (EBCDIC)
text_header = f.text[0]
print(text_header)
# Read extended textual headers (if present)
if f.ext_headers > 0:
for i in range(1, f.ext_headers + 1):
ext_header = f.text[i]
print(f"Extended header {i}:")
print(ext_header)def apply_coordinate_scaling(coordinate, scalar):
"""Apply SEG-Y coordinate scaling factor."""
if scalar == 0:
return coordinate
elif scalar < 0:
return coordinate / (-scalar)
else:
return coordinate * scalar
# Usage
with segyio.open('data.sgy') as f:
header = f.header[0]
cdp_x = header[segyio.TraceField.CDP_X]
cdp_y = header[segyio.TraceField.CDP_Y]
scalar = header[segyio.TraceField.CoordinateScalar]
actual_x = apply_coordinate_scaling(cdp_x, scalar)
actual_y = apply_coordinate_scaling(cdp_y, scalar)def analyze_geometry(filename):
"""Analyze SEG-Y file geometry from headers."""
with segyio.open(filename) as f:
# Get inline/crossline ranges
ilines = set()
xlines = set()
for i in range(min(1000, f.tracecount)): # Sample first 1000 traces
header = f.header[i]
ilines.add(header[segyio.TraceField.INLINE_3D])
xlines.add(header[segyio.TraceField.CROSSLINE_3D])
return {
'inline_range': (min(ilines), max(ilines)),
'crossline_range': (min(xlines), max(xlines)),
'inline_count': len(ilines),
'crossline_count': len(xlines)
}Install with Tessl CLI
npx tessl i tessl/pypi-segyio