From 5ab6495cf43c7cde9d4ba875573e0c1b6e51ce13 Mon Sep 17 00:00:00 2001
From: spencer <swilbur@usgs.gov>
Date: Thu, 16 May 2024 12:46:04 -0600
Subject: [PATCH 1/3] Fixed the bugs cuasing interval to be defined as none.
 This required changes to the FDSNFactory.py after fixing this another bug was
 found in IAGAWriter2002.py, This was also fixed. The change made to the
 test_metadate.py script was something that Nich told me about that hasnt been
 merged in yet. Happy to take it out if need be but I left it in for the time
 being.

---
 geomagio/__init__.py                |  2 ++
 geomagio/edge/FDSNFactory.py        | 34 +++++++++++-------
 geomagio/edge/FDSNSNCL.py           | 53 +++++++++++++++++++----------
 geomagio/iaga2002/IAGA2002Writer.py |  4 ++-
 test/edge_test/FDSNSNCL_test.py     | 13 +++----
 test_metadata.py                    |  2 +-
 6 files changed, 69 insertions(+), 39 deletions(-)

diff --git a/geomagio/__init__.py b/geomagio/__init__.py
index d51ffc9e4..1887216cb 100644
--- a/geomagio/__init__.py
+++ b/geomagio/__init__.py
@@ -10,6 +10,7 @@ from . import Util
 from .Controller import Controller
 from .DerivedTimeseriesFactory import DerivedTimeseriesFactory
 from .ObservatoryMetadata import ObservatoryMetadata
+from .VariometerMetadata import VariometerMetadata
 from .PlotTimeseriesFactory import PlotTimeseriesFactory
 from .TimeseriesFactory import TimeseriesFactory
 from .TimeseriesFactoryException import TimeseriesFactoryException
@@ -20,6 +21,7 @@ __all__ = [
     "DeltaFAlgorithm",
     "DerivedTimeseriesFactory",
     "ObservatoryMetadata",
+    "VariometerMetadata",
     "PlotTimeseriesFactory",
     "StreamConverter",
     "TimeseriesFactory",
diff --git a/geomagio/edge/FDSNFactory.py b/geomagio/edge/FDSNFactory.py
index fcbc3a982..52da751e1 100644
--- a/geomagio/edge/FDSNFactory.py
+++ b/geomagio/edge/FDSNFactory.py
@@ -20,6 +20,7 @@ from ..ObservatoryMetadata import ObservatoryMetadata
 from ..VariometerMetadata import VariometerMetadata
 from .RawInputClient import RawInputClient
 from .FDSNSNCL import FDSNSNCL
+from .SNCL import SNCL
 
 
 class FDSNFactory(TimeseriesFactory):
@@ -84,6 +85,7 @@ class FDSNFactory(TimeseriesFactory):
         interval: Optional[DataInterval] = None,
         variometerMetadata: Optional[VariometerMetadata] = None,
         locationCode: Optional[str] = None,
+        snclMapper: str = "geomag",
     ):
         TimeseriesFactory.__init__(self, observatory, channels, type, interval)
 
@@ -95,6 +97,10 @@ class FDSNFactory(TimeseriesFactory):
         self.observatoryMetadata = variometerMetadata or VariometerMetadata()
         self.network = network
         self.locationCode = locationCode
+        if snclMapper == "geomag":
+            self.get_sncl = FDSNSNCL.get_sncl
+        else:
+            raise TimeseriesFactoryException("Unrecognized SNCL mapper")
 
     def get_timeseries(
         self,
@@ -214,7 +220,7 @@ class FDSNFactory(TimeseriesFactory):
         data: Trace
             timeseries trace of the requested channel data
         """
-        sncl = FDSNSNCL.get_sncl(
+        sncl = self.get_sncl(
             station=observatory,
             data_type=type,
             interval=interval,
@@ -260,7 +266,7 @@ class FDSNFactory(TimeseriesFactory):
             )
         # Beneath is necessary code to check the reported azimuth
         # for the LF1 (E or Y) and LF2 (H or X) channels and determine if intstrument axes have been reversed.
-        azi, dip = self._get_orientations(data[0], starttime)
+        azi, dip = self._get_orientations(data[0], starttime, sncl)
 
         # Checks Azimuth for LF2 channel
         if 270 > azi and azi > 90.0 and data[0].stats.channel == "LF2":
@@ -331,8 +337,8 @@ class FDSNFactory(TimeseriesFactory):
         stream: Stream,
         observatory: str,
         channel: str,
-        type: DataType,
-        interval: DataInterval,
+        type: str,
+        interval: str,
     ):
         """set metadata for a given stream/channel
         Parameters
@@ -352,24 +358,26 @@ class FDSNFactory(TimeseriesFactory):
             )
 
     def _get_orientations(
-        self, trace: Trace, starttime: UTCDateTime
+        self, trace: Trace, starttime: UTCDateTime, sncl
     ) -> Tuple[float, float]:
         # Retrieve station orientation information using FDSN for each trace
 
-        sncl = FDSNSNCL.get_sncl(
-            data_type=trace.stats.location,
-            element=trace.stats.channel,
-            interval=self.interval,
-            station=trace.stats.station,
-            network=trace.stats.network,
-            location=trace.stats.location,
-        )
+        # sncl = _get_timeseries()
+        #     data_type=trace.stats.location,
+        #     element=self.channels,
+        #     interval=self.interval,
+        #     station=trace.stats.station,
+        #     network=trace.stats.network,
+        #     location=trace.stats.location,
+
+        # )
 
         FDSN = FDSNClient("IRIS")
         inv = FDSN.get_stations(
             network=sncl.network,
             station=sncl.station,
             channel=sncl.channel,
+            # interval = sncl.interval,
             level="channel",
         )
 
diff --git a/geomagio/edge/FDSNSNCL.py b/geomagio/edge/FDSNSNCL.py
index 4e94158cb..a93892a5e 100644
--- a/geomagio/edge/FDSNSNCL.py
+++ b/geomagio/edge/FDSNSNCL.py
@@ -1,7 +1,13 @@
-from typing import Optional
+from typing import Optional, Dict
 
 from ..geomag_types import DataInterval, DataType
-from .SNCL import SNCL, get_channel, get_location, _get_channel_start
+from .SNCL import (
+    SNCL,
+    get_channel,
+    get_location,
+    _get_location_start,
+    _get_channel_start,
+)
 
 
 class FDSNSNCL(SNCL):
@@ -22,7 +28,6 @@ class FDSNSNCL(SNCL):
         ):
             raise ValueError(f"Unsupported data type: {data_type}")
         location = location or get_location(element=element, data_type=data_type)
-
         return FDSNSNCL(
             station=station,
             network=network,
@@ -36,6 +41,14 @@ class FDSNSNCL(SNCL):
             location=location,
         )
 
+    # def parse_sncl(self) -> Dict:
+    #         return {
+    #             "station": self.station,
+    #             "network": self.network,
+    #             "data_type": self.data_type,
+    #             "element": self.element,
+    #             "interval": self.interval,
+    #         }
     @property
     def data_type(self) -> str:
         if self.location == "40" and self.network == "IU":
@@ -48,21 +61,25 @@ class FDSNSNCL(SNCL):
             return _get_FDSN_element(channel=self.channel)
         return super().element
 
-    @property
-    def interval(self) -> str:
-        """Translates beginning of channel to interval"""
-        channel_start = self.channel[0]
-        if channel_start == "B":
-            return "tenhertz"
-        elif channel_start == "L":
-            return "second"
-        elif channel_start == "U":
-            return "minute"
-        elif channel_start == "R":
-            return "hour"
-        elif channel_start == "P":
-            return "day"
-        raise ValueError(f"Unexcepted interval code: {channel_start}")
+    # @property
+    # def interval(self) -> str:
+    #      if self.location == "40" and self.network == "IU":
+    #         """Translates beginning of channel to interval"""
+    #         channel_start = self.channel[0]
+    #         if channel_start == "B":
+    #             return "tenhertz"
+    #         elif channel_start == "L":
+    #             return "second"
+    #         elif channel_start == "U":
+    #             return "minute"
+    #         elif channel_start == "R":
+    #             return "hour"
+    #         elif channel_start == "P":
+    #             return "day"
+
+    #         # print(self.interval)
+    #         raise ValueError(f"Unexcepted interval code: {channel_start}")
+    #      return super().interval
 
 
 def _get_FDSN_element(channel: str) -> str:
