diff --git a/geomagio/pcdcp/PCDCPFactory.py b/geomagio/pcdcp/PCDCPFactory.py index fb3d9ea8c499680e6697ec5a94ea37e2da7945c9..df94833c2eb00cc6f7f4a6751a6f602f71290491 100644 --- a/geomagio/pcdcp/PCDCPFactory.py +++ b/geomagio/pcdcp/PCDCPFactory.py @@ -10,6 +10,7 @@ from .PCDCPWriter import PCDCPWriter # pattern for pcdcp file names PCDCP_FILE_PATTERN = '%(obs)s%(y)s%(j)s.%(i)s' +# note: seconds files end in .raw after 2008, .sec or .Sec on or before class PCDCPFactory(TimeseriesFactory): @@ -53,20 +54,17 @@ class PCDCPFactory(TimeseriesFactory): parser = PCDCPParser() parser.parse(data) - yr = int(parser.header['year']) - yrday = int(parser.header['yearday']) + # minutes files times are 4 characters long (1440) + # seconds files times are 5 characters long (86400) + sample_periods = {4: 60.0, 5: 1.0} + sample_period = sample_periods[len(parser.times[0])] - begin = int(parser.times[0]) - startHour = int(begin / 60.0) - startMinute = int(begin % 60.0) - ending = int(parser.times[-1]) - endHour = int(ending / 60.0) - endMinute = int(ending % 60.0) + yr = parser.header['year'] + yrday = parser.header['yearday'] - starttime = obspy.core.UTCDateTime(year=yr, julday=yrday, - hour=startHour, minute=startMinute) - endtime = obspy.core.UTCDateTime(year=yr, julday=yrday, hour=endHour, - minute=endMinute) + startday = obspy.core.UTCDateTime(yr + yrday) + starttime = startday + int(parser.times[0]) * sample_period + endtime = startday + int(parser.times[-1]) * sample_period data = parser.data length = len(data[list(data)[0]]) diff --git a/geomagio/pcdcp/PCDCPParser.py b/geomagio/pcdcp/PCDCPParser.py index f82a51a1d62a651ce2bb5c0044ad113ba4dcc7b1..1c6c87d92943923b8e7a36365a859ee1493e4ce8 100644 --- a/geomagio/pcdcp/PCDCPParser.py +++ b/geomagio/pcdcp/PCDCPParser.py @@ -29,7 +29,11 @@ class PCDCPParser(object): def __init__(self): """Create a new PCDCP parser.""" # header fields + self.header_fields = ['station', 'year', 'yearday', 'date', + 'orientation', 'resolution', 'Version'] self.header = {} + # resolution (float) + self.resolution = 0.0 # array of channel names self.channels = [] # timestamps of data (datetime.datetime) @@ -64,11 +68,10 @@ class PCDCPParser(object): Adds value to ``self.header``. """ - self.header['header'] = line - self.header['station'] = line[0:3] - self.header['year'] = line[5:9] - self.header['yearday'] = line[11:14] - self.header['date'] = line[16:25] + self.header = dict(zip(self.header_fields, + line.split(None, len(self.header_fields)))) + + self.resolution = float(self.header['resolution'].split('nT')[0]) return @@ -78,13 +81,9 @@ class PCDCPParser(object): Adds time to ``self.times``. Adds channel values to ``self.data``. """ - t, d1, d2, d3, d4 = self._parsedata - - t.append(line[0:4]) - d1.append(int(line[5:13])) - d2.append(int(line[14:22])) - d3.append(int(line[23:31])) - d4.append(int(line[32:40])) + values = line.split() + for (value, column) in zip(values, self._parsedata): + column.append(value) def _post_process(self): """Post processing after data is parsed. @@ -98,7 +97,8 @@ class PCDCPParser(object): data = numpy.array(data, dtype=numpy.float64) # filter empty values data[data == NINES] = numpy.nan - data = numpy.divide(data, 100) + data[data == NINES_RAW] = numpy.nan + data = numpy.multiply(data, self.resolution) self.data[channel] = data self._parsedata = None diff --git a/test/pcdcp_test/PCDCPFactory_test.py b/test/pcdcp_test/PCDCPFactory_test.py index 7466a0f107eed25342204070dc850adaa8d8f7fd..9b4b6ce149b3a552ee43c4b8d16968b4be970846 100644 --- a/test/pcdcp_test/PCDCPFactory_test.py +++ b/test/pcdcp_test/PCDCPFactory_test.py @@ -13,6 +13,15 @@ pcdcpString = \ 0003 2086239 -5632 4745739 5237796 0004 2086198 -5626 4745743 5237786""" +pcdcpString_seconds = \ +"""BOU 2015 001 01-Jan-15 HEZF 0.001nT File Version 2.00 +00000 20861520 -57095 47457409 52377630 +00001 20861533 -57096 47457397 52377650 +00002 20861554 -57077 47457391 52377650 +00003 20861578 -57068 47457389 52377680 +00004 20861600 -57068 47457384 52377660 +""" + def test_parse_string(): """pcdcp_test.PCDCPFactory_test.test_parse_string() @@ -27,3 +36,30 @@ def test_parse_string(): assert_equals(stream[0].stats.station, 'BOU') assert_equals(stream[0].stats.starttime, UTCDateTime('2015-01-01T00:00:00.000000Z')) + h = stream.select(channel='H')[0] + assert_equals(h.data[1], 20861.90) + assert_equals(stream[0].stats.endtime, + UTCDateTime('2015-01-01T00:04:00.000000Z')) + z = stream.select(channel='Z')[0] + assert_equals(z.data[-1], 47457.43) + + +def test_parse_string_seconds(): + """pcdcp_test.PCDCPFactory_test.test_parse_string_seconds() + + Send a PCDCP seconds file string into parse_string to make sure a well + formed stream is created with proper values + """ + stream = PCDCPFactory().parse_string(pcdcpString_seconds) + + assert_equals(type(stream), Stream) + assert_equals(stream[0].stats.network, 'NT') + assert_equals(stream[0].stats.station, 'BOU') + assert_equals(stream[0].stats.starttime, + UTCDateTime('2015-01-01T00:00:00.000000Z')) + h = stream.select(channel='H')[0] + assert_equals(h.data[0], 20861.520) + assert_equals(stream[0].stats.endtime, + UTCDateTime('2015-01-01T00:00:04.000000Z')) + z = stream.select(channel='Z')[0] + assert_equals(z.data[-1], 47457.384) diff --git a/test/pcdcp_test/PCDCPParser_test.py b/test/pcdcp_test/PCDCPParser_test.py index e31a4f8ba7de6ca8905a576dfe4a866ac71fc8ee..7ff78762dfee85248d29d66f707697971ff3e99b 100644 --- a/test/pcdcp_test/PCDCPParser_test.py +++ b/test/pcdcp_test/PCDCPParser_test.py @@ -18,8 +18,24 @@ BOU 2015 001 01-Jan-15 HEZF 0.01nT File Version 2.00 0008 2086278 -5571 4745734 5237808 """ +PCDCP_EXAMPLE_SECOND = \ +""" +BOU 2015 001 01-Jan-15 HEZF 0.001nT File Version 2.00 +00000 20861520 -57095 47457409 52377630 +00001 20861533 -57096 47457397 52377650 +00002 20861554 -57077 47457391 52377650 +00003 20861578 -57068 47457389 52377680 +00004 20861600 -57068 47457384 52377660 +00005 20861640 -57047 47457388 52377690 +00006 20861654 -57039 47457378 52377650 +00007 20861699 -57026 47457377 52377690 +00008 20861721 -56995 47457365 52377680 +00009 20861743 -56977 47457350 52377680 +00010 20861750 -56968 47457349 52377690 +""" -def test__parse_header(): + +def test_parse_header(): """pcdcp_test.PCDCPParser_test.test_parse_header() Call the _parse_header method with a header. @@ -27,9 +43,27 @@ def test__parse_header(): """ parser = PCDCPParser() parser._parse_header('BOU 2015 001 01-Jan-15 HEZF 0.01nT' + - ' File Version 2.00') + ' File Version 2.00') + + assert_equals(parser.header['date'], '01-Jan-15') + assert_equals(parser.header['station'], 'BOU') + assert_equals(parser.header['year'], '2015') + assert_equals(parser.header['yearday'], '001') + assert_equals(parser.header['resolution'], '0.01nT') + + +def test_parse_header_sec(): + """pcdcp_test.PCDCPParser_test.test_parse_header_sec() + + Call the _parse_header method with a pcdcp seconds file '.raw' + header. Verify the header name and value are split correctly. + """ + parser = PCDCPParser() + parser._parse_header('BOU 2015 001 01-Jan-15 HEZF 0.001nT' + + ' File Version 2.00') assert_equals(parser.header['date'], '01-Jan-15') assert_equals(parser.header['station'], 'BOU') assert_equals(parser.header['year'], '2015') assert_equals(parser.header['yearday'], '001') + assert_equals(parser.header['resolution'], '0.001nT')