| |
| """ |
| Convenience class for iterating over miniSEED records in a file. |
| |
| Version 2017.114 |
| """ |
| from __future__ import (absolute_import, division, print_function, |
| unicode_literals) |
| from future.builtins import * |
|
|
| import ctypes as C |
| import os |
|
|
| from obspy import UTCDateTime |
| from obspy.io.mseed.headers import (HPTMODULUS, MS_NOERROR, MS_ENDOFFILE, |
| MSFileParam, MSRecord, clibmseed) |
|
|
|
|
| class MSR_iterator(object): |
| """ |
| Class for iterating through miniSEED records in a file. |
| |
| :ivar msr: MSRecord (pointer to) |
| :ivar msf: MSFileparam (pointer to) |
| :ivar file: filename |
| :ivar offset: Current offset |
| |
| :param filename: File to read |
| :param startoffset: Offset in bytes to start reading the file |
| :param reclen: If reclen is 0 the length of the first record is auto- |
| detected. All subsequent records are then expected to have the |
| same record length. If reclen is negative the length of every |
| record is automatically detected. Defaults to -1. |
| :param dataflag: Controls whether data samples are unpacked, defaults |
| to False. |
| :param skipnotdata: If true (not zero) any data chunks read that to do |
| not have valid data record indicators will be skipped. Defaults to |
| True (1). |
| :param verbose: Controls verbosity from 0 to 2. Defaults to None (0). |
| |
| .. rubric:: Notes |
| |
| The elements of the MSRecord struct are available through `contents` |
| on the pointer to the MSrecord, e.g. `MSR_iterator.msr.contents.reclen`. |
| |
| The raw record as a byte array is available at: |
| `MSR_iterator.msr.contents.record` |
| and can be used with Python I/O routines using: |
| `ctypes.string_at(MSR_iterator.msr.contents.record, MSR_iterator.msr.contents.reclen)) |
| |
| .. rubric:: Example |
| |
| from future.builtins import * |
| |
| from msriterator import MSR_iterator |
| |
| mseedfile = "test.mseed" |
| |
| for msri in MSR_iterator(filename=mseedfile, dataflag=False): |
| |
| print ("{:d}: {}, reclen: {}, samples: {}, starttime: {}, endtime: {}". |
| format(msri.get_offset(), |
| msri.get_srcname(quality=False), |
| msri.msr.contents.reclen, |
| msri.msr.contents.samplecnt, |
| msri.get_starttime(), |
| msri.get_endtime())) |
| """ |
|
|
| def __init__(self, filename, startoffset=0, |
| reclen=-1, dataflag=0, skipnotdata=1, verbose=0, |
| raise_errors=True): |
|
|
| self.msr = clibmseed.msr_init(C.POINTER(MSRecord)()) |
| self.msf = C.POINTER(MSFileParam)() |
| self.file = filename |
|
|
| |
| self._c_off_t = C.c_long |
|
|
| self.fpos = self._c_off_t(0) |
| if startoffset != 0: |
| self.fpos = self._c_off_t(-startoffset) |
|
|
| self.reclen = reclen |
| self.dataflag = 1 if dataflag else 0 |
| self.skipnotdata = 1 if skipnotdata else 0 |
| self.verbose = verbose |
| self.raise_errors = raise_errors |
|
|
| def __iter__(self): |
| return self |
|
|
| def __next__(self): |
| """ |
| Read next record from file. |
| """ |
| errcode = clibmseed.ms_readmsr_r(C.pointer(self.msf), |
| C.pointer(self.msr), |
| self.file.encode('ascii', 'strict'), |
| self.reclen, C.byref(self.fpos), None, |
| self.skipnotdata, self.dataflag, self.verbose) |
|
|
| if errcode == MS_ENDOFFILE: |
| raise StopIteration() |
|
|
| if self.raise_errors: |
| if errcode != MS_NOERROR: |
| raise Exception("Error %d in ms_readmsr_r" % errcode) |
|
|
| return self |
|
|
| def __del__(self): |
| """ |
| Method for deallocating MSFileParam and MSRecord structures. |
| """ |
| errcode = clibmseed.ms_readmsr_r(C.pointer(self.msf), |
| C.pointer(self.msr), |
| None, -1, None, None, 0, 0, 0) |
| if errcode != MS_NOERROR: |
| raise Exception("Error %d in ms_readmsr_r" % errcode) |
|
|
| def get_srcname(self, quality=False): |
| """ |
| Return record start time |
| """ |
| srcname = C.create_string_buffer(50) |
|
|
| clibmseed.msr_srcname.argtypes = [C.POINTER(MSRecord), |
| C.POINTER(C.c_char), |
| C.c_int] |
| clibmseed.msr_srcname.restype = C.POINTER(C.c_char) |
|
|
| if quality: |
| clibmseed.msr_srcname(self.msr, srcname, 1) |
| else: |
| clibmseed.msr_srcname(self.msr, srcname, 0) |
|
|
| return srcname.value.decode('utf-8') |
|
|
| def get_starttime(self): |
| """ |
| Return record start time as UTCDateTime |
| """ |
| hptime = self.msr.contents.starttime |
| return UTCDateTime(hptime / HPTMODULUS) |
|
|
| def get_endtime(self): |
| """ |
| Return record end time as UTCDateTime |
| """ |
| hptime = clibmseed.msr_endtime(self.msr) |
| return UTCDateTime(hptime / HPTMODULUS) |
|
|
| def get_startepoch(self): |
| """ |
| Return record start time as epoch time |
| """ |
| return self.msr.contents.starttime / HPTMODULUS |
|
|
| def get_endepoch(self): |
| """ |
| Return record end time as epoch time |
| """ |
| hptime = clibmseed.msr_endtime(self.msr) |
| return hptime / HPTMODULUS |
|
|
| def set_offset(self, value): |
| """ |
| Set file reading position |
| """ |
| self.fpos = self._c_off_t(-value) |
|
|
| def get_offset(self): |
| """ |
| Return offset into file for current record |
| """ |
| return self.fpos.value |
|
|
| offset = property(get_offset, set_offset) |
|
|