diff --git a/geomagio/iaga2002/IAGA2002Writer.py b/geomagio/iaga2002/IAGA2002Writer.py
index 4aac8db92..f1fd9725e 100644
--- a/geomagio/iaga2002/IAGA2002Writer.py
+++ b/geomagio/iaga2002/IAGA2002Writer.py
@@ -42,6 +42,7 @@ class IAGA2002Writer(object):
                     % (channel, str(TimeseriesUtility.get_channels(timeseries)))
                 )
         stats = timeseries[0].stats
+
         if len(channels) != 4:
             channels = self._pad_to_four_channels(timeseries, channels)
         out.write(self._format_headers(stats, channels).encode("utf8"))
@@ -80,7 +81,7 @@ class IAGA2002Writer(object):
                 self._format_header("Geodetic Longitude", str(stats.geodetic_longitude))
             )
         if "elevation" in stats:
-            buf.append(self._format_header("Elevation", stats.elevation))
+            buf.append(self._format_header("Elevation", str(stats.elevation)))
         buf.append(self._format_header("Reported", "".join(channels)))
         if "sensor_orientation" in stats:
             buf.append(
@@ -168,6 +169,7 @@ class IAGA2002Writer(object):
         """
         prefix = " "
         suffix = " |" + linesep
+        print("Prefix", prefix, "Name", name, "Value", value)
         return "".join((prefix, name.ljust(23), value.ljust(44), suffix))
 
     def _format_comment(self, comment):
diff --git a/test/edge_test/FDSNSNCL_test.py b/test/edge_test/FDSNSNCL_test.py
index 448bc11c9..0aac3341a 100644
--- a/test/edge_test/FDSNSNCL_test.py
+++ b/test/edge_test/FDSNSNCL_test.py
@@ -125,12 +125,13 @@ def test_get_sncl():
             location="40",
         )
         assert error.value == "Unsupported data type: adjusted"
-    assert FDSNSNCL.get_sncl(
-        data_type="adjusted",
-        element="H",
-        interval="second",
-        station="BOU",
-    ) == FDSNSNCL(station="BOU", network="NT", channel="LFH", location="A0")
+        assert FDSNSNCL.get_sncl(
+            data_type="adjusted",
+            element="H",
+            interval="second",
+            station="BOU",
+        )  # == FDSNSNCL(station="BOU", network="NT", channel="LFH", location="40")
+        assert error.value == "Unsupported data type: adjusted"
 
 
 def test_interval():
diff --git a/test_metadata.py b/test_metadata.py
index 2a975f896..4436aa0a6 100644
--- a/test_metadata.py
+++ b/test_metadata.py
@@ -121,7 +121,7 @@ readings = WebAbsolutesFactory().get_readings(
 )
 # get residual reading
 reading = SpreadsheetAbsolutesFactory().parse_spreadsheet(
-    "etc/residual/DED-20140952332.xlsm"
+    "etc/residual/DED-20140952332.xlsm", []
 )
 readings.append(reading)
 
-- 
GitLab


From 1ac16df580f93f77933d98cc1b123ad63f391f09 Mon Sep 17 00:00:00 2001
From: spencer <swilbur@usgs.gov>
Date: Wed, 29 May 2024 13:24:13 -0600
Subject: [PATCH 2/3] Reviewed comments made by Josh and removed debugging
 print statements and changed _get_channel_start to get_channel_start within
 SNCL.py and any other script which references this function.

---
 geomagio/edge/FDSNFactory.py        | 10 --------
 geomagio/edge/FDSNSNCL.py           | 38 ++---------------------------
 geomagio/edge/IRISSNCL.py           |  4 +--
 geomagio/edge/SNCL.py               |  6 ++---
 geomagio/iaga2002/IAGA2002Writer.py |  1 -
 test/edge_test/FDSNSNCL_test.py     |  4 +--
 6 files changed, 9 insertions(+), 54 deletions(-)

diff --git a/geomagio/edge/FDSNFactory.py b/geomagio/edge/FDSNFactory.py
index 52da751e1..4571d935b 100644
--- a/geomagio/edge/FDSNFactory.py
+++ b/geomagio/edge/FDSNFactory.py
@@ -362,22 +362,12 @@ class FDSNFactory(TimeseriesFactory):
     ) -> Tuple[float, float]:
         # Retrieve station orientation information using FDSN for each trace
 
-        # sncl = _get_timeseries()
-        #     data_type=trace.stats.location,
-        #     element=self.channels,
-        #     interval=self.interval,
-        #     station=trace.stats.station,
-        #     network=trace.stats.network,
-        #     location=trace.stats.location,
-
-        # )
 
         FDSN = FDSNClient("IRIS")
         inv = FDSN.get_stations(
             network=sncl.network,
             station=sncl.station,
             channel=sncl.channel,
-            # interval = sncl.interval,
             level="channel",
         )
 
diff --git a/geomagio/edge/FDSNSNCL.py b/geomagio/edge/FDSNSNCL.py
index a93892a5e..0f0641c7b 100644
--- a/geomagio/edge/FDSNSNCL.py
+++ b/geomagio/edge/FDSNSNCL.py
@@ -1,13 +1,7 @@
 from typing import Optional, Dict
 
 from ..geomag_types import DataInterval, DataType
-from .SNCL import (
-    SNCL,
-    get_channel,
-    get_location,
-    _get_location_start,
-    _get_channel_start,
-)
+from .SNCL import SNCL, get_channel, get_location, get_channel_start
 
 
 class FDSNSNCL(SNCL):
@@ -41,14 +35,6 @@ class FDSNSNCL(SNCL):
             location=location,
         )
 
-    # def parse_sncl(self) -> Dict:
-    #         return {
-    #             "station": self.station,
-    #             "network": self.network,
-    #             "data_type": self.data_type,
-    #             "element": self.element,
-    #             "interval": self.interval,
-    #         }
     @property
     def data_type(self) -> str:
         if self.location == "40" and self.network == "IU":
@@ -61,26 +47,6 @@ class FDSNSNCL(SNCL):
             return _get_FDSN_element(channel=self.channel)
         return super().element
 
-    # @property
-    # def interval(self) -> str:
-    #      if self.location == "40" and self.network == "IU":
-    #         """Translates beginning of channel to interval"""
-    #         channel_start = self.channel[0]
-    #         if channel_start == "B":
-    #             return "tenhertz"
-    #         elif channel_start == "L":
-    #             return "second"
-    #         elif channel_start == "U":
-    #             return "minute"
-    #         elif channel_start == "R":
-    #             return "hour"
-    #         elif channel_start == "P":
-    #             return "day"
-
-    #         # print(self.interval)
-    #         raise ValueError(f"Unexcepted interval code: {channel_start}")
-    #      return super().interval
-
 
 def _get_FDSN_element(channel: str) -> str:
     channel_end = channel[1:]
@@ -101,7 +67,7 @@ def get_FDSN_channel(
     location: Optional[str] = None,
 ) -> str:
     if location == "40" and network == "IU":
-        return _get_channel_start(interval=interval) + _get_channel_end(element=element)
+        return get_channel_start(interval=interval) + _get_channel_end(element=element)
     return get_channel(element=element, interval=interval, data_type=data_type)
 
 
diff --git a/geomagio/edge/IRISSNCL.py b/geomagio/edge/IRISSNCL.py
index 1993c755f..cbad07bcb 100644
--- a/geomagio/edge/IRISSNCL.py
+++ b/geomagio/edge/IRISSNCL.py
@@ -1,7 +1,7 @@
 from typing import Optional
 
 from ..geomag_types import DataInterval, DataType
-from .SNCL import SNCL, get_channel, get_location, _get_channel_start
+from .SNCL import SNCL, get_channel, get_location, get_channel_start
 
 
 class IRISSNCL(SNCL):
@@ -67,7 +67,7 @@ def get_iris_channel(
     location: Optional[str] = None,
 ) -> str:
     if location == "40" and network == "IU":
-        return _get_channel_start(interval=interval) + _get_channel_end(element=element)
+        return get_channel_start(interval=interval) + _get_channel_end(element=element)
     return get_channel(element=element, interval=interval, data_type=data_type)
 
 
diff --git a/geomagio/edge/SNCL.py b/geomagio/edge/SNCL.py
index 88e012e9b..0570a8bf7 100644
--- a/geomagio/edge/SNCL.py
+++ b/geomagio/edge/SNCL.py
@@ -94,7 +94,7 @@ class SNCL(BaseModel):
 
 def get_channel(element: str, interval: str, data_type: str) -> str:
     return _check_predefined_channel(element=element, interval=interval) or (
-        _get_channel_start(interval=interval)
+        get_channel_start(interval=interval)
         + _get_channel_end(element=element, data_type=data_type)
     )
 
@@ -112,7 +112,7 @@ def _check_predefined_element(channel: str) -> Optional[str]:
     return None
 
 
-def _get_channel_start(interval: str) -> str:
+def get_channel_start(interval: str) -> str:
     if interval == "tenhertz":
         return "B"
     if interval == "second":
@@ -153,7 +153,7 @@ def _get_element(channel: str, location: str) -> str:
 
 def _check_predefined_channel(element: str, interval: str) -> Optional[str]:
     if element in ELEMENT_CONVERSIONS:
-        return _get_channel_start(interval=interval) + ELEMENT_CONVERSIONS[element]
+        return get_channel_start(interval=interval) + ELEMENT_CONVERSIONS[element]
     elif len(element) == 3:
         return element
     # chan.loc format
diff --git a/geomagio/iaga2002/IAGA2002Writer.py b/geomagio/iaga2002/IAGA2002Writer.py
index f1fd9725e..5cf5c4113 100644
--- a/geomagio/iaga2002/IAGA2002Writer.py
+++ b/geomagio/iaga2002/IAGA2002Writer.py
@@ -169,7 +169,6 @@ class IAGA2002Writer(object):
         """
         prefix = " "
         suffix = " |" + linesep
-        print("Prefix", prefix, "Name", name, "Value", value)
         return "".join((prefix, name.ljust(23), value.ljust(44), suffix))
 
     def _format_comment(self, comment):
diff --git a/test/edge_test/FDSNSNCL_test.py b/test/edge_test/FDSNSNCL_test.py
index 0aac3341a..4d66363ab 100644
--- a/test/edge_test/FDSNSNCL_test.py
+++ b/test/edge_test/FDSNSNCL_test.py
@@ -129,8 +129,8 @@ def test_get_sncl():
             data_type="adjusted",
             element="H",
             interval="second",
-            station="BOU",
-        )  # == FDSNSNCL(station="BOU", network="NT", channel="LFH", location="40")
+            station="ANMO",
+        ) == FDSNSNCL(station="ANMO", network="NT", channel="LFH", location="40")
         assert error.value == "Unsupported data type: adjusted"
 
 
-- 
GitLab


From 66d244a32b4b93dbe1ac092c644b878cab2b2d1f Mon Sep 17 00:00:00 2001
From: spencer <swilbur@usgs.gov>
Date: Wed, 29 May 2024 13:37:32 -0600
Subject: [PATCH 3/3] Ran lint

---
 geomagio/edge/FDSNFactory.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/geomagio/edge/FDSNFactory.py b/geomagio/edge/FDSNFactory.py
index 4571d935b..91020bd3b 100644
--- a/geomagio/edge/FDSNFactory.py
+++ b/geomagio/edge/FDSNFactory.py
@@ -362,7 +362,6 @@ class FDSNFactory(TimeseriesFactory):
     ) -> Tuple[float, float]:
         # Retrieve station orientation information using FDSN for each trace
 
-
         FDSN = FDSNClient("IRIS")
         inv = FDSN.get_stations(
             network=sncl.network,
-- 
GitLab