Commit 1eb82c95 authored by Javier Quinteros's avatar Javier Quinteros
Browse files

Open proper file based on time window selection.

Add sampling_rate, start and endtime to the TDMS class.
parent aff0599e
......@@ -22,6 +22,8 @@ import logging
import struct
import datetime
import numpy as np
from math import floor
from math import ceil
class TDMS(object):
......@@ -43,8 +45,15 @@ class TDMS(object):
self.__chstep = chstep
# Timewindow selection
self.__starttime = starttime
self.__endtime = endtime
self.__twstart = starttime
self.__twend = endtime
# Available time window
self.starttime = None
self.endtime = None
# Sampling Rate
self.sampling_rate = None
# Name of file
self.__filename = filename
......@@ -97,7 +106,16 @@ class TDMS(object):
logs = logging.getLogger('Open file')
logs.setLevel(self.__loglevel)
filename = os.path.join(self.__directory, self.__available[0]['name'])
for idx, fi in enumerate(self.__available):
if fi['dt'] > self.__twstart:
if not idx:
raise Exception('Data not available in the specified time window')
filename = os.path.join(self.__directory, self.__available[idx-1]['name'])
break
else:
raise Exception('Data not available in the specified time window')
# filename = os.path.join(self.__directory, self.__available[0]['name'])
self.__fi = open(filename, 'rb')
leadin = self.__fi.read(self.__HEADERLEN)
......@@ -177,6 +195,20 @@ class TDMS(object):
logs.debug('No raw data assigned to this segment')
self.metadata[obj]['data'] = False
self.__readproperties(self.metadata[obj])
try:
if self.sampling_rate is None:
self.sampling_rate = self.metadata[obj]['SamplingFrequency[Hz]']
except:
pass
try:
if self.starttime is None:
self.starttime = self.metadata[obj]['GPSTimeStamp']
except:
pass
continue
elif not rawDataIdx:
......@@ -212,6 +244,16 @@ class TDMS(object):
self.datatypesize = self.__data2mask[datatype][1]
self.numChannels = numChannels
self.samples = int((self.__segmentOffset - self.__dataOffset) / numChannels / self.datatypesize)
# Calculate endtime based on the number of samples declared and the sampling rate
self.endtime = self.starttime + datetime.timedelta(seconds=(self.samples-1)/self.sampling_rate)
self.__samplestart = floor((self.__twstart - self.starttime).total_seconds() * self.sampling_rate)
if self.__twend >= self.endtime:
self.__sampleend = self.samples-1
else:
self.__sampleend = ceil((self.__twend - self.starttime).total_seconds() * self.sampling_rate)
logs.info('Samples: %s' % self.samples)
logs.info('Total chunks size: %s' % (self.__segmentOffset - self.__dataOffset))
logs.info('Length of channel: %d' % ((self.__segmentOffset - self.__dataOffset)/numChannels/self.__data2mask[datatype][1]))
......@@ -240,12 +282,16 @@ class TDMS(object):
return self.__iter_data__()
def __iter_data__(self):
# Metadata
# Data
logs = logging.getLogger('Iterate Data')
# Loop through channels
for ch in range(self.__chstart, self.__chstop+1, self.__chstep):
yield self.__readdata(channel=ch)
data = self.__readdata(channel=ch)
stats = {'network': 'XX', 'station': 'XXXX', 'location': '',
'channel': str(ch), 'npts': len(data),
'sampling_rate': self.sampling_rate}
yield (data, stats)
def __iter_metadata__(self):
# Metadata
......@@ -263,7 +309,7 @@ class TDMS(object):
logs = logging.getLogger('readvalue')
datatype = self.__readdatatype()
logs.debug('datatype: 0x%x' % datatype)
# logs.debug('datatype: 0x%x' % datatype)
# Consider cases which need another read
# 0x20 is a string. Read again!
......@@ -271,7 +317,7 @@ class TDMS(object):
return self.__readstring()
(mask, numBytes) = self.__data2mask[datatype]
logs.debug('Mask: %s; Bytes: %s' % (mask, numBytes))
# logs.debug('Mask: %s; Bytes: %s' % (mask, numBytes))
# This instruction returns a tuple. Needed for timestamps
result = struct.unpack('%c%s' % (self.__endian, mask), self.__fi.read(numBytes))
......@@ -282,7 +328,7 @@ class TDMS(object):
# Disassemble the tuple if not a timestamp
result = result[0]
logs.debug('result: %s' % result)
# logs.debug('result: %s' % result)
return result
def __readproperties(self, result=dict()):
......@@ -294,10 +340,9 @@ class TDMS(object):
for prop in range(numProps):
propStr = self.__readstring()
logs.debug('Prop: %s' % propStr)
value = self.__readvalue()
result[propStr] = value
logs.debug(value)
logs.debug('%s: %s' % (propStr, value))
return result
......@@ -306,13 +351,13 @@ class TDMS(object):
def __tup2time(self, fraction, seconds):
logs = logging.getLogger('tup2time')
logs.debug('seconds: %s' % seconds)
logs.debug('fraction: %s' % fraction)
# logs.debug('seconds: %s' % seconds)
# logs.debug('fraction: %s' % fraction)
dt1904 = datetime.datetime(1904, 1, 1)
delta = seconds + fraction * 2**(-64)
result = dt1904 + datetime.timedelta(seconds=delta)
logs.debug('Date-time %s' % result)
# logs.debug('Date-time %s' % result)
return result
def __readdata(self, channel=0):
......@@ -322,6 +367,7 @@ class TDMS(object):
# Read all channel in one step
# FIXME Big/Little Endian not set!
# FIXME Start and end sample!
result = np.fromfile(self.__fi, dtype=self.datatype, count=self.samples)
else:
......@@ -332,6 +378,7 @@ class TDMS(object):
for ch in range(self.samples):
# Read from all channels and select the specific one with an index (channel)
# FIXME Big/Little Endian not set!
# FIXME Start and end sample!
result[ch] = np.fromfile(self.__fi, dtype=self.datatype, count=self.numChannels)[channel]
return result
......@@ -357,13 +404,15 @@ def main():
logs = logging.getLogger('OpenFile')
logs.setLevel(args.loglevel)
dt = datetime.datetime(2019, 5, 8, 9, 38, 5, 409000)
dt = datetime.datetime(2019, 5, 8, 9, 37, 50)
td = TDMS(args.filename, directory=args.directory, iterate='D', chstart=800, chstop=801, chstep=5,
starttime=dt, endtime=dt+datetime.timedelta(seconds=30))
starttime=dt, endtime=dt+datetime.timedelta(seconds=10))
with td:
for ch in td:
print(ch)
print(td.starttime, td.endtime)
for data, stats in td:
print(stats)
print(data)
if __name__ == '__main__':
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment