Coverage for /opt/obspy/update-docs/src/obspy/obspy/segy/segy : 86%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*- #------------------------------------------------------------------- # Filename: seg.py # Purpose: Routines for reading and writing SEG Y files. # Author: Lion Krischer # Email: krischer@geophysik.uni-muenchen.de # # Copyright (C) 2010 Lion Krischer #--------------------------------------------------------------------- Routines to read and write SEG Y rev 1 encoded seismic data files. """
BINARY_FILE_HEADER_FORMAT, DATA_SAMPLE_FORMAT_PACK_FUNCTIONS, \ TRACE_HEADER_FORMAT, DATA_SAMPLE_FORMAT_SAMPLE_SIZE, TRACE_HEADER_KEYS
""" Base SEGY exception class. """
""" Raised if the trace header is not the required 240 byte long. """
""" Raised if there is not enough data left in the file to unpack the data according to the values read from the header. """
""" Raised if attempting to unpack trace data but no ``unpack_data()`` function exists. """
""" Raised if the trace header is not the required 240 byte long. """
""" Class that internally handles SEG Y files. """ unpack_headers=False, headonly=False): """ Class that internally handles SEG Y files.
:param file: A file like object with the file pointer set at the beginning of the SEG Y file. If file is None, an empty SEGYFile object will be initialized. :param endian: The endianness of the file. If None, autodetection will be used. :param textual_header_encoding: The encoding of the textual header. Either 'EBCDIC', 'ASCII' or None. If it is None, autodetection will be attempted. If it is None and file is also None, it will default to 'ASCII'. :param unpack_headers: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. :param headonly: Bool. Determines whether or not the actual data records will be read and unpacked. Has a huge impact on memory usage. Data can be read and unpacked on-the-fly after reading the file. Defaults to False. """ # Set the endianness to big. else: self.endian = ENDIAN[endian] # And the textual header encoding to ASCII. # If endian is None autodetect is. else: # If the textual header encoding is None, autodetection will be used. # Read the headers. # Read the actual traces.
""" Prints some information about the SEG Y file. """
""" Tries to automatically determine the endianness of the file at hand. """ # Jump to the data sample format code. # Check if valid. # Else test little endian. else: else: msg = 'Unable to determine the endianness of the file. ' + \ 'Please specify it.' raise SEGYError(msg) # Jump to previous position.
""" Creates an empty SEGYFile object. """
""" Reads the textual header. """ # The first 3200 byte are the textual header. # The data can either be saved as plain ASCII or EBCDIC. The first # character always is mostly 'C' and therefore used to check the # encoding. Sometimes is it not C but also cannot be decoded from # EBCDIC so it is treated as ASCII and all empty symbols are removed. textual_header.decode('EBCDIC-CP-BE').encode('ascii') # If this worked, the encoding is EBCDIC. # Otherwise it is ASCII. else: # Otherwise the encoding will also be ASCII. textual_header.decode('EBCDIC-CP-BE').encode('ascii') The textual_header_encoding has to be either ASCII, EBCDIC or None for autodetection. ASCII, EBCDIC or None for autodetection. """.strip() # Finally set it.
""" Reads the textual and binary file headers starting at the current file pointer position. """ # Read the textual header. # The next 400 bytes are from the Binary File Header. # If bytes 3506-3506 are not zero, an extended textual header follows # which is not supported so far. msg = 'Extended textual headers are supported yet. ' + \ 'Please contact the developers.' raise NotImplementedError(msg)
""" Write a SEG Y file to file which is either a file like object with a write method or a filename string.
If data_encoding or endian is set, these values will be enforced. """ self._write(file, data_encoding=data_encoding, endian=endian)
""" Writes SEG Y to a file like object.
If data_encoding or endian is set, these values will be enforced. """ # Write the textual header.
# Write certain fields in the binary header if they are not set. Most # fields will be written using the data from the first trace. It is # usually better to set the header manually! self.binary_file_header.number_of_data_traces_per_ensemble = \ len(self.traces) self.binary_file_header.sample_interval_in_microseconds = \ self.traces[0].header.sample_interval_in_ms_for_this_trace self.binary_file_header.number_of_samples_per_data_trace = \ len(self.traces[0].data)
# Always set the SEGY Revision number to 1.0 (hex-coded). # Set the fixed length flag to zero if all traces have NOT the same # length. Leave unchanged otherwise. self.binary_file_header.fixed_length_trace_flag = 0 # Extended textual headers are not supported by ObsPy so far. number_of_3200_byte_ext_file_header_records_following = 0 # Enforce the encoding
# Write the binary header. # Write all traces.
""" Write the textual header in various encodings. The encoding will depend on self.textual_header_encoding. If self.textual_file_header is too small it will be padded with zeros. If it is too long or an invalid encoding is specified an exception will be raised. """ # Append spaces to the end if its too short. textual_header = self.textual_file_header + ' ' * (3200 - length) # The length must not exceed 3200 byte. else: msg = 'self.textual_file_header is not allowed to be longer ' + \ 'than 3200 bytes' raise SEGYWritingError(msg) textual_header.decode('ascii').encode('EBCDIC-CP-BE') # Should not happen. else: msg = 'self.textual_header_encoding has to be either ASCII or ' + \ 'EBCDIC.' raise SEGYWritingError(msg)
""" Reads the actual traces starting at the current file pointer position to the end of the file.
:param unpack_headers: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False.
:param headonly: Bool. Determines whether or not the actual data records will be read and unpacked. Has a huge impact on memory usage. Data can be read and unpacked on-the-fly after reading the file. Defaults to False. """ # Determine the filesize once. else: # Big loop to read all data traces. # Read and as soon as the trace header is too small abort. unpack_headers=unpack_headers, filesize=filesize, headonly=headonly)
""" Parses the binary file header at the given starting position. """ """ """
""" Reads the binary file header and stores every value in a class attribute. """ # Unpack according to different lengths. # Set the class attribute. # Update: Seems to be correct. Two's complement integers seem to be # the common way to store integer values. # Set the class attribute. # The other value are the unassigned values. As it is unclear how # these are formated they will be stored as strings. # These are only the unassigned fields. # Set the class attribute. # Should not happen. else: raise Exception
""" Convenience method to print the binary file header. """ final_str = ["Binary File Header:"] for item in BINARY_FILE_HEADER_FORMAT: final_str.append("\t%s: %s" % (item[1], str(getattr(self, item[1])))) return "\n".join(final_str)
""" Writes the header to an open file like object. """ # Unpack according to different lengths. # Write to file. # Update: Seems to be correct. Two's complement integers seem to be # the common way to store integer values. # Write to file. # These are the two unassigned values in the binary file header. # Pad to desired length if necessary. temp += '\x00' * (length - temp_length) # Should not happen. else: raise Exception
""" Just fills all necessary class attributes with zero. """
""" Convenience class that internally handles a single SEG Y trace. """ unpack_headers=False, filesize=None, headonly=False): """ Convenience class that internally handles a single SEG Y trace.
:param file: Open file like object with the file pointer of the beginning of a trace. If it is None, an empty trace will be created. :param data_encoding: The data sample format code as defined in the binary file header:
1: 4 byte IBM floating point 2: 4 byte Integer, two's complement 3: 2 byte Integer, two's complement 4: 4 byte Fixed point with gain 5: 4 byte IEEE floating point 8: 1 byte Integer, two's complement
Defaults to 4. :param big_endian: Bool. True means the header is encoded in big endian and False corresponds to a little endian header. :param unpack_headers: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. :param filesize: Integer. Filesize of the file. If not given it will be determined using fstat which is slow. :param headonly: Bool. Determines whether or not the actual data records will be read and unpacked. Has a huge impact on memory usage. Data can be read and unpacked on-the-fly after reading the file. Defaults to False. """ # If None just return empty structure. # Set the filesize if necessary. else: else: # Otherwise read the file.
""" Reads the complete next header starting at the file pointer at self.file.
:param unpack_headers: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. :param headonly: Bool. Determines whether or not the actual data records will be read and unpacked. Has a huge impact on memory usage. Data can be read and unpacked on-the-fly after reading the file. Defaults to False. """ # Check if it is smaller than 240 byte. endian=self.endian, unpack_headers=unpack_headers) # The number of samples in the current trace. # Do a sanity check if there is enough data left. npts Too little data left in the file to unpack it according to its trace header. This is most likely either due to a wrong byteorder or a corrupt file. """.strip() # skip reading the data, but still advance the file # build a function for reading data from the disk on the fly DATA_SAMPLE_FORMAT_UNPACK_FUNCTIONS[self.data_encoding], self.file.name, self.file.mode, pos, npts, endian=self.endian) else: # Unpack the data. self.data_encoding](self.file, npts, endian=self.endian)
""" Writes the Trace to a file like object.
If endian or data_encoding is set, these values will be enforced. Otherwise use the values of the SEGYTrace object. """ # Set the data length in the header before writing it.
# Write the header. # Write the data. msg = "No data in the SEGYTrace." raise SEGYWritingError(msg) endian=endian)
""" Creates an empty trace with an empty header. """
""" Print some information about the trace. """ ret_val = 'Trace sequence number within line: %i\n' % \ self.header.trace_sequence_number_within_line ret_val += '%i samples, dtype=%s, %.2f Hz' % (len(self.data), self.data.dtype, 1.0 / \ (self.header.sample_interval_in_ms_for_this_trace / \ float(1E6))) return ret_val
""" This method is only called if the attribute is not found in the usual places (i.e. not an instance attribute or not found in the class tree for self). """ # Use data unpack function to unpack data on the fly else: msg = """ Attempted to unpack trace data on the fly with self.unpack_data(), but function does not exist. """.strip() raise SEGYTraceOnTheFlyDataUnpackingError(msg) else: msg = "'%s' object has no attribute '%s'" % \ (self.__class__.__name__, name) raise AttributeError(msg)
""" Convenience class that handles reading and writing of the trace headers. """ """ Will take the 240 byte of the trace header and unpack all values with the given endianness.
:param header: String that contains the packed binary header values. If header is None, a trace header with all values set to 0 will be created :param big_endian: Bool. True means the header is encoded in big endian and False corresponds to a little endian header. :param unpack_headers: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. """ # Check the length of the string, msg = 'The trace header needs to be 240 bytes long' raise SEGYTraceHeaderTooSmallError(msg) # Either unpack the header or just append the unpacked header. This is # much faster and can later be unpacked on the fly. # The number of samples is an essential information that always # needs to be unpacked. else:
""" Reads the 240 byte long header and unpacks all values into corresponding class attributes. """ # Set the start position. # Loop over all items in the TRACE_HEADER_FORMAT list which is supposed # to be in the correct order. length, special_format))
""" Writes the header to an open file like object. """ # Use special format if necessary. # Pack according to different lengths. # Update: Seems to be correct. Two's complement integers seem to be # the common way to store integer values. # Just the one unassigned field. # An empty field will have a zero. # Should not happen. else: raise Exception
""" This method is only called if the attribute is not found in the usual places (i.e. not an instance attribute or not found in the class tree for self). """ # If not found raise an attribute error. except ValueError: msg = "'%s' object has no attribute '%s'" % \ (self.__class__.__name__, name) raise AttributeError(msg) # Unpack the one value and set the class attribute so it will does not # have to unpacked again if accessed in the future. special_format)
""" Just returns all header values. """ retval = '' for item in TRACE_HEADER_FORMAT: _, name, _, _ = item # Do not print the unassigned value. if name == 'unassigned': continue retval += '%s: %i\n' % (name, getattr(self, name)) return retval
""" Init the trace header with zeros. """ # First set all fields to zero.
unpack_headers=False, headonly=False): """ Reads a SEG Y file and returns a SEGYFile object.
:param file: Open file like object or a string which will be assumed to be a filename. :param endian: String that determines the endianness of the file. Either '>' for big endian or '<' for little endian. If it is None, obspy.segy will try to autodetect the endianness. The endianness is always valid for the whole file. :param textual_header_encoding: The encoding of the textual header. Either 'EBCDIC', 'ASCII' or None. If it is None, autodetection will be attempted. :param unpack_headers: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. :param headonly: Bool. Determines whether or not the actual data records will be read and unpacked. Has a huge impact on memory usage. Data can be read and unpacked on-the-fly after reading the file. Defaults to False. """ # Open the file if it is not a file like object. hasattr(file, 'seek'): textual_header_encoding=textual_header_encoding, unpack_headers=unpack_headers, headonly=headonly) # Otherwise just read it. textual_header_encoding=textual_header_encoding, unpack_headers=unpack_headers, headonly=headonly)
unpack_headers=False, headonly=False): """ Reads on open file object and returns a SEGYFile object.
:param file: Open file like object. :param endian: String that determines the endianness of the file. Either '>' for big endian or '<' for little endian. If it is None, obspy.segy will try to autodetect the endianness. The endianness is always valid for the whole file. :param textual_header_encoding: The encoding of the textual header. Either 'EBCDIC', 'ASCII' or None. If it is None, autodetection will be attempted. :param unpack_headers: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. :param headonly: Bool. Determines whether or not the actual data records will be read and unpacked. Has a huge impact on memory usage. Data can be read and unpacked on-the-fly after reading the file. Defaults to False. """ textual_header_encoding=textual_header_encoding, unpack_headers=unpack_headers, headonly=headonly)
""" Convenience class that internally handles Seismic Unix data files. It currently can only read IEEE 4 byte float encoded SU data files. """ headonly=False): """ :param file: A file like object with the file pointer set at the beginning of the SEG Y file. If file is None, an empty SEGYFile object will be initialized.
:param endian: The endianness of the file. If None, autodetection will be used. :param unpack_header: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. :param headonly: Bool. Determines whether or not the actual data records will be read and unpacked. Has a huge impact on memory usage. Data can be read and unpacked on-the-fly after reading the file. Defaults to False. """ # Set the endianness to big. if endian is None: self.endian = '>' else: self.endian = ENDIAN[endian] return # If endian is None autodetect is. else: # Read the actual traces.
""" Tries to automatically determine the endianness of the file at hand. """ msg = 'Autodetection of Endianness failed. Please specify it ' + \ 'by hand or contact the developers.' raise Exception(msg)
""" Creates an empty SUFile object. """
""" Prints some information about the SU file. """ return '%i traces in the SU structure.' % len(self.traces)
""" Reads the actual traces starting at the current file pointer position to the end of the file.
:param unpack_header: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. :param headonly: Bool. Determines whether or not the actual data records will be unpacked. Useful if one is just interested in the headers. Defaults to False. """ # Big loop to read all data traces. # Read and as soon as the trace header is too small abort. # Always unpack with IEEE unpack_headers=unpack_headers, headonly=headonly)
""" Write a SU Y file to file which is either a file like object with a write method or a filename string.
If endian is set it will be enforced. """ self._write(file, endian=endian)
""" Write a SU Y file to file which is either a file like object with a write method or a filename string.
If endian is set it will be enforced. """ # Write all traces.
""" Reads a Seismic Unix (SU) file and returns a SUFile object.
:param file: Open file like object or a string which will be assumed to be a filename. :param endian: String that determines the endianness of the file. Either '>' for big endian or '<' for little endian. If it is None, obspy.segy will try to autodetect the endianness. The endianness is always valid for the whole file. :param unpack_header: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. :param headonly: Bool. Determines whether or not the actual data records will be unpacked. Useful if one is just interested in the headers. Defaults to False. """ # Open the file if it is not a file like object. hasattr(file, 'seek'): unpack_headers=unpack_headers, headonly=headonly) # Otherwise just read it. headonly=headonly)
""" Reads on open file object and returns a SUFile object.
:param file: Open file like object. :param endian: String that determines the endianness of the file. Either '>' for big endian or '<' for little endian. If it is None, obspy.segy will try to autodetect the endianness. The endianness is always valid for the whole file. :param unpack_header: Bool. Determines whether or not all headers will be unpacked during reading the file. Has a huge impact on the memory usage and the performance. They can be unpacked on-the-fly after being read. Defaults to False. :param headonly: Bool. Determines whether or not the actual data records will be unpacked. Useful if one is just interested in the headers. Defaults to False. """ headonly=headonly)
""" Takes an open file and tries to determine the endianness of a Seismic Unix data file by doing some sanity checks with the unpacked header values.
Returns False if the sanity checks failed and the endianness otherwise.
It is assumed that the data is written as 32bit IEEE floating points in either little or big endian.
The test currently can only identify SU files in which all traces have the same length. It basically just makes a sanity check for various fields in the Trace header. """ else: # Also has to be a multiple of 4 in length because every header is 400 long # and every data value 4 byte long. # Jump to the number of samples field in the trace header. # Jump to the beginning of the year fields. # Jump to previous position. # Unpack in little and big endian. # Check if both work. # If None works return False. # Check if the other header values make sense. # Make a sanity check for each. # XXX: The arbitrary maximum of the sample interval is 10 seconds. continue # Some programs write two digit years. (this_year < 0 or this_year >= 100): continue # 9999 is often used as a placeholder continue continue continue continue return False else: # XXX: In the unlikely case both byteorders pass the sanity checks # something else should be checked. Currently it is not. msg = """ Both possible byteorders passed all sanity checks. Please contact the ObsPy developers so they can implement additional tests. """.strip() raise Exception(msg) |