From baf55bec7c2d6b0bf8f5928ca5b2fc6d8661dbc7 Mon Sep 17 00:00:00 2001
From: Hal Simpson <hasimpson@usgs.gov>
Date: Wed, 4 Nov 2015 15:25:50 -0700
Subject: [PATCH] Added factory to read goes server directly for data

---
 geomagio/imfv283/GOESIMFV283Factory.py | 171 +++++++++++++++++++++++++
 1 file changed, 171 insertions(+)
 create mode 100644 geomagio/imfv283/GOESIMFV283Factory.py

diff --git a/geomagio/imfv283/GOESIMFV283Factory.py b/geomagio/imfv283/GOESIMFV283Factory.py
new file mode 100644
index 000000000..62bd9831e
--- /dev/null
+++ b/geomagio/imfv283/GOESIMFV283Factory.py
@@ -0,0 +1,171 @@
+"""Factory to load IMFV283 files from an input StreamIMFV283Factory."""
+
+from IMFV283Factory import IMFV283Factory
+from datetime import datetime
+import subprocess
+import obspy.core
+
+
+class GOESIMFV283Factory(IMFV283Factory):
+    """Timeseries Factory for IMFV283 formatted files loaded from the goes
+        server.
+
+    Parameters
+    ----------
+    directory: String
+        The directory that support files go in. Primarily criteria files,
+        and log files.
+    getdcpmessages: String
+        The directory where the getDcpMessages executable will be found
+    server: array of strings
+        An array of strings, to be used in order of which goes server to go to
+    user: String
+        The goes user.
+
+
+    Notes
+    -----
+    GOESIMFV283Factory gets it's data by calling the getDcpMessages program
+        provided by NOAA using the subprocess routines.
+        https://dcs1.noaa.gov/LRGS/LRGS-Client-Getting-Started.pdf
+
+    The server packets are timestamped when they are received by the server,
+    which can easily be 20 minutes off the time of the data. To compensate we
+    ask for 30 minutes before and after the range requested.
+
+    See Also
+    --------
+    IMFV283Factory
+    Timeseriesfactory
+    """
+    def __init__(self, observatory=None, channels=None,
+            type=None, interval='Minute',  directory=None,
+            getdcpmessages=None, server=None, user=None):
+        IMFV283Factory.__init__(self, None, observatory, channels,
+            type, interval)
+        self.directory = directory
+        self.getdcpmessages = getdcpmessages
+        self.server = server
+        self.user = user
+        self.datetime = datetime.today()
+        self._set_log_filename()
+        self._set_criteria_filename()
+
+    def get_timeseries(self, starttime, endtime, observatory=None,
+            channels=None, type=None, interval=None):
+        """Implements get_timeseries
+
+        Notes: Calls IMFV283Factory.parse_string in place of
+            IMFV283Factory.get_timeseries.
+        """
+        observatory = observatory or self.observatory
+        channels = channels or self.channels
+        type = type or self.type
+        interval = interval or self.interval
+        timeseries = obspy.core.Stream()
+        output = self._retrieve_goes_messages(starttime, endtime, observatory)
+        timeseries  += IMFV283Factory.parse_string(self, output)
+                # merge channel traces for multiple days
+        timeseries.merge()
+        # trim to requested start/end time
+        timeseries.trim(starttime, endtime)
+        self._post_process(timeseries)
+        if observatory is not None:
+            timeseries = timeseries.select(station=observatory)
+        return timeseries
+
+    def _retrieve_goes_messages(self, starttime, endtime, observatory):
+        """Retrieve goes messages, using getdcpmessages commandline tool.
+
+        Parameters
+        ----------
+        starttime: obspy.core.UTCDateTime
+            time of first sample.
+        endtime: obspy.core.UTCDateTime
+            time of last sample.
+        observatory: str
+            observatory code.
+
+        Notes
+        -----
+        See page 37-38
+            http://lighthouse.tamucc.edu/dnrpub/Sutron/XPert/Software/ilex%20Software/DCS%20Tool%20Users%20Guide_4-4.pdf
+        getDcpMessages options.
+        -h host             A hostname.
+        -u user             The user name that must be known to the DDS server
+        -f criteria file    The name of the search criteria file.
+        -l log file         Logfile name for error messages.
+        -t seconds          Timeout value
+        -n                  Causes a newline to be output after each messages
+        -v                  Causes extra status messages to be output.
+
+        Returns
+        -------
+        String
+            Messages from getDcpMessages
+        """
+        self._fill_criteria_file(starttime, endtime)
+        args = '-h ' + self.server + ' -u ' + self.user + \
+                ' -f ' + self.directory + '/' + self.criteria_file_name + \
+                ' -l ' + self.directory + '/' + self.log_file_name + \
+                ' -t 60 -n'
+        getDcpMessage = self.getdcpmessages + '/getDcpMessages'
+        output = subprocess.check_output([getDcpMessage, args])
+        return output
+
+    def _set_log_filename(self):
+        """Set Log Filename
+
+        Notes
+        -----
+        Sets the filename for getDcpMessages to the Observatory code with a
+            .log extension.
+        """
+        self.log_file_name = self.observatory + \
+                '.log'
+
+    def _set_criteria_filename(self):
+        """Set Criteria Filename
+
+        Notes
+        -----
+        The Criteria file tells the GOES server what data we want and how
+            to return it.
+        See Page 30-34:
+            http://lighthouse.tamucc.edu/dnrpub/Sutron/XPert/Software/ilex%20Software/DCS%20Tool%20Users%20Guide_4-4.pdf
+
+        Sets the criteria filename to the observatory code with a .sc extension
+            First 3 lines are comments.
+            DAPS_SINCE: The time after which messages are to be retrieved.
+            DAPS_UNTIL: The time before which messages are to be retrieved.
+            NETWORK_LIST: The file name on the server, which holds the
+                key value pairs of observatory keys to be retrieved.
+            DAPS_STATUS: Do Not retrieve Status Messages.
+            RETRANSMITTED: Do Not retrieve retransmitted messages.
+            ASCENDING_TIME: Do Not sort messages into ascending time.
+            RT_SETTLE_DELAY: Do wait to prevent duplicate messages.
+        """
+        self.criteria_file_name = self.observatory + '.sc'
+
+    def _fill_criteria_file(self, starttime, endtime):
+        start = starttime - 1800
+        end = endtime + 1800
+
+        criteria_file = self.directory + '/' + self.criteria_file_name
+        buf = []
+        buf.append('#\n# LRGS Search Criteria\n#\n')
+        buf.append('DAPS_SINCE: ')
+        buf.append(starttime.datetime.strftime('%y/%j %H:%M:%S\n'))
+        buf.append('DAPS_UNTIL: ')
+        buf.append(end.datetime.strftime('%y/%j %H:%M:%S\n'))
+        buf.append('NETWORK_LIST: ./opendcs/netlist/' + \
+                self.observatory.lower() + \
+                '.nl\n')
+        buf.append('DAPS_STATUS: N\n')
+        buf.append('RETRANSMITTED: N\n')
+        buf.append('ASCENDING_TIME: false\n')
+        buf.append('RT_SETTLE_DELAY: true\n')
+
+        with open(criteria_file, 'wb') as fh:
+            fh.write(''.join(buf))
+            fh.close()
-- 
GitLab