def read_binary_values(fh, pos=None, seg_y_type='int32', num_items=1, endian='>'): """Read a series of values from a binary file. Args: fh: A file-like-object open in binary mode. seg_y_type: The SEG Y data type. num_items: The number of items to be read. Returns: A sequence containing count items. """ ctype = SEG_Y_TYPE_TO_CTYPE[seg_y_type] item_size = size_in_bytes(ctype) block_size = item_size * num_items fh.seek(pos, os.SEEK_SET) buf = fh.read(block_size) if len(buf) < block_size: raise EOFError("{} bytes requested but only {} available".format( block_size, len(buf))) values = (unpack_ibm_floats(buf, num_items) if ctype == 'ibm' else unpack_values(buf, ctype, endian)) assert len(values) == num_items return values
def trace_samples(self, trace_index, start=None, stop=None): """Read a specific trace_samples. Args: trace_index: An integer in the range zero to num_traces() - 1 start: Optional zero-based start sample index. The default is to read from the first (i.e. zeroth) sample. stop: Optional zero-based stop sample index. Following Python slice convention this is one beyond the end. Returns: A sequence of numeric trace_samples samples. Example: first_trace_samples = segy_reader.trace_samples(0) part_of_second_trace_samples = segy_reader.trace_samples(1, 1000, 2000) """ if not (0 <= trace_index < self.num_traces()): raise ValueError("Trace index out of range.") num_samples_in_trace = self.num_trace_samples(trace_index) start_sample = start if start is not None else 0 stop_sample = stop if stop is not None else num_samples_in_trace if not (0 <= stop_sample <= num_samples_in_trace): raise ValueError( "trace_samples(): stop value {} out of range 0 to {}".format( stop, num_samples_in_trace)) if not (0 <= start_sample <= stop_sample): raise ValueError( "trace_samples(): start value {} out of range 0 to {}".format( start, stop_sample)) dsf = self._binary_reel_header.data_sample_format seg_y_type = DATA_SAMPLE_FORMAT_TO_SEG_Y_TYPE[dsf] start_pos = ( self._trace_offset_catalog[trace_index] + TRACE_HEADER_NUM_BYTES + start_sample * size_in_bytes(SEG_Y_TYPE_TO_CTYPE[seg_y_type])) num_samples_to_read = stop_sample - start_sample trace_values = read_binary_values(self._fh, start_pos, seg_y_type, num_samples_to_read, self._endian) return trace_values
def trace_samples(self, trace_index, start=None, stop=None): """Read a specific trace_samples. Args: trace_index: An integer in the range zero to num_traces() - 1 start: Optional zero-based start sample index. The default is to read from the first (i.e. zeroth) sample. stop: Optional zero-based stop sample index. Following Python slice convention this is one beyond the end. Returns: A sequence of numeric trace_samples samples. Example: first_trace_samples = segy_reader.trace_samples(0) part_of_second_trace_samples = segy_reader.trace_samples(1, 1000, 2000) """ if not (0 <= trace_index < self.num_traces()): raise ValueError("Trace index out of range.") num_samples_in_trace = self.num_trace_samples(trace_index) start_sample = start if start is not None else 0 stop_sample = stop if stop is not None else num_samples_in_trace if not (0 <= stop_sample <= num_samples_in_trace): raise ValueError("trace_samples(): stop value {} out of range 0 to {}" .format(stop, num_samples_in_trace)) if not (0 <= start_sample <= stop_sample): raise ValueError("trace_samples(): start value {} out of range 0 to {}" .format(start, stop_sample)) dsf = self._binary_reel_header.data_sample_format seg_y_type = DATA_SAMPLE_FORMAT_TO_SEG_Y_TYPE[dsf] start_pos = (self._trace_offset_catalog[trace_index] + TRACE_HEADER_NUM_BYTES + start_sample * size_in_bytes(SEG_Y_TYPE_TO_CTYPE[seg_y_type])) num_samples_to_read = stop_sample - start_sample trace_values = read_binary_values( self._fh, start_pos, seg_y_type, num_samples_to_read, self._endian) return trace_values
def read_binary_values(fh, pos=None, seg_y_type='int32', num_items=1, endian='>'): """Read a series of values from a binary file. Args: fh: A file-like-object open in binary mode. pos: An optional file offset in bytes from the beginning from which the data is to be read. If None, the current file position will be used. seg_y_type: The SEG Y data type. num_items: The number of items to be read. endian: '>' for big-endian data (the standard and default), '<' for little-endian (non-standard) Returns: A sequence containing count items. """ ctype = SEG_Y_TYPE_TO_CTYPE[seg_y_type] item_size = size_in_bytes(ctype) block_size = item_size * num_items pos = fh.tell() if pos is None else pos fh.seek(pos, os.SEEK_SET) buf = fh.read(block_size) if len(buf) < block_size: raise EOFError("{} bytes requested but only {} available when reading " "from position {}".format(block_size, len(buf), pos)) values = (unpack_ibm_floats(buf, num_items) if ctype == 'ibm' else unpack_values(buf, ctype, endian)) assert len(values) == num_items return values
def test_illegal_ctypes_raise_value_error(ctype): assume(ctype not in LEGAL_CTYPES) with raises(ValueError): size_in_bytes(ctype)
def test_floats_are_four_bytes(ctype): assert size_in_bytes(ctype) == 4
def test_bytes_are_one_byte(ctype): assert size_in_bytes(ctype) == 1
def test_shorts_are_two_bytes(ctype): assert size_in_bytes(ctype) == 2
def test_integers_are_four_bytes(ctype): assert size_in_bytes(ctype) == 4