Traces¶
Altay Sansal
Feb 12, 2026
5 min read
Defining a Trace¶
The TraceSpec is a way to define the structure of a seismic trace as stored in SEG-Y files. It is composed of Trace Header Specification and Trace Data Specification. This information is combined using the TraceSpec.
The TraceSpec has fields for trace header, optional extended trace header, and trace data definitions. We also provide an optional offset field to define the beginning byte-location of the traces within a binary file. Most of the time this field gets populated automatically.
A custom trace specification can be built programmatically following a simple
workflow. The same spec can be built from JSON as well. Navigate to
JSON Trace Specification below for that.
Trace Header Specification¶
Trace headers are defined using HeaderSpec. Each header field is a HeaderField. We have an example workflow here. You can see more examples in the Data Types documentation.
We first do the required imports and then define header fields. We don’t allow setting endianness for individual fields.
1
2from segy.schema import HeaderField
3
4trace_header_fields = [
5 HeaderField(name="inline", byte=189, format="int32"),
6 HeaderField(name="crossline", byte=193, format="int32"),
7]
Then we create HeaderSpec for trace headers. We know trace headers must be 240-bytes so we declare it. This will ensure we read/write with correct padding.
Note
Endianness can be set here but we don’t recommend it. By default it will take
the machine endianness. When the SegyFile is initialized it will
automatically set this to the correct value. By default its None.
1
2from segy.schema import HeaderSpec
3
4trace_header_spec = HeaderSpec(
5 fields=trace_header_fields,
6 item_size=240,
7)
Trace Data Specification¶
Trace data is described using TraceDataSpec. The data is mainly explained by its data format and number of samples.
Continuing our previous example, we build the trace data spec. We assume that samples
are encoded in ibm32 format. Endianness can’t be set here, because it is assigned
at TraceSpec level.
1
2from segy.schema import TraceDataSpec
3
4trace_data_spec = TraceDataSpec(
5 format="ibm32",
6 samples=360
7)
Trace Specification¶
Finally, since we have all components, we can create a trace specification.
1from segy.schema import TraceSpec
2
3trace_spec = TraceSpec(
4 header_spec=trace_header_spec,
5 data_spec=trace_data_spec,
6 offset=3600 # just an example of possible offset
7)
Note
Endianness can be set here but we don’t recommend it. By default it will take
the machine endianness. When the SegyFile is initialized it will
automatically set this to the correct value. By default its None.
If we look at the Numpy data type of the trace, we can see how it will be decoded from raw bytes:
1>>> trace_spec.dtype
2dtype([('header', {'names': ['inline', 'crossline'], 'formats': ['<i4', '<i4'], 'offsets': [188, 192], 'itemsize': 240}), ('data', '<u4', (360,))])
JSON Trace Specification¶
We can define the exact same trace specification above using JSON. This can either
be defined as a string or can be read from a file. Both will work. Let’s write
the JSON.
{
"headerSpec": {
"fields": [
{
"format": "int32",
"name": "inline",
"byte": 189
},
{
"format": "int32",
"name": "crossline",
"byte": 193
}
],
"itemSize": 240
},
"dataSpec": {
"format": "ibm32",
"samples": 360
},
"offset": 3600
}
Then if we have our JSON as a string in the variable json_str, we can generate
the same specification, with validation of all fields. If there are any errors in the
JSON, there will be a validation error raised.
1>>> trace_spec_from_json = TraceSpec.model_validate_json(json_str)
2>>> trace_spec_from_json == trace_spec
3True
Reference¶
- pydantic model segy.schema.TraceSpec¶
A spec class for a trace (header + data).
Show JSON schema
{ "title": "TraceSpec", "description": "A spec class for a trace (header + data).", "type": "object", "properties": { "header": { "$ref": "#/$defs/HeaderSpec", "description": "Trace header spec." }, "extHeader": { "anyOf": [ { "$ref": "#/$defs/HeaderSpec" }, { "type": "null" } ], "default": null, "description": "Extended trace header spec." }, "data": { "$ref": "#/$defs/TraceDataSpec", "description": "Trace data spec." }, "offset": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Starting offset of the trace.", "title": "Offset" }, "endianness": { "anyOf": [ { "$ref": "#/$defs/Endianness" }, { "type": "null" } ], "default": null, "description": "Endianness of traces and headers." }, "count": { "anyOf": [ { "minimum": 0, "type": "integer" }, { "type": "null" } ], "default": null, "description": "Number of traces.", "title": "Count" } }, "$defs": { "Endianness": { "description": "Enumeration class with three possible endianness values.\n\nAttributes:\n BIG: Big endian.\n LITTLE: Little endian.\n\nExamples:\n >>> endian = Endianness.BIG\n >>> print(endian.symbol)\n >", "enum": [ "big", "little" ], "title": "Endianness", "type": "string" }, "HeaderField": { "description": "A class representing header field spec.\n\nExamples:\n A named float starting at byte location 9:\n\n >>> field = HeaderField(\n >>> name=\"my_var\",\n >>> format=\"float32\",\n >>> byte=9,\n >>> )\n\n The name, byte, and offset fields will only be used if the structured\n field is used within the context of a :class:`HeaderSpec`. Offset is\n calculated automatically from byte location.\n\n >>> field.name\n my_var\n >>> field.byte\n 9\n >>> field.offset\n 8\n\n The `dtype` property is inherited from :class:`DataFormat`.\n\n >>> field.dtype\n dtype('float32')", "properties": { "name": { "description": "The short name of the field.", "title": "Name", "type": "string" }, "byte": { "description": "Field's start byte location.", "minimum": 1, "title": "Byte", "type": "integer" }, "format": { "$ref": "#/$defs/ScalarType", "description": "The data type of the field." } }, "required": [ "name", "byte", "format" ], "title": "HeaderField", "type": "object" }, "HeaderSpec": { "description": "A class representing a header specification.\n\nExamples:\n Let's build a header from scratch!\n\n We will define three fields with different names, data-types, and\n start byte locations.\n\n >>> field1 = HeaderField(\n >>> name=\"foo\",\n >>> format=\"int32\",\n >>> byte=1,\n >>> )\n >>> field2 = HeaderField(\n >>> name=\"bar\",\n >>> format=\"int16\",\n >>> byte=5,\n >>> )\n >>> field3 = HeaderField(\n >>> name=\"fizz\",\n >>> format=\"int32\",\n >>> byte=17,\n >>> )\n\n Note that the fields span the following byte ranges:\n\n * `field1` between bytes `[0, 4)`\n * `field2` between bytes `[4, 6)`\n * `field3` between bytes `[16, 20)`\n\n The gap between `field2` and `field3` will be padded with `void`. In\n this case we expect to see an item size of 20-bytes (total length of\n the header struct).\n\n >>> header = HeaderSpec(\n >>> fields=[field1, field2, field3],\n >>> )\n\n Now let's look at its data type:\n\n >>> header.dtype\n dtype({'names': ['foo', 'bar', 'fizz'], 'formats': ['<i4', '<i2', '<i4'], 'offsets': [0, 4, 16], 'itemsize': 20})\n\n If we wanted to pad the end of the struct (to fit a specific byte range),\n we would provide the item_size in the spec. If we set it to 30, this means\n that we padded the struct by 10 bytes at the end.\n\n >>> header = HeaderSpec(\n >>> fields=[field1, field2, field3],\n >>> item_size=30,\n >>> )\n\n Now let's look at its data type:\n\n >>> header.dtype\n dtype({'names': ['foo', 'bar', 'fizz'], 'formats': ['<i4', '<i2', '<i4'], 'offsets': [0, 4, 16], 'itemsize': 30})\n\n To see what's going under the hood, we can look at a lower level numpy\n description of the `dtype`. Here we observe all the gaps (void types).\n\n >>> header.dtype.descr\n [('foo', '<i4'), ('bar', '<i2'), ('', '|V10'), ('fizz', '<i4'), ('', '|V10')]", "properties": { "fields": { "description": "List containing multiple header field spec instances.", "items": { "$ref": "#/$defs/HeaderField" }, "title": "Fields", "type": "array" }, "itemSize": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Expected size of the struct.", "title": "Itemsize" }, "offset": { "anyOf": [ { "minimum": 0, "type": "integer" }, { "type": "null" } ], "default": null, "description": "Starting byte offset.", "title": "Offset" }, "endianness": { "anyOf": [ { "$ref": "#/$defs/Endianness" }, { "type": "null" } ], "default": null, "description": "Endianness of structured data type." } }, "required": [ "fields" ], "title": "HeaderSpec", "type": "object" }, "ScalarType": { "description": "A class representing scalar data types.", "enum": [ "ibm32", "int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8", "float64", "float32", "float16", "S8" ], "title": "ScalarType", "type": "string" }, "TraceDataSpec": { "description": "A spec class for trace data (samples).", "properties": { "format": { "$ref": "#/$defs/ScalarType", "description": "Format of trace samples." }, "samples": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Number of samples in trace. It can be variable, then it must be read from each trace header.", "title": "Samples" }, "interval": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Sample interval of traces", "title": "Interval" } }, "required": [ "format" ], "title": "TraceDataSpec", "type": "object" } }, "required": [ "header", "data" ] }
- field header: HeaderSpec [Required]¶
Trace header spec.
- field extHeader: HeaderSpec | None = None¶
Extended trace header spec.
- field data: TraceDataSpec [Required]¶
Trace data spec.
- field endianness: Endianness | None = None¶
Endianness of traces and headers.
- pydantic model segy.schema.TraceDataSpec¶
A spec class for trace data (samples).
Show JSON schema
{ "title": "TraceDataSpec", "description": "A spec class for trace data (samples).", "type": "object", "properties": { "format": { "$ref": "#/$defs/ScalarType", "description": "Format of trace samples." }, "samples": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Number of samples in trace. It can be variable, then it must be read from each trace header.", "title": "Samples" }, "interval": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "default": null, "description": "Sample interval of traces", "title": "Interval" } }, "$defs": { "ScalarType": { "description": "A class representing scalar data types.", "enum": [ "ibm32", "int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8", "float64", "float32", "float16", "S8" ], "title": "ScalarType", "type": "string" } }, "required": [ "format" ] }
- field format: ScalarType [Required]¶
Format of trace samples.