Exemplo n.º 1
0
    def write(self, filename):
        """
            writes to segy file

            :param filename: file name
            :note: the function uses the `obspy` module.
            """

        if not OBSPY_AVAILABLE:
            raise RuntimeError("This feature (SimpleSEGYWriter.write())"+\
                    " depends on obspy, which is not installed, see "+\
                    "https://github.com/obspy/obspy for install guide")

        if getMPISizeWorld() > 1:
            raise RuntimeError("Writing segy files with multiple ranks is"+\
                    " not yet supported.")

        stream = Stream()

        for i in range(len(self.__receiver_group)):
            trace = Trace(data=np.array(self.__trace[i], dtype='float32'))
            # Attributes in trace.stats will overwrite everything in
            # trace.stats.segy.trace_header (in Hz)
            trace.stats.sampling_rate = 1. / self.getSamplingInterval()
            #trace.stats.starttime = UTCDateTime(2011,11,11,0,0,0)
            if not hasattr(trace.stats, 'segy.trace_header'):
                trace.stats.segy = {}
            trace.stats.segy.trace_header = SEGYTraceHeader()
            trace.stats.segy.trace_header.trace_identification_code = 1
            trace.stats.segy.trace_header.trace_sequence_number_within_line = i + 1
            trace.stats.segy.trace_header.scalar_to_be_applied_to_all_coordinates = -int(
                self.COORDINATE_SCALE)
            trace.stats.segy.trace_header.coordinate_units = 1
            trace.stats.segy.trace_header.source_coordinate_x = int(
                self.__source[0] * self.COORDINATE_SCALE)
            trace.stats.segy.trace_header.source_coordinate_y = int(
                self.__source[1] * self.COORDINATE_SCALE)
            trace.stats.segy.trace_header.group_coordinate_x = int(
                self.__receiver_group[i][0] * self.COORDINATE_SCALE)
            trace.stats.segy.trace_header.group_coordinate_y = int(
                self.__receiver_group[i][1] * self.COORDINATE_SCALE)

            # Add trace to stream
            stream.append(trace)
        # A SEGY file has file wide headers. This can be attached to the stream
        # object.  If these are not set, they will be autocreated with default
        # values.
        stream.stats = AttribDict()
        stream.stats.textual_file_header = 'C.. ' + self.__text + '\nC.. with esys.escript.downunder r%s\nC.. %s' % (
            getVersion(), time.asctime())
        stream.stats.binary_file_header = SEGYBinaryFileHeader()

        if getMPIRankWorld() < 1:
            stream.write(filename,
                         format="SEGY",
                         data_encoding=1,
                         byteorder=sys.byteorder)
Exemplo n.º 2
0
 def test_read_and_write_trace_header(self):
     """
     Reading and writing should not change the trace header.
     """
     for file, attribs in self.files.items():
         endian = attribs['endian']
         file = os.path.join(self.path, file)
         # Read the file.
         with open(file, 'rb') as f:
             f.seek(3600)
             org_header = f.read(240)
         header = SEGYTraceHeader(header=org_header, endian=endian)
         # The header writes to a file like object.
         new_header = io.BytesIO()
         header.write(new_header)
         new_header.seek(0, 0)
         new_header = new_header.read()
         # Assert the correct length.
         self.assertEqual(len(new_header), 240)
         # Assert the actual header.
         self.assertEqual(org_header, new_header)
Exemplo n.º 3
0
 def test_read_and_write_trace_header(self):
     """
     Reading and writing should not change the trace header.
     """
     for file, attribs in self.files.items():
         endian = attribs['endian']
         file = os.path.join(self.path, file)
         # Read the file.
         with open(file, 'rb') as f:
             f.seek(3600)
             org_header = f.read(240)
         header = SEGYTraceHeader(header=org_header, endian=endian)
         # The header writes to a file like object.
         new_header = io.BytesIO()
         header.write(new_header)
         new_header.seek(0, 0)
         new_header = new_header.read()
         # Assert the correct length.
         self.assertEqual(len(new_header), 240)
         # Assert the actual header.
         self.assertEqual(org_header, new_header)
Exemplo n.º 4
0
def savesegy(DASdata, filename):
    stream = Stream()
    for i in range(DASdata.data.shape[0]):
        data = DASdata.data[i, :]
        DASdt = np.median(np.diff(DASdata.taxis))
        if DASdt < 0.001:
            dt = 0.001
            data = gjsignal.lpfilter(data, DASdt, 500)
            oldtaxis = np.arange(len(data)) * DASdt
            newtaxis = np.arange(0, oldtaxis[-1], dt)
            data = np.interp(newtaxis, oldtaxis, data)
        else:
            dt = DASdt

        data = np.require(data, dtype=np.float32)
        trace = Trace(data=data)

        # Attributes in trace.stats will overwrite everything in
        # trace.stats.segy.trace_header
        trace.stats.delta = dt
        # SEGY does not support microsecond precision! Any microseconds will
        # be discarded.
        trace.stats.starttime = UTCDateTime(DASdata.start_time)

        # If you want to set some additional attributes in the trace header,
        # add one and only set the attributes you want to be set. Otherwise the
        # header will be created for you with default values.
        if not hasattr(trace.stats, 'segy.trace_header'):
            trace.stats.segy = {}
        trace.stats.segy.trace_header = SEGYTraceHeader()
        trace.stats.segy.trace_header.trace_sequence_number_within_line = DASdata.chans[
            i]
        trace.stats.segy.trace_header.x_coordinate_of_ensemble_position_of_this_trace = int(
            DASdata.mds[i] * 1000)  # in millimeter
        trace.stats.segy.trace_header.lag_time_A = DASdata.start_time.microsecond

        # Add trace to stream
        stream.append(trace)

    # A SEGY file has file wide headers. This can be attached to the stream
    # object.  If these are not set, they will be autocreated with default
    # values.
    stream.stats = AttribDict()
    stream.stats.textual_file_header = 'Textual Header!'
    stream.stats.binary_file_header = SEGYBinaryFileHeader()
    stream.stats.binary_file_header.trace_sorting_code = 5

    print(stream)
    stream.write(filename,
                 format='SEGY',
                 data_encoding=1,
                 byteorder=sys.byteorder)
def savetracetostream(stream, idx, out, data):
    """
    this function add data (data) using the header from stream (idx) to an output stream object (out)
    delta needs to be changed to the sample rate of data (not automatically done yet)
    """
    np.require(data, dtype=np.float32)
    trace = Trace(data=data)
    trace.stats.delta = 0.01
    trace.stats.starttime = UTCDateTime(2011, 11, 11, 11, 11, 11)
    if not hasattr(trace.stats, 'segy.trace_header'):
        trace.stats.segy = {}
    trace.stats.segy.trace_header = SEGYTraceHeader()
    trace.stats.segy.trace_header = stream.traces[idx].header
    out.append(trace)
Exemplo n.º 6
0
def rad2segy(fname, outfile):

    file_header, trace_headers, arr = read_rad(fname)

    dt = int(file_header.get('SPR_SAMPLING_INTERVAL', 0))

    out = Stream()
    out.stats = Stats()

    # Text header.
    header = [
        'Created by seg22segy.',
        'More info to come.',
    ]
    out.stats.textual_file_header = ''.encode()
    for line in header:
        out.stats.textual_file_header += '{:80s}'.format(line).encode()

    # Binary header.
    out.stats.binary_file_header = SEGYBinaryFileHeader()
    out.stats.binary_file_header.trace_sorting_code = 4
    out.stats.binary_file_header.sample_interval_in_microseconds_of_original_field_recording = dt
    out.stats.binary_file_header.seg_y_format_revision_number = 0x0100

    # Trace data.
    for i, trace in enumerate(arr):

        # Make the trace.
        tr = Trace(trace)

        # Add required data.
        tr.stats.delta = dt / 1e6  # In microseconds.
        tr.stats.starttime = 0  # Not strictly required.

        # Add yet more to the header (optional).
        tr.stats.segy = {'trace_header': SEGYTraceHeader()}
        tr.stats.segy.trace_header.trace_sequence_number_within_line = i + 1
        tr.stats.segy.trace_header.receiver_group_elevation = 0
        tr.stats.segy.trace_header.sampling_rate = 1 / dt

        # Append the trace to the stream.
        out.append(tr)

    outbase, ext = os.path.splitext(fname)
    outfile = outfile or '{}_{}.sgy'.format(outbase, BANDS[ext])
    out.write(outfile, format='SEGY', data_encoding=3)  # 3:int16, 5:float32

    return outfile
