From 3ee542074262872c42dcfede2c14acfbadb7d9d9 Mon Sep 17 00:00:00 2001
From: pcain-usgs <pcain@usgs.gov>
Date: Tue, 10 Aug 2021 17:34:04 -0600
Subject: [PATCH] add_empty_channel in get_timeseries methods

---
 geomagio/TimeseriesFactory.py              |  3 +++
 geomagio/edge/EdgeFactory.py               | 29 +++++++++++++++++++---
 geomagio/edge/MiniSeedFactory.py           | 28 ++++++++++++++++++---
 geomagio/iaga2002/StreamIAGA2002Factory.py |  1 +
 geomagio/imfv122/StreamIMFV122Factory.py   |  1 +
 geomagio/imfv283/GOESIMFV283Factory.py     |  1 +
 geomagio/imfv283/StreamIMFV283Factory.py   |  1 +
 test/edge_test/EdgeFactory_test.py         | 25 +++++++++++++++++++
 8 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/geomagio/TimeseriesFactory.py b/geomagio/TimeseriesFactory.py
index 7446f81ee..064b868d6 100644
--- a/geomagio/TimeseriesFactory.py
+++ b/geomagio/TimeseriesFactory.py
@@ -67,6 +67,7 @@ class TimeseriesFactory(object):
         channels=None,
         type=None,
         interval=None,
+        add_empty_channels: bool = True,
     ):
         """Get timeseries data.
 
@@ -93,6 +94,8 @@ class TimeseriesFactory(object):
         interval : {'day', 'hour', 'minute', 'month', 'second'}
             data interval, optional.
             uses default if unspecified.
+        add_empty_channels
+            if True, returns channels without data as empty traces
 
         Returns
         -------
diff --git a/geomagio/edge/EdgeFactory.py b/geomagio/edge/EdgeFactory.py
index 682d03f73..5dbde248f 100644
--- a/geomagio/edge/EdgeFactory.py
+++ b/geomagio/edge/EdgeFactory.py
@@ -91,7 +91,6 @@ class EdgeFactory(TimeseriesFactory):
     ):
         TimeseriesFactory.__init__(self, observatory, channels, type, interval)
         self.client = earthworm.Client(host, port)
-
         self.observatoryMetadata = observatoryMetadata or ObservatoryMetadata()
         self.tag = tag
         self.locationCode = locationCode
@@ -111,6 +110,7 @@ class EdgeFactory(TimeseriesFactory):
         channels=None,
         type=None,
         interval=None,
+        add_empty_channels: bool = True,
     ):
         """Get timeseries data
 
@@ -128,6 +128,8 @@ class EdgeFactory(TimeseriesFactory):
             data type.
         interval: {'day', 'hour', 'minute', 'second', 'tenhertz'}
             data interval.
+        add_empty_channels
+            if True, returns channels without data as empty traces
 
         Returns
         -------
@@ -159,8 +161,16 @@ class EdgeFactory(TimeseriesFactory):
             timeseries = obspy.core.Stream()
             for channel in channels:
                 data = self._get_timeseries(
-                    starttime, endtime, observatory, channel, type, interval
+                    starttime,
+                    endtime,
+                    observatory,
+                    channel,
+                    type,
+                    interval,
+                    add_empty_channels,
                 )
+                if len(data) == 0:
+                    continue
                 timeseries += data
         finally:
             # restore stdout
@@ -278,7 +288,16 @@ class EdgeFactory(TimeseriesFactory):
             trace.data = numpy.ma.masked_invalid(trace.data)
         return stream
 
-    def _get_timeseries(self, starttime, endtime, observatory, channel, type, interval):
+    def _get_timeseries(
+        self,
+        starttime,
+        endtime,
+        observatory,
+        channel,
+        type,
+        interval,
+        add_empty_channels: bool = True,
+    ):
         """get timeseries data for a single channel.
 
         Parameters
@@ -295,6 +314,8 @@ class EdgeFactory(TimeseriesFactory):
             data type {definitive, quasi-definitive, variation}
         interval : str
             interval length {minute, second}
+        add_empty_channels
+            if True, returns channels without data as empty traces
 
         Returns
         -------
@@ -325,7 +346,7 @@ class EdgeFactory(TimeseriesFactory):
         for trace in data:
             trace.data = trace.data.astype("i4")
         data.merge()
-        if data.count() == 0:
+        if data.count() == 0 and add_empty_channels:
             data += TimeseriesUtility.create_empty_trace(
                 starttime,
                 endtime,
diff --git a/geomagio/edge/MiniSeedFactory.py b/geomagio/edge/MiniSeedFactory.py
index abcf8b261..d708b30f4 100644
--- a/geomagio/edge/MiniSeedFactory.py
+++ b/geomagio/edge/MiniSeedFactory.py
@@ -97,6 +97,7 @@ class MiniSeedFactory(TimeseriesFactory):
         channels=None,
         type=None,
         interval=None,
+        add_empty_channels: bool = True,
     ):
         """Get timeseries data
 
@@ -114,6 +115,8 @@ class MiniSeedFactory(TimeseriesFactory):
             data type.
         interval: {'day', 'hour', 'minute', 'second', 'tenhertz'}
             data interval.
+        add_empty_channels
+            if True, returns channels without data as empty traces
 
         Returns
         -------
