From b47ff27594e9cda5c14d29a5ef639fd96b233cc8 Mon Sep 17 00:00:00 2001
From: Jeremy Fee <jmfee@usgs.gov>
Date: Fri, 19 Dec 2014 15:34:45 -0700
Subject: [PATCH] Updated main to work with updated factory, added algorithm
 interface, streamconverter

---
 src/python/geomag/Algorithm.py       |  20 ++++
 src/python/geomag/StreamConverter.py | 162 +++++++++++++++++++++++++++
 src/python/main.py                   |   7 +-
 3 files changed, 186 insertions(+), 3 deletions(-)
 create mode 100644 src/python/geomag/Algorithm.py
 create mode 100644 src/python/geomag/StreamConverter.py

diff --git a/src/python/geomag/Algorithm.py b/src/python/geomag/Algorithm.py
new file mode 100644
index 00000000..1c05eaae
--- /dev/null
+++ b/src/python/geomag/Algorithm.py
@@ -0,0 +1,20 @@
+
+
+class Algorithm(object):
+    """An algorithm processes a stream of timeseries to produce new timeseries.
+    """
+
+    def process(self, stream):
+        """Process a chunk of data.
+
+        Parameters
+        ----------
+        stream : obspy.core.Stream
+            input data
+
+        Returns
+        -------
+        obspy.core.Stream
+            resulting data
+        """
+        return stream.copy()
diff --git a/src/python/geomag/StreamConverter.py b/src/python/geomag/StreamConverter.py
new file mode 100644
index 00000000..8b4f9cbe
--- /dev/null
+++ b/src/python/geomag/StreamConverter.py
@@ -0,0 +1,162 @@
+"""Convert streams from one coordinate system to another.
+
+We use three coordinate systems.
+Geo: Based on Geographic North.  X, Y, Z, F
+     X is north, Y is east, Z is down
+Obs: Based on the observatories orientaion. H, E, Z, F, d0
+Mag: Based on Magnetic North. H, D, Z, F
+"""
+
+
+import obspy.core
+import ChannelConverter
+
+
+def get_geo_from_mag(mag):
+    pass
+
+
+def get_geo_from_obs(obs):
+    """Convert a stream to geographic coordinate system.
+
+    Parameters
+    ----------
+    stream : obspy.core.Stream
+        stream containing observatory components H, D or E, Z, and F.
+
+    Returns
+    -------
+    obspy.core.Stream
+        new stream object containing geographic components X, Y, Z, and F.
+    """
+    return get_geo_from_mag(get_mag_from_obs(obs))
+
+
+def get_mag_from_geo(geo):
+    pass
+
+
+def get_mag_from_obs(obs):
+    """Convert a stream to magnetic coordinate system.
+
+    Parameters
+    ----------
+    obs : obspy.core.Stream
+        stream containing observatory components H, D or E, Z, and F.
+
+    Returns
+    -------
+    obspy.core.Stream
+        new stream object containing magnetic components H, D, Z, and F.
+    """
+    h = obs.select(channel='H')[0]
+    d = __get_obs_d_from_obs(obs)
+    z = obs.select(channel='Z')[0]
+    f = obs.select(channel='F')[0]
+    obs_h = h.data
+    obs_d = d.data
+    d0 = ChannelConverter.get_radians_from_minutes(
+            numpy.float64(d.stats['DECBAS']) / 10)
+    (mag_h, mag_d) = ChannelConverter.get_mag_from_obs(obs_h, obs_d, d0)
+    return obspy.core.Stream((
+            __get_trace('H', h.stats, mag_h),
+            __get_trace('D', d.stats, mag_d),
+            z, f))
+
+
+def get_obs_from_geo(geo, include_e=False):
+    """Convert a stream to geographic coordinate system.
+
+    Parameters
+    ----------
+    stream : obspy.core.Stream
+        stream containing geographic components X, Y, Z, and F.
+    include_e : boolean
+        whether to also include the observatory E component.
+
+    Returns
+    -------
+    obspy.core.Stream
+        new stream object containing observatory components H, D, E, Z, and F.
+    """
+    return get_obs_from_mag(get_mag_from_geo(geo))
+
+
+def get_obs_from_mag(mag, include_e=False):
+    # TODO
+    obs = obspy.core.Stream()
+    if include_e:
+        obs += __get_obs_e_from_obs(obs)
+    return obs
+
+
+def __get_trace(channel, stats, data):
+    """Utility to create a new trace object.
+
+    Parameters
+    ----------
+    channel : str
+        channel name.
+    stats : obspy.core.Stats
+        channel metadata to clone.
+    data : numpy.array
+        channel data.
+
+    Returns
+    -------
+    obspy.core.Trace
+        trace containing data and metadata.
+    """
+    stats = obspy.core.Stats(stats)
+    stats.channel = channel
+    return obspy.core.Trace(data, stats)
+
+
+def __get_obs_d_from_obs(obs):
+    """Get trace containing observatory D component.
+
+    Returns D if found, otherwise computes D from H, E, D0.
+
+    Parameters
+    ----------
+    obs : obspy.core.Stream
+        observatory components (D) or (H, E).
+
+    Returns
+    -------
+    obspy.core.Trace
+        observatory component D.
+    """
+    try:
+        d = obs.select(channel='D')[0]
+    except:
+        h = obs.select(channel='H')[0]
+        e = obs.select(channel='E')[0]
+        d = __get_trace('D', e.stats,
+                ChannelConverter.get_obs_d_from_obs(h.data, e.data))
+    return d
+
+
+def __get_obs_e_from_obs(obs):
+    """Get trace containing observatory E component.
+
+    Returns E if found, otherwise computes E from H,D.
+
+    Parameters
+    ----------
+    obs : obspy.core.Stream
+        observatory components (E) or (H, D).
+
+    Returns
+    -------
+    obspy.core.Trace
+        observatory component E.
+    """
+    try:
+        e = obs.select(channel='E')[0]
+    except:
+        h = obs.select(channel='H')[0]
+        d = obs.select(channel='D')[0]
+        e = __get_trace('E', d.stats,
+                ChannelConverter.get_obs_e_from_obs(h.data, d.data))
+    return e
diff --git a/src/python/main.py b/src/python/main.py
index abc365af..daacb0cd 100644
--- a/src/python/main.py
+++ b/src/python/main.py
@@ -15,10 +15,11 @@ def main():
     import pprint
     iaga_dir = path.normpath(path.join(script_dir, '../../etc/iaga2002'))
     factory = iaga2002.IAGA2002Factory('file://' + iaga_dir +
-            '/%(OBS)s/%(interval)s%(type)s/%(obs)s%(ymd)s%(t)s%(i)s.%(i)s')
-    timeseries = factory.get_timeseries('BOU',
-            UTCDateTime('2014-11-01'), UTCDateTime('2014-11-02'),
+            '/%(OBS)s/%(interval)s%(type)s/%(obs)s%(ymd)s%(t)s%(i)s.%(i)s',
+            observatory='BOU', channels=('H', 'D', 'Z', 'F'),
             interval='minute', type='variation')
+    timeseries = factory.get_timeseries(
+            UTCDateTime('2014-11-01'), UTCDateTime('2014-11-02'))
     print timeseries
 
 
-- 
GitLab