Exemplo n.º 7
0
def write_segy(f, data):
    """
    Write a 2D NumPY array to an open file handle f.
    """
    stream = Stream()

    # Data is in [0, 1] so rescale to 8-bit.
    # USING 16-bit because can't save as 8-bit int in ObsPy.
    data = np.int16((data - 0.5) * 255)

    for i, trace in enumerate(data):

        # Make the trace.
        tr = Trace(trace)

        # Add required data.
        tr.stats.delta = 0.004

        # Add yet more to the header (optional).
        tr.stats.segy = {'trace_header': SEGYTraceHeader()}
        tr.stats.segy.trace_header.trace_sequence_number_within_line = i + 1
        tr.stats.segy.trace_header.receiver_group_elevation = 0

        # Append the trace to the stream.
        stream.append(tr)

    # Text header.
    stream.stats = AttribDict()
    stream.stats.textual_file_header = '{:80s}'.format(
        'Generated by Keats.').encode()
    stream.stats.textual_file_header += '{:80s}'.format(
        'Sample interval unknown.').encode()
    stream.stats.textual_file_header += '{:80s}'.format(
        'IEEE floats.').encode()

    # Binary header.
    stream.stats.binary_file_header = SEGYBinaryFileHeader()
    stream.stats.binary_file_header.trace_sorting_code = 4
    stream.stats.binary_file_header.seg_y_format_revision_number = 0x0100

    # Write the data.
    # Encoding should be 8, but that doesn't work.
    stream.write(f, format='SEGY', data_encoding=3, byteorder=sys.byteorder)

    return f
