sixty-north / segpy

A Python package for reading and writing SEG Y files.
Other
99 stars 54 forks source link

Unable to read shot_gather.sgy file with error: ValueError: Assigned value 43690 for num_samples #92

Closed noppGithub closed 4 years ago

noppGithub commented 4 years ago

@rob-smallshire Please accept my apology if my question annoys you. I have read your guide in #87 and try to make use of custom_header.py but can't make it. I'm trying to read a shot-gather.sgy file with the following script. Could you please guide me on which number to be replaced.

Thank you in advance

from segpy.binary_reel_header import BinaryReelHeader
from segpy.datatypes import SegYType
from segpy.field_types import IntFieldMeta
from segpy.header import field
from segpy.reader import create_reader

# try to solve error below
# ValueError: Assigned value 43690 for num_samples attribute must be convertible to NNInt16: NNInt16 value 43690 outside range 0 to 32767
# read sample file from: https://github.com/sixty-north/segpy/blob/master/examples/custom_header.py

# Standard SEG-Y does not support 16-bit unsigned integer values in headers.
# This section customises SEG-Y to support them.
class UInt16(int,
            metaclass=IntFieldMeta,
            min_value=0,       # Use the full-range for unsigned
            max_value=65535,   # 16-bit integers
            seg_y_type=SegYType.NNINT16):   # The underlying NNINT16 type is actually read as an unsigned type.
    """16-bit unsigned integer."""
    pass

# Subclass the standard reel header to specialize one of its fields to have a type of UInt16.
class CustomBinaryReelHeader(BinaryReelHeader):
    num_samples = field(
        UInt16, offset=3221, default=0, documentation=
        """Number of samples per data trace. Mandatory for all types of data.
        Note: The sample interval and number of samples in the Binary File Header should be for the primary set of
        seismic data traces in the file."""
    )

# ============================================= RUN below =============================================
'''
The way I tried
- Changed `default` variable of class `CustomBinaryReelHeader` to my value(43690): Failed
- Changed `endian='<'`, got similar error with different value(59395)
'''
with open('./file/shot-gather.sgy', 'rb') as segy_in_file:
    # The seg_y_dataset is a lazy-reader, so keep the file open throughout.
    # seg_y_dataset = create_reader(segy_in_file, endian='<')  # Non-standard Rev 1 little-endian
    seg_y_dataset = create_reader(segy_in_file, binary_reel_header_format=CustomBinaryReelHeader)
    print(seg_y_dataset.num_traces())
GGDRriedel commented 4 years ago

I had a similar problem. The cause was that whoever manipulated my SEGYs used different encoding when manipulating the binary header, so some are read in little endian, some in big.

You need to override every single binary header variable type that throws an error with one that fits. For that you need to look at the error message, find the corresponding python variable and override it.

For me it was for example

class CustomBinaryReelHeader(BinaryReelHeader):

    ensemble_fold = field(
        UInt16, offset=3227, default=0, documentation=
        """Number of samples per data trace. Mandatory for all types of data.
        Note: The sample interval and number of samples in the Binary File Header should be for the primary set of
        seismic data traces in the file."""
    )

    correlated_data_traces=field(
        UInt16, offset=3249, default=0, documentation=
        """Number of correlated data traces."""
    )

    binary_gain_recovered=field(
        UInt16, offset=3251, default=0, documentation=
        """Binary Gain rec"""
    )
    amplitude_recovery_method=field(
        UInt16, offset=3253, default=0, documentation=
        ""Recovery Method"""
    )

BEWARE!

This will create nonsensical readings in the binary file header. But at least it fully reads the stuff.