From ae2e33ebcf1e78f6d3b1174625ba71e6aaa915a5 Mon Sep 17 00:00:00 2001 From: Jeremy Fee <jmfee@usgs.gov> Date: Thu, 12 May 2016 15:43:03 -0600 Subject: [PATCH] Implement common TimeseriesFactory._put_timeseries method, integrate into IAGA factory --- geomagio/TimeseriesFactory.py | 78 ++++++++++++++++- geomagio/iaga2002/IAGA2002Factory.py | 98 ++++------------------ test/iaga2002_test/IAGA2002Factory_test.py | 24 ------ 3 files changed, 90 insertions(+), 110 deletions(-) delete mode 100644 test/iaga2002_test/IAGA2002Factory_test.py diff --git a/geomagio/TimeseriesFactory.py b/geomagio/TimeseriesFactory.py index 443b1519f..2d9ec3f81 100644 --- a/geomagio/TimeseriesFactory.py +++ b/geomagio/TimeseriesFactory.py @@ -84,13 +84,13 @@ class TimeseriesFactory(object): """ raise NotImplementedError('"get_timeseries" not implemented') - def parse_string(self, iaga2002String): + def parse_string(self, data): """Parse the contents of a string in the format of an IAGA2002 file. Parameters ---------- - iaga2002String : str - string containing IAGA2002 content. + data : str + string containing parsable content. Returns ------- @@ -129,6 +129,20 @@ class TimeseriesFactory(object): """ raise NotImplementedError('"put_timeseries" not implemented') + def write_file(self, fh, timeseries, channels): + """Write timeseries data to the given file object. + + Parameters + ---------- + fh : writable + file handle where data is written. + timeseries : obspy.core.Stream + stream containing traces to store. + channels : list + list of channels to store. + """ + raise NotImplementedError('"write_file" not implemented') + def _get_file_from_url(self, url): """Get a file for writing. @@ -387,3 +401,61 @@ class TimeseriesFactory(object): raise TimeseriesFactoryException( 'Unsupported type "%s"' % type) return type_name + + def _put_timeseries(self, timeseries, starttime=None, endtime=None, + channels=None, type=None, interval=None): + """A basic implementation of put_timeseries using write_file. + + Parameters + ---------- + timeseries : obspy.core.Stream + stream containing traces to store. + starttime : UTCDateTime + time of first sample in timeseries to store. + uses first sample if unspecified. + endtime : UTCDateTime + time of last sample in timeseries to store. + uses last sample if unspecified. + channels : array_like + list of channels to store, optional. + uses default if unspecified. + type : {'definitive', 'provisional', 'quasi-definitive', 'variation'} + data type, optional. + uses default if unspecified. + interval : {'daily', 'hourly', 'minute', 'monthly', 'second'} + data interval, optional. + uses default if unspecified. + Raises + ------ + TimeseriesFactoryException + if any errors occur. + """ + if not self.urlTemplate.startswith('file://'): + raise TimeseriesFactoryException('Only file urls are supported') + channels = channels or self.channels + type = type or self.type + interval = interval or self.interval + stats = timeseries[0].stats + delta = stats.delta + observatory = stats.station + starttime = starttime or stats.starttime + endtime = endtime or stats.endtime + + urlIntervals = Util.get_intervals( + starttime=starttime, + endtime=endtime, + size=self.urlInterval) + for urlInterval in urlIntervals: + url = self._get_url( + observatory=observatory, + date=urlInterval['start'], + type=type, + interval=interval, + channels=channels) + url_data = timeseries.slice( + starttime=urlInterval['start'], + # subtract delta to omit the sample at end: `[start, end)` + endtime=(urlInterval['end'] - delta)) + url_file = Util.get_file_from_url(url, createParentDirectory=True) + with open(url_file, 'wb') as fh: + self.write_file(fh, url_data, channels) diff --git a/geomagio/iaga2002/IAGA2002Factory.py b/geomagio/iaga2002/IAGA2002Factory.py index 36f479385..9f17624ed 100644 --- a/geomagio/iaga2002/IAGA2002Factory.py +++ b/geomagio/iaga2002/IAGA2002Factory.py @@ -3,7 +3,6 @@ import obspy.core from .. import ChannelConverter from ..TimeseriesFactory import TimeseriesFactory -from ..TimeseriesFactoryException import TimeseriesFactoryException from IAGA2002Parser import IAGA2002Parser from IAGA2002Writer import IAGA2002Writer @@ -105,54 +104,6 @@ class IAGA2002Factory(TimeseriesFactory): stream += obspy.core.Trace(data[channel], stats) return stream - def _get_days(self, starttime, endtime): - """Get days between (inclusive) starttime and endtime. - - Parameters - ---------- - starttime : obspy.core.UTCDateTime - the start time - endtime : obspy.core.UTCDateTime - the end time - - Returns - ------- - array_like - list of times, one per day, for all days between and including - ``starttime`` and ``endtime``. - - Raises - ------ - TimeseriesFactoryException - if starttime is after endtime - """ - if starttime > endtime: - raise TimeseriesFactoryException( - 'starttime must be before endtime') - days = [] - day = starttime - lastday = (endtime.year, endtime.month, endtime.day) - while True: - days.append(day) - if lastday == (day.year, day.month, day.day): - break - # move to next day - day = obspy.core.UTCDateTime(day.timestamp + 86400) - return days - - def write_file(self, fh, timeseries, channels): - """writes timeseries data to the given file object. - - Parameters - ---------- - fh: file object - timeseries : obspy.core.Stream - stream containing traces to store. - channels : array_like - list of channels to store - """ - IAGA2002Writer().write(fh, timeseries, channels) - def put_timeseries(self, timeseries, starttime=None, endtime=None, channels=None, type=None, interval=None): """Store timeseries data. @@ -177,42 +128,23 @@ class IAGA2002Factory(TimeseriesFactory): data interval, optional. uses default if unspecified. """ - if not self.urlTemplate.startswith('file://'): - raise TimeseriesFactoryException('Only file urls are supported') - channels = channels or self.channels - type = type or self.type - interval = interval or self.interval - stats = timeseries[0].stats - observatory = stats.station - starttime = starttime or stats.starttime - endtime = endtime or stats.endtime - days = self._get_days(starttime, endtime) - for day in days: - day_filename = self._get_file_from_url( - self._get_url(observatory, day, type, interval)) - day_timeseries = self._get_slice(timeseries, day, interval) - with open(day_filename, 'wb') as fh: - self.write_file(fh, day_timeseries, channels) - - def _get_slice(self, timeseries, day, interval): - """Get the first and last time for a day + return self._put_timeseries( + timeseries=timeseries, + starttime=starttime, + endtime=endtime, + channels=channels, + type=type, + interval=interval) + + def write_file(self, fh, timeseries, channels): + """writes timeseries data to the given file object. Parameters ---------- + fh: file object timeseries : obspy.core.Stream - timeseries to slice - day : UTCDateTime - time in day to slice - - Returns - ------- - obspy.core.Stream - sliced stream + stream containing traces to store. + channels : array_like + list of channels to store """ - day = day.datetime - start = obspy.core.UTCDateTime(day.year, day.month, day.day, 0, 0, 0) - if interval == 'minute': - end = start + 86340.0 - else: - end = start + 86399.999999 - return timeseries.slice(start, end) + IAGA2002Writer().write(fh, timeseries, channels) diff --git a/test/iaga2002_test/IAGA2002Factory_test.py b/test/iaga2002_test/IAGA2002Factory_test.py deleted file mode 100644 index 388ef6870..000000000 --- a/test/iaga2002_test/IAGA2002Factory_test.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Tests for IAGA2002Factory.""" - -from geomagio.iaga2002 import IAGA2002Factory -from obspy.core.utcdatetime import UTCDateTime -from nose.tools import assert_equals - - -def test__get_days(): - """iaga2002_test.IAGA2002Factory_test.test__get_days() - - Call the _get_days method with starttime and endtime separated by more - than one day. - Verify it returns all days between the given starttime and endtime. - """ - starttime = UTCDateTime('2014-01-01') - endtime = UTCDateTime('2014-01-07') - assert_equals(IAGA2002Factory()._get_days(starttime, endtime), [ - UTCDateTime('2014-01-01'), - UTCDateTime('2014-01-02'), - UTCDateTime('2014-01-03'), - UTCDateTime('2014-01-04'), - UTCDateTime('2014-01-05'), - UTCDateTime('2014-01-06'), - UTCDateTime('2014-01-07')]) -- GitLab