Exemplo n.º 8
0
def radar2segy(data='', 
               receiver_elevation=0, 
               num_of_samples=0, 
               sample_interval=0,
               X='', 
               Y='',
               step=1,
               time_mode='gmtime',
               gps_time='',
               year='',
               day_of_year='',
               hour='',
               minute='',
               second='',
               differenciate='',
               to_dB=False):

    '''  
    ==>    Writes Cradar Object as SEGY-Format File.
    Usage: write_segy(self, region='', differenciate=False, step=1)

    - Parameters are:
        1) Cradar Object
        2) region='Greenland' or 'Antarctica'
        3) differenciate=True/False (False is default)
        4) step


            1) Cradar Object, either in 'twt' or 'Z' Domain
            2) if the parameter 'region' is set empty, you already
               should have 'X' and 'Y' coordinates available for your region
               --> if you set it to 'Greenland'  they will be projected to EPSG:3413
               --> if you set it to 'Antarctica' they will be projected to EPSG:3031
            3) choose weather to take the data as it is or to differenciate
               --> set differenciate=True (default is differenciate=False)
            4) step=N, every N'th trace will be considered (to reduce data size if needed)
    ''' 

    import numpy as np

    from obspy import Trace, Stream
    from obspy.core import AttribDict
    from obspy.io.segy.segy import SEGYTraceHeader, SEGYBinaryFileHeader

    from pyproj import Transformer
    import time
    import sys


    data = data
    step = step

    gps_time = gps_time

    receiver_elevation = receiver_elevation
    num_of_samples     = num_of_samples
    sample_interval    = sample_interval

    sample_interval    = sample_interval

    X = X
    Y = Y

    time_array   = year
    year         = year
    day_of_year  = day_of_year
    hour         = hour
    minute       = minute
    second       = second

    differenciate = differenciate


    # Create empty stream
    stream = Stream()

    # Create Traces and Trace Header
    for i in range(0, len(X) - 1, step)[0:-1]:

        if time_mode == 'gmtime':

            year            = int(time.strftime("%Y", time.gmtime(gps_time[i])))
            day_of_year     = int(time.strftime("%j", time.gmtime(gps_time[i])))
            hour            = int(time.strftime("%H", time.gmtime(gps_time[i])))
            minute          = int(time.strftime("%M", time.gmtime(gps_time[i])))
            second          = int(time.strftime("%S", time.gmtime(gps_time[i])))

        else:
            year         = year[i]
            day_of_year  = day_of_year[i]
            hour         = hour[i]
            minute       = minute[i]
            second       = second[i]

        # Create some random data.
        if to_dB == False:
            trace_  = np.array(data[i])
        elif to_dB == True:
            trace_  = np.array(20*np.log10(data[i]))
        trace_  = np.require(trace_, dtype=np.float32)
        trace_  = trace_.flatten()
        trace   = Trace(data=trace_)

        if differenciate == True:
            trace = trace.differentiate(method='gradient')
        else:
            pass


        #print(i)
        #print(X[i].astype(int))
        #print(Y[i].astype(int))
        #print(trace)
        #print(np.array(20*np.log10(data[i])))
        #print(np.array(20*np.log10(data[i])).shape)
        #print()


        #trace.stats.delta = 0.01
        trace.stats.sampling_rate = 1/sample_interval
        # SEGY does not support microsecond precision! Any microseconds will
        # be discarded.

        # If you want to set some additional attributes in the trace header,
        # add one and only set the attributes you want to be set. Otherwise the
        # header will be created for you with default values.

        if not hasattr(trace.stats, 'segy.trace_header'):
            pass
        trace.stats.segy = {}
            
        trace.stats.segy.trace_header = SEGYTraceHeader()

        trace.stats.segy.trace_header.trace_sequence_number_within_line = i + 1
        trace.stats.segy.trace_header.trace_sequence_number_within_segy_file = i + 1
        trace.stats.segy.trace_header.original_field_record_number = i + 1
        trace.stats.segy.trace_header.trace_number_within_the_original_field_record = i + 1
        trace.stats.segy.trace_header.energy_source_point_number = i + 1
        
        trace.stats.segy.trace_header.ensemble_number = 1
        trace.stats.segy.trace_header.trace_number_within_the_ensemble = 1
        trace.stats.segy.trace_header.trace_identification_code = 1
        trace.stats.segy.trace_header.number_of_vertically_summed_traces_yielding_this_trace = 1
        trace.stats.segy.trace_header.number_of_horizontally_stacked_traces_yielding_this_trace = 1
        trace.stats.segy.trace_header.data_use = 1
        trace.stats.segy.trace_header.distance_from_center_of_the_source_point_to_the_center_of_the_receiver_group = 0

        trace.stats.segy.trace_header.receiver_group_elevation = int(receiver_elevation)
        trace.stats.segy.trace_header.surface_elevation_at_source = int(receiver_elevation)

        trace.stats.segy.trace_header.source_depth_below_surface = 0
        trace.stats.segy.trace_header.datum_elevation_at_receiver_group = 36167
        trace.stats.segy.trace_header.datum_elevation_at_source = 89275
        trace.stats.segy.trace_header.water_depth_at_source = 36292
        trace.stats.segy.trace_header.water_depth_at_group = 89581
        trace.stats.segy.trace_header.scalar_to_be_applied_to_all_elevations_and_depths = 1
        trace.stats.segy.trace_header.scalar_to_be_applied_to_all_coordinates = 1

        trace.stats.segy.trace_header.source_coordinate_x   = X[i].astype(int)
        trace.stats.segy.trace_header.source_coordinate_y   = Y[i].astype(int)
        trace.stats.segy.trace_header.group_coordinate_x    = X[i].astype(int)
        trace.stats.segy.trace_header.group_coordinate_y    = Y[i].astype(int)

        trace.stats.segy.trace_header.coordinate_units = 1
        trace.stats.segy.trace_header.weathering_velocity = 300
        trace.stats.segy.trace_header.subweathering_velocity = 168
        trace.stats.segy.trace_header.uphole_time_at_source_in_ms = 38
        trace.stats.segy.trace_header.uphole_time_at_group_in_ms = 0
        trace.stats.segy.trace_header.source_static_correction_in_ms = 0
        trace.stats.segy.trace_header.group_static_correction_in_ms = 0
        trace.stats.segy.trace_header.total_static_applied_in_ms = 0
        trace.stats.segy.trace_header.lag_time_A = 0
        trace.stats.segy.trace_header.lag_time_B = 0
        trace.stats.segy.trace_header.delay_recording_time = 0
        trace.stats.segy.trace_header.mute_time_start_time_in_ms = 0
        trace.stats.segy.trace_header.mute_time_end_time_in_ms = 0
        trace.stats.segy.trace_header.number_of_samples_in_this_trace = num_of_samples
        trace.stats.segy.trace_header.sample_interval_in_ms_for_this_trace = sample_interval
        trace.stats.segy.trace_header.gain_type_of_field_instruments = 1
        trace.stats.segy.trace_header.instrument_gain_constant = 0
        trace.stats.segy.trace_header.instrument_early_or_initial_gain = 0
        trace.stats.segy.trace_header.correlated = 1
        trace.stats.segy.trace_header.sweep_frequency_at_start = 180
        trace.stats.segy.trace_header.sweep_frequency_at_end = 210
        trace.stats.segy.trace_header.sweep_length_in_ms = 10
        trace.stats.segy.trace_header.sweep_type = 4
        trace.stats.segy.trace_header.sweep_trace_taper_length_at_start_in_ms = 3
        trace.stats.segy.trace_header.sweep_trace_taper_length_at_end_in_ms = 0
        trace.stats.segy.trace_header.taper_type = 3
        trace.stats.segy.trace_header.alias_filter_frequency = 0
        trace.stats.segy.trace_header.alias_filter_slope = 0
        trace.stats.segy.trace_header.notch_filter_frequency = 0
        trace.stats.segy.trace_header.notch_filter_slope = 0
        trace.stats.segy.trace_header.low_cut_frequency = 0
        trace.stats.segy.trace_header.high_cut_frequency = 0
        trace.stats.segy.trace_header.low_cut_slope = 0
        trace.stats.segy.trace_header.high_cut_slope = 0
        trace.stats.segy.trace_header.year_data_recorded = year
        trace.stats.segy.trace_header.day_of_year = day_of_year
        trace.stats.segy.trace_header.hour_of_day = hour
        trace.stats.segy.trace_header.minute_of_hour = minute
        trace.stats.segy.trace_header.second_of_minute = second
        trace.stats.segy.trace_header.time_basis_code = 4
        trace.stats.segy.trace_header.trace_weighting_factor = 0
        trace.stats.segy.trace_header.geophone_group_number_of_roll_switch_position_one = 0
        trace.stats.segy.trace_header.geophone_group_number_of_trace_number_one = 1
        trace.stats.segy.trace_header.geophone_group_number_of_last_trace = 1
        trace.stats.segy.trace_header.gap_size = 0
        trace.stats.segy.trace_header.over_travel_associated_with_taper = 0

        trace.stats.segy.trace_header.x_coordinate_of_ensemble_position_of_this_trace = X[i].astype(int)
        trace.stats.segy.trace_header.y_coordinate_of_ensemble_position_of_this_trace = Y[i].astype(int)

        trace.stats.segy.trace_header.for_3d_poststack_data_this_field_is_for_in_line_number = 1

        trace.stats.segy.trace_header.for_3d_poststack_data_this_field_is_for_cross_line_number = i + 1
        trace.stats.segy.trace_header.shotpoint_number = i + 1

        trace.stats.segy.trace_header.scalar_to_be_applied_to_the_shotpoint_number = 1
        trace.stats.segy.trace_header.trace_value_measurement_unit = 1
        trace.stats.segy.trace_header.transduction_constant_mantissa = 1
        trace.stats.segy.trace_header.transduction_constant_exponent = 0
        trace.stats.segy.trace_header.transduction_units = 9
        trace.stats.segy.trace_header.device_trace_identifier = 0
        trace.stats.segy.trace_header.scalar_to_be_applied_to_times = 0
        trace.stats.segy.trace_header.source_type_orientation = 0
        trace.stats.segy.trace_header.source_energy_direction_mantissa = 0
        trace.stats.segy.trace_header.source_energy_direction_exponent = 0
        trace.stats.segy.trace_header.source_measurement_mantissa = 1
        trace.stats.segy.trace_header.source_measurement_exponent = 0
        trace.stats.segy.trace_header.source_measurement_unit = 2

        # Add trace to stream
        stream.append(trace)

    # A SEGY file has file wide headers. This can be attached to the stream
    # object.  If these are not set, they will be autocreated with default
    # values.
    stream.stats = AttribDict()
    stream.stats.textual_file_header = 'Textual Header!'
    stream.stats.binary_file_header = SEGYBinaryFileHeader()
    stream.stats.binary_file_header.trace_sorting_code = 5
    stream.stats.binary_file_header.number_of_samples_per_data_trace = num_of_samples
    stream.stats.binary_file_header.number_of_samples_per_data_trace_for_original_field_recording = num_of_samples
    stream.stats.binary_file_header.data_sample_format_code = 5

    return stream