@@ -150,8 +153,16 @@ class MiniSeedFactory(TimeseriesFactory):
                     )
                 else:
                     data = self._get_timeseries(
-                        starttime, endtime, observatory, channel, type, interval
+                        starttime,
+                        endtime,
+                        observatory,
+                        channel,
+                        type,
+                        interval,
+                        add_empty_channels,
                     )
+                    if len(data) == 0:
+                        continue
                 timeseries += data
         finally:
             # restore stdout
@@ -296,7 +307,16 @@ class MiniSeedFactory(TimeseriesFactory):
             trace.data = numpy.ma.masked_invalid(trace.data)
         return stream
 
-    def _get_timeseries(self, starttime, endtime, observatory, channel, type, interval):
+    def _get_timeseries(
+        self,
+        starttime,
+        endtime,
+        observatory,
+        channel,
+        type,
+        interval,
+        add_empty_channels: bool = True,
+    ):
         """get timeseries data for a single channel.
 
         Parameters
@@ -313,6 +333,8 @@ class MiniSeedFactory(TimeseriesFactory):
             data type {definitive, quasi-definitive, variation}
         interval : str
             interval length {'day', 'hour', 'minute', 'second', 'tenhertz'}
+        add_empty_channels
+            if True, returns channels without data as empty traces
 
         Returns
         -------
@@ -330,7 +352,7 @@ class MiniSeedFactory(TimeseriesFactory):
             sncl.network, sncl.station, sncl.location, sncl.channel, starttime, endtime
         )
         data.merge()
-        if data.count() == 0:
+        if data.count() == 0 and add_empty_channels:
             data += TimeseriesUtility.create_empty_trace(
                 starttime,
                 endtime,
diff --git a/geomagio/iaga2002/StreamIAGA2002Factory.py b/geomagio/iaga2002/StreamIAGA2002Factory.py
index 62f6f871c..eb1625f62 100644
--- a/geomagio/iaga2002/StreamIAGA2002Factory.py
+++ b/geomagio/iaga2002/StreamIAGA2002Factory.py
@@ -31,6 +31,7 @@ class StreamIAGA2002Factory(IAGA2002Factory):
         channels=None,
         type=None,
         interval=None,
+        add_empty_channels: bool = True,
     ):
         """Implements get_timeseries
 
diff --git a/geomagio/imfv122/StreamIMFV122Factory.py b/geomagio/imfv122/StreamIMFV122Factory.py
index b868d8dd2..4a9575fc9 100644
--- a/geomagio/imfv122/StreamIMFV122Factory.py
+++ b/geomagio/imfv122/StreamIMFV122Factory.py
@@ -31,6 +31,7 @@ class StreamIMFV122Factory(IMFV122Factory):
         channels=None,
         type=None,
         interval=None,
+        add_empty_channels: bool = True,
     ):
         """Implements get_timeseries
 
diff --git a/geomagio/imfv283/GOESIMFV283Factory.py b/geomagio/imfv283/GOESIMFV283Factory.py
index 29bda1d9b..195e87105 100644
--- a/geomagio/imfv283/GOESIMFV283Factory.py
+++ b/geomagio/imfv283/GOESIMFV283Factory.py
@@ -67,6 +67,7 @@ class GOESIMFV283Factory(IMFV283Factory):
         channels=None,
         type=None,
         interval=None,
+        add_empty_channels: bool = True,
     ):
         """Implements get_timeseries
 
diff --git a/geomagio/imfv283/StreamIMFV283Factory.py b/geomagio/imfv283/StreamIMFV283Factory.py
index aff52877f..402f0e2c3 100644
--- a/geomagio/imfv283/StreamIMFV283Factory.py
+++ b/geomagio/imfv283/StreamIMFV283Factory.py
@@ -31,6 +31,7 @@ class StreamIMFV283Factory(IMFV283Factory):
         channels=None,
         type=None,
         interval=None,
+        add_empty_channels: bool = True,
     ):
         """Implements get_timeseries
 
diff --git a/test/edge_test/EdgeFactory_test.py b/test/edge_test/EdgeFactory_test.py
index 6b524fb31..55e94f126 100644
--- a/test/edge_test/EdgeFactory_test.py
+++ b/test/edge_test/EdgeFactory_test.py
@@ -29,3 +29,28 @@ def dont_get_timeseries():
         "H",
         "Expect timeseries stats channel to be equal to H",
     )
+
+
+def test_add_empty_channels():
+    """edge_test.EdgeFactory_test.test_add_empty_channels()"""
+    edge_factory = EdgeFactory(host="TODO", port="TODO")
+    timeseries = edge_factory.get_timeseries(
+        UTCDateTime(2015, 3, 1, 0, 0, 0),
+        UTCDateTime(2015, 3, 1, 1, 0, 0),
+        "BOU",
+        ("H"),
+        "variation",
+        "minute",
+        add_empty_channels=False,
+    )
+    assert len(timeseries) == 0
+    timeseries = edge_factory.get_timeseries(
+        UTCDateTime(2015, 3, 1, 0, 0, 0),
+        UTCDateTime(2015, 3, 1, 1, 0, 0),
+        "BOU",
+        ("H"),
+        "variation",
+        "minute",
+        add_empty_channels=True,  # default
+    )
+    assert len(timeseries) == 1
-- 
GitLab