Coverage for /opt/obspy/update-docs/src/obspy/obspy/mseed/core : 85%

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 -*- MSEED bindings to ObsPy core module. """
SAMPLESIZES, VALID_RECORD_LENGTHS, HPTERROR, SelectTime, Selections, \ blkt_1001_s, VALID_CONTROL_HEADERS, SEED_CONTROL_HEADERS
""" Checks whether a file is Mini-SEED/full SEED or not.
:type filename: string :param filename: Mini-SEED/full SEED file to be checked. :rtype: bool :return: ``True`` if a Mini-SEED file.
This method only reads the first seven bytes of the file and checks whether its a Mini-SEED or full SEED file.
It also is true for fullSEED files because libmseed can read the data part of fullSEED files. If the method finds a fullSEED file it also checks if it has a data part and returns False otherwise.
Thus it cannot be used to validate a Mini-SEED or SEED file. """ # File has less than 7 characters # Sequence number must contains a single number or be empty # Check for any valid control header types. # Check if Full-SEED # Parse the whole file and check whether it has has a data record. # search for blockettes 010 or 008 # the next for bytes are the record length # as we are currently at position 7 (fp.read(3) fp.read(4)) # we need to subtract this first before we seek # to the appropriate position # break after 3 cycles return False # Try to get a record length. # Jump to the second record. # Loop over all records and return True if one record is a data # record return False
sourcename=None, reclen=None, recinfo=True, details=False, **kwargs): """ Reads a Mini-SEED file and returns a Stream object.
.. warning:: This function should NOT be called directly, it registers via the ObsPy :func:`~obspy.core.stream.read` function, call this instead.
:param mseed_object: Filename or open file like object that contains the binary Mini-SEED data. Any object that provides a read() method will be considered to be a file like object. :type starttime: UTCDateTime :param starttime: Only read data samples after or at the starttime. :type endtime: UTCDateTime :param endtime: Only read data samples before or at the starttime. :param headonly: Determines whether or not to unpack the data or just read the headers. :type sourcename: str :param sourcename: Sourcename has to have the structure 'network.station.location.channel' and can contain globbing characters. Defaults to ``None``. :param reclen: If it is None, it will be automatically determined for every record. If it is known, just set it to the record length in bytes which will increase the reading speed slightly. :type recinfo: bool, optional :param recinfo: If ``True`` the byteorder, record length and the encoding of the file will be read and stored in every Trace's stats.mseed AttribDict. These stored attributes will also be used while writing a Mini-SEED file. Only the very first record of the file will be read and all following records are assumed to be the same. Defaults to ``True``. :type details: bool, optional :param details: If ``True`` read additional information: timing quality and availability of calibration information. Note, that the traces are then also split on these additional information. Thus the number of traces in a stream will change. Details are stored in the mseed stats AttribDict of each trace. -1 specifies for both cases, that these information is not available. ``timing_quality`` specifies the timing quality from 0 to 100 [%]. ``calibration_type`` specifies the type of available calibration information: 1 == Step Calibration, 2 == Sine Calibration, 3 == Pseudo-random Calibration, 4 == Generic Calibration and -2 == Calibration Abort.
.. rubric:: Example
>>> from obspy import read >>> st = read("/path/to/two_channels.mseed") >>> print(st) # doctest: +ELLIPSIS 2 Trace(s) in Stream: BW.UH3..EHE | 2010-06-20T00:00:00.279999Z - ... | 200.0 Hz, 386 samples BW.UH3..EHZ | 2010-06-20T00:00:00.279999Z - ... | 200.0 Hz, 386 samples
>>> from obspy import UTCDateTime >>> st = read("/path/to/test.mseed", ... starttime=UTCDateTime("2003-05-29T02:16:00"), ... selection="NL.*.*.?HZ") >>> print(st) # doctest: +ELLIPSIS 1 Trace(s) in Stream: NL.HGN.00.BHZ | 2003-05-29T02:15:59.993400Z - ... | 40.0 Hz, 5629 samples """ # Parse the headonly and reclen flags. else: elif reclen is not None and reclen not in VALID_RECORD_LENGTHS: msg = 'Invalid record length. Autodetection will be used.' warnings.warn(msg) reclen = -1 else: reclen = int(log(reclen, 2))
# The quality flag is no more supported. Raise a warning. 'obspy.mseed. obspy.mseed.util has some functions with similar' + \ ' behaviour.'
# Parse some information about the file. # Only keep information relevant for the whole file. 'filesize': info['filesize'], 'record_length': info['record_length'], 'byteorder': info['byteorder'], 'number_of_records': info['number_of_records']}
# If its a filename just read it. # Read to NumPy array which is used as a buffer.
# Get the record length
# Search for data records and pass only the data part to the underlying C # routine. # 0 to 9 are defined in a row in the ASCII charset. # Small function to check whether an array of ASCII values contains only # digits. # This should never happen (buffer[offset + 6] not in VALID_CONTROL_HEADERS): msg = 'Not a valid (Mini-)SEED file' raise Exception(msg)
# If no selection is given pass None to the C function. else: msg = 'starttime needs to be a UTCDateTime object' raise ValueError(msg) util._convertDatetimeToMSTime(starttime) else: # HPTERROR results in no starttime. msg = 'endtime needs to be a UTCDateTime object' raise ValueError(msg) util._convertDatetimeToMSTime(endtime) else: # HPTERROR results in no starttime. msg = 'sourcename needs to be a string' raise ValueError(msg) # libmseed uses underscores as separators and allows filtering # after the dataquality which is disabled here to not confuse # users. (* == all data qualities) else:
# Use a callback function to allocate the memory and keep track of the # data. # XXX: Do this properly! # Define Python callback function for use in C function. Return a long so # it hopefully works on 32 and 64 bit systems.
reclen, 0, C.c_int(details), allocData)
# XXX: Check if the freeing works.
# Return stream if not traces are found. except ValueError: clibmseed.lil_free(lil) del lil return Stream()
# Init header with the essential information. 'station': currentID.station.strip(), 'location': currentID.location.strip(), 'channel': currentID.channel.strip(), 'mseed': {'dataquality': currentID.dataquality}} # Loop over segments. util._convertMSTimeToDatetime(currentSegment.starttime) # TODO: write support is missing timing_quality = -1 currentSegment.calibration_type
# The data always will be in sequential order. else: # Make sure to init the number of samples. # Append information if necessary. # A Null pointer access results in a ValueError
flush=1, verbose=0, **_kwargs): """ Write Mini-SEED file from a Stream object.
.. warning:: This function should NOT be called directly, it registers via the the :meth:`~obspy.core.stream.Stream.write` method of an ObsPy :class:`~obspy.core.stream.Stream` object, call this instead.
:type stream: :class:`~obspy.core.stream.Stream` :param stream: A Stream object. :type filename: str :param filename: Name of the output file :type encoding: int or str, optional :param encoding: Should be set to one of the following supported Mini-SEED data encoding formats: ASCII (``0``)*, INT16 (``1``), INT32 (``3``), FLOAT32 (``4``)*, FLOAT64 (``5``)*, STEIM1 (``10``) and STEIM2 (``11``)*. Default data types a marked with an asterisk. Currently INT24 (``2``) is not supported due to lacking NumPy support. :type reclen: int, optional :param reclen: Should be set to the desired data record length in bytes which must be expressible as 2 raised to the power of X where X is between (and including) 8 to 20. Defaults to 4096 :type byteorder: [``0`` or ``'<'`` | ``1`` or ``'>'`` | ``'='``], optional :param byteorder: Must be either ``0`` or ``'<'`` for LSBF or little-endian, ``1`` or ``'>'`` for MBF or big-endian. ``'='`` is the native byteorder. If ``-1`` it will be passed directly to libmseed which will also default it to big endian. Defaults to big endian. :type flush: int, optional :param flush: If it is not zero all of the data will be packed into records, otherwise records will only be packed while there are enough data samples to completely fill a record. :type verbose: int, optional :param verbose: Controls verbosity, a value of zero will result in no diagnostic output.
.. note:: The reclen, encoding and byteorder keyword arguments can be set in the stats.mseed of each :class:`~obspy.core.trace.Trace` as well as as kwargs of this function. If both are given the kwargs will be used.
.. rubric:: Example
>>> from obspy import read >>> st = read() >>> st.write('filename.mseed', format='MSEED') # doctest: +SKIP """ # Some sanity checks for the keyword arguments. 'of 2 to the power of X where 8 <= X <= 20.' # If not elif because NATIVE_BYTEORDER is '<' or '>'. else: msg = "Invalid byteorder. It must be either '<', '>', '=', " + \ "0, 1 or -1" raise ValueError(msg)
# Check if encoding kwarg is set and catch invalid encodings. # XXX: Currently INT24 is not working due to lacking NumPy support.
in encoding_strings: else:
# The data might need to be modified. To not modify the input data keep # references of which data to finally write. # Loop over every trace and figure out the correct settings. # Create temporary dict for storing information while writing.
# Figure out whether or not to use Blockette 1001. This check is done # once to ensure that Blockette 1001 is either written for every record # in the file or for none. It checks the starttime as well as the # sampling rate. If either one has a precision of more than 100 # microseconds, Blockette 1001 will be written for every record. (1.0 / trace.stats.sampling_rate * HPTMODULUS) % 100 != 0:
# Determine if a blockette 100 will be needed to represent the input # sample rate or if the sample rate in the fixed section of the data # header will suffice (see ms_genfactmult in libmseed/genutils.c) trace.stats.sampling_rate <= (1.0 / 32727.0): else:
# Set data quality to indeterminate (= D) if it is not already set. trace.stats['mseed']['dataquality'].upper() # Sanity check for the dataquality to get a nice Python exception # instead of a C error. '.mseed.dataquality\n' + \ 'The dataquality for Mini-SEED must be either D, R, Q ' + \ 'or M. See the SEED manual for further information.'
# Check that data is of the right type. msg = "Unsupported data type %s" % type(trace.data) + \ " for Stream[%i].data." % _i raise ValueError(msg)
# Check if ndarray is contiguous (see #192, #193) ".data. Trying to fix array."
# Handle the record length. hasattr(stats.mseed, 'record_length'): else: msg = 'Invalid record length in Stream[%i].stats.' % _i + \ 'mseed.reclen.\nThe record length must be a value ' + \ 'of 2 to the power of X where 8 <= X <= 20.' raise ValueError(msg) else:
# Handle the byteorder. hasattr(stats.mseed, 'byteorder'): trace_attr['byteorder'] = stats.mseed.byteorder if NATIVE_BYTEORDER == '<': trace_attr['byteorder'] = 0 else: trace_attr['byteorder'] = 1 else: msg = "Invalid byteorder in Stream[%i].stats." % _i + \ "mseed.byteorder. It must be either '<', '>', '='," + \ " 0, 1 or -1" raise ValueError(msg) else: if NATIVE_BYTEORDER == '<': trace_attr['byteorder'] = 0 else: trace_attr['byteorder'] = 1
# Handle the encoding. # Check if the dtype for all traces is compatible with the enforced # encoding. Wrong dtype for Stream[%i].data for encoding %s. Please change the dtype of your data or use an appropriate encoding. See the obspy.mseed documentation for more information. """ % (_i, id) 'encoding'): # Check if the encoding is valid. mseed_encoding in encoding_strings: else: msg = 'Invalid encoding %s in ' + \ 'Stream[%i].stats.mseed.encoding. Valid encodings: %s' raise ValueError(msg % (mseed_encoding, _i, encoding_strings)) # Check if the encoding matches the data's dtype. 'trace.stats.mseed.encoding does not match the ' + \ 'dtype of the data.\nA suitable encoding will ' + \ 'be chosen.' trace_attr['encoding'] = None # automatically detect encoding if no encoding is given. else: (trace.data.dtype, _i)
# Convert data if necessary, otherwise store references in list. # INT16 needs INT32 data type else:
# Do some final sanity checks and raise a warning if a file will be written # with more than one different encoding, record length or byteorder. 'This might have a negative influence on the compatibility ' + \ 'with other programs.' warnings.warn(msg % 'record lengths') warnings.warn(msg % 'byteorders')
# Open filehandler or use an existing file like object. else: f = filename
# Loop over every trace and finally write it to the filehandler. continue # Create C struct MSTrace.
# Initialize packedsamples pointer for the mst_pack function
# Callback function for mst_pack to actually write the file # Define Python callback function for use in C function C.c_void_p)(record_handler)
# Fill up msr record structure, this is already contained in # mstg, however if blk1001 is set we need it anyway
# Only use Blockette 1001 if necessary. size, 1001, 0) # Usually returns a pointer to the added blockette in the # blockette link chain and a NULL pointer if it fails. # NULL pointers have a false boolean value according to the # ctypes manual. clibmseed.msr_free(C.pointer(msr)) del mstg, msr raise Exception('Error in msr_addblockette') # Only use Blockette 100 if necessary. size, 100, 0) # Usually returns a pointer to the added blockette in the # blockette link chain and a NULL pointer if it fails. # NULL pointers have a false boolean value according to the # ctypes manual. clibmseed.msr_free(C.pointer(msr)) del mstg, msr raise Exception('Error in msr_addblockette')
# Pack mstg into a MSEED file using the callback record_handler as # write method. trace_attr['reclen'], trace_attr['encoding'], trace_attr['byteorder'], C.byref(packedsamples), flush, verbose, msr)
msg = ("Did not write any data for trace '%s' even though it " "contains data values.") % trace raise ValueError(ms) clibmseed.msr_free(C.pointer(msr)) del mst, msr raise Exception('Error in mst_pack') # Deallocate any allocated memory. # Close if its a file handler.
""" Class that transforms a ObsPy Trace object to a libmseed internal MSTrace struct. """ """ The init function requires a ObsPy Trace object which will be used to fill self.mstg. """ # Figure out the datatypes.
# Set the header values. util._convertDatetimeToMSTime(trace.stats.starttime) util._convertDatetimeToMSTime(trace.stats.endtime)
# libmseed expects data in the native byteorder.
# Copy the data. The copy appears to be necessary so that Python's # garbage collection does not interfere it.
bytecount)
""" Frees all allocated memory. """ # This also frees the data of the associated datasamples pointer.
if __name__ == '__main__': import doctest doctest.testmod(exclude_empty=True) |