Exemplo n.º 9
0
def readBigSuFile(nameOfFile, nt, format='SU', byteorder='<'):
    """ This function is a hack to read .su file containing too many samples
        per traces.
        In the su format only 2 bytes per trace are dedicated to encoding for
        the number of samples (as signed int, see:
        http://lists.swapbytes.de/archives/obspy-users/2017-March/002359.html).
        Even if it's an old format it's still extremely stupid.
        This proove the lack of vision the designer of this format had at that
        time. They could have chosen 8 bytes or 16 bytes it was no big deal...
        They've cost me a day's work.
        But let us forget about the past. This limits the size of the
        traces to 32768 samples (NSTEP beween -32768 to 32768). Let us now
        suppose that we have NSTEP = 80000 samples per trace. We still want to
        use Obspy. The problem is that the NSTEP written in the .su file does
        not make any sense anymore and it is read by the obspy.read function!
        We thus rewrote a quick version of this function replacing the number
        of point by PAR.NT
        It is mainly copy-pasted from Obspy source code.
    """

    from obspy.core import Stream, Trace
    from obspy.core.utcdatetime import UTCDateTime
    from obspy.core.util import AttribDict
    from obspy.io.segy.core import LazyTraceHeaderAttribDict
    from obspy.io.segy.segy import SEGYTraceReadingError
    from obspy.io.segy.segy import SEGYTraceHeaderTooSmallError
    from obspy.io.segy.segy import SEGYTraceHeader
    from obspy.io.segy.header import DATA_SAMPLE_FORMAT_UNPACK_FUNCTIONS
    from obspy.io.segy.header import DATA_SAMPLE_FORMAT_SAMPLE_SIZE

    file_object = open(nameOfFile, 'r')
    endian = byteorder
    datas = []
    headers = []
    data_encoding = 5
    # Big loop to read all data traces.
    while True:
        # Read and as soon as the trace header is too small abort.
        try:
            # Always unpack with IEEE
            filesize = os.fstat(file_object.fileno())[6]
            trace_header = file_object.read(240)
            # Check if it is smaller than 240 byte.
            if len(trace_header) != 240:
                msg = 'The trace header needs to be 240 bytes long'
                raise SEGYTraceHeaderTooSmallError(msg)
            header = SEGYTraceHeader(trace_header, endian=endian)
            header.number_of_samples_in_this_trace = nt
            # The number of samples in the current trace.
            npts = header.number_of_samples_in_this_trace
            # Do a sanity check if there is enough data left.
            pos = file_object.tell()
            data_left = filesize - pos
            data_needed = DATA_SAMPLE_FORMAT_SAMPLE_SIZE[data_encoding] * npts
            if npts < 1 or data_needed > data_left:
                msg = """
                      Too little data left in the file to unpack it according
                      to its trace header. This is most likely either due to a
                      wrong byte order or a corrupt file.
                      """.strip()
                raise SEGYTraceReadingError(msg)
            else:
                # Unpack the data
                dsfuf = DATA_SAMPLE_FORMAT_UNPACK_FUNCTIONS
                data = dsfuf[data_encoding](file_object, npts, endian=endian)
            datas.append(data)
            headers.append(header)
        except SEGYTraceHeaderTooSmallError:
            break

    file_object.close()
    # Create the stream object.
    stream = Stream()

    # Loop over all traces.
    for idx, data in enumerate(datas):
        # Create new Trace object for every segy trace and append to the Stream
        # object.
        trace = Trace()
        stream.append(trace)
        trace.data = data
        trace.stats.su = AttribDict()

        # Add the trace header as a new lazy attrib dictionary.
        header = LazyTraceHeaderAttribDict(headers[idx].unpacked_header,
                                           endian)
        trace.stats.su.trace_header = header
        # Also set the endianness.
        trace.stats.su.endian = endian
        # The sampling rate should be set for every trace. It is a sample
        # interval in microseconds. The only sanity check is that is should be
        # larger than 0.
        tr_header = trace.stats.su.trace_header
        if tr_header.sample_interval_in_ms_for_this_trace > 0:
            trace.stats.delta = \
                float(headers[idx].sample_interval_in_ms_for_this_trace) / 1E6
        # If the year is not zero, calculate the start time. The end time is
        # then calculated from the start time and the sampling rate.
        # 99 is often used as a placeholder.
        if tr_header.year_data_recorded > 0:
            year = tr_header.year_data_recorded
            # The SEG Y rev 0 standard specifies the year to be a 4 digit
            # number.  Before that it was unclear if it should be a 2 or 4
            # digit number. Old or wrong software might still write 2 digit
            # years. Every number <30 will be mapped to 2000-2029 and every
            # number between 30 and 99 will be mapped to 1930-1999.
            if year < 100:
                if year < 30:
                    year += 2000
                else:
                    year += 1900
            julday = tr_header.day_of_year
            julday = tr_header.day_of_year
            hour = tr_header.hour_of_day
            minute = tr_header.minute_of_hour
            second = tr_header.second_of_minute
            trace.stats.starttime = UTCDateTime(year=year,
                                                julday=julday,
                                                hour=hour,
                                                minute=minute,
                                                second=second)

    # set _format identifier for each element
    for trace in stream:
        trace.stats._format = format

    return stream
Exemplo n.º 10
0
def assemply_segy(image, xStart, xEnd, yStart, yEnd, dt=0.01, scaler=1000):
    """
    mostly from http://geophysicslabs.com/2017/02/12/how-to-add-cross-sections-to-opendtect/
    """
    data = np.asarray(image, dtype=np.float32)
    nrows, ncols = image.shape
    # create linearly interpolated sequence of points between the two ends of the line
    traces = np.arange(ncols)
    X = np.interp(traces, [0, ncols - 1], [xStart, xEnd])
    Y = np.interp(traces, [0, ncols - 1], [yStart, yEnd])

    # create coordinate vectors with applied scaling factor
    Xint = np.round(X * scaler).astype(np.int)
    Yint = np.round(Y * scaler).astype(np.int)

    # Make a new Stream object
    out = Stream()
    # For each column in the image, create a new trace
    for i, t in enumerate(data.T):
        trace = Trace(t, header={'delta': dt})
        out.append(trace)

    # create trace headers with trace coordinates
    for i, trace in enumerate(out):
        trace.stats.segy = {}
        trace.stats.segy.trace_header = SEGYTraceHeader()

        trace.stats.segy.trace_header.trace_sequence_number_within_line = i + 1
        trace.stats.segy.trace_header.sample_interval_in_ms_for_this_trace = dt
        trace.stats.segy.trace_header.number_of_samples_in_this_trace = len(
            trace)
        trace.stats.segy.trace_header.scalar_to_be_applied_to_all_coordinates = -1 * scaler
        trace.stats.segy.trace_header.delay_recording_time = 0
        trace.stats.segy.trace_header.source_coordinate_x = Xint[i]
        trace.stats.segy.trace_header.source_coordinate_y = Yint[i]
        #     trace.stats.segy.trace_header.source_coordinate_x= X[i]
        #     trace.stats.segy.trace_header.source_coordinate_y= Y[i]
        trace.stats.segy.trace_header.x_coordinate_of_ensemble_position_of_this_trace = Xint[
            i]
        trace.stats.segy.trace_header.y_coordinate_of_ensemble_position_of_this_trace = Yint[
            i]

    #     trace.stats.segy.trace_header.x_coordinate_of_ensemble_position_of_this_trace= X[i]
    #     trace.stats.segy.trace_header.y_coordinate_of_ensemble_position_of_this_trace=Y[i]

    # create text header
    text_header = '{0:<80}'.format("File created on " +
                                   datetime.date.today().isoformat())
    text_header += '{0:<80}'.format("Coordinates of the line:")
    text_header += '{0:<80}'.format("LeftX   : " + str(int(X[0])))
    text_header += '{0:<80}'.format("LeftY   : " + str(int(Y[0])))
    text_header += '{0:<80}'.format("RightX  : " + str(int(X[-1])))
    text_header += '{0:<80}'.format("RightY  : " + str(int(Y[-1])))

    # Add text and binary headers to stream
    out.stats = Stats(dict(textual_file_header=text_header.encode('utf-8')))
    out.stats.binary_file_header = SEGYBinaryFileHeader()
    out.stats.binary_file_header.number_of_data_traces_per_ensemble = 1
    out.stats.binary_file_header.number_of_samples_per_data_trace = len(trace)

    return out