Skip to content
Snippets Groups Projects
Controller.py 5.67 KiB
Newer Older
  • Learn to ignore specific revisions
  • """Controller class for geomag algorithms"""
    
    
    import TimeseriesFactoryException
    
    class Controller(object):
        """Controller for geomag algorithms.
    
        Parameters
        ----------
    
    Hal Simpson's avatar
    Hal Simpson committed
        inputFactory: TimeseriesFactory
    
            the factory that will read in timeseries data
    
    Hal Simpson's avatar
    Hal Simpson committed
        outputFactory: TimeseriesFactory
    
            the factory that will output the timeseries data
    
        algorithm: Algorithm
            the algorithm(s) that will procees the timeseries data
    
        Notes
        -----
    
    Hal Simpson's avatar
    Hal Simpson committed
        Has 2 basic modes.
    
        Run simply sends all the data in a stream to edge. If a startime/endtime is
            provided, it will send the data from the stream that is within that
            time span.
        Update will update any data that has changed between the source, and
    
    Hal Simpson's avatar
    Hal Simpson committed
            the target during a given timeframe. It will also attempt to
            recursively backup so it can update all missing data.
    
    Hal Simpson's avatar
    Hal Simpson committed
        def __init__(self, inputFactory, outputFactory, algorithm):
    
    Hal Simpson's avatar
    Hal Simpson committed
            self._inputFactory = inputFactory
            self._algorithm = algorithm
            self._outputFactory = outputFactory
    
    
        def run(self, starttime, endtime, options):
    
            Parameters
            ----------
    
            starttime: obspy.core.UTCDateTime
                time of first sample. None if starttime should come from dataset
            endtime: obspy.core.UTCDateTime
                endtime of last sampel.  None if endtime should come from dataset
    
    Hal Simpson's avatar
    Hal Simpson committed
            options: dictionary
                The dictionary of all the command line arguments. Could in theory
                contain other options passed in by the controller.
    
            input_channels = self._algorithm.get_input_channels()
    
            algorithm_start, algorithm_end = self._algorithm.get_input_interval(
                    starttime, endtime)
    
            timeseries = self._inputFactory.get_timeseries(algorithm_start,
                algorithm_end, channels=input_channels)
    
            processed = self._algorithm.process(timeseries)
    
    Hal Simpson's avatar
    Hal Simpson committed
            output_channels = self._algorithm.get_output_channels()
    
    Hal Simpson's avatar
    Hal Simpson committed
            output_channels = self._get_output_channels(output_channels,
    
            self._outputFactory.put_timeseries(timeseries=processed,
                    starttime=starttime, endtime=endtime,
                    channels=output_channels)
    
        def run_as_update(self, starttime, endtime, options):
    
            """Updates data.
            Parameters
            ----------
            starttime: obspy.core.UTCDateTime
                time of first sample. None if starttime should come from dataset
            endtime: obspy.core.UTCDateTime
                endtime of last sampel.  None if endtime should come from dataset
    
    Hal Simpson's avatar
    Hal Simpson committed
            options: dictionary
                The dictionary of all the command line arguments. Could in theory
                contain other options passed in by the controller.
    
    
            Notes
            -----
            Finds gaps in the target data, and if there's new data in the input
                source, calls run with the start/end time of a given gap to fill
                in.
    
    Hal Simpson's avatar
    Hal Simpson committed
            It checks the start of the target data, and if it's missing, and
                there's new data available, it backs up the starttime/endtime,
                and recursively calls itself, to check the previous period, to see
                if new data is available there as well. Calls run for each new
                period, oldest to newest.
    
    Hal Simpson's avatar
    Hal Simpson committed
            input_channels = self._algorithm.get_input_channels()
    
    Hal Simpson's avatar
    Hal Simpson committed
            output_channels = self._algorithm._get_output_channels()
    
    Hal Simpson's avatar
    Hal Simpson committed
            output_channels = self._get_output_channels(output_channels,
    
            timeseries_source = self._inputFactory.get_timeseries(starttime,
                    endtime, channels=input_channels)
            timeseries_target = self._outputFactory.get_timeseries(starttime,
                    endtime, channels=output_channels)
    
            source_gaps = TUtils.get_timeseries_gaps(
                timeseries_source, input_channels, starttime, endtime)
            target_gaps = TUtils.get_timeseries_gaps(
                timeseries_target, output_channels, starttime, endtime)
            source_gaps = TUtils.get_merged_gaps(
                    source_gaps, input_channels)
            target_gaps = TUtils.get_merged_gaps(
                    target_gaps, output_channels)
            del timeseries_source
            del timeseries_target
    
                    len(source_gaps) and source_gaps[0][0] != starttime) and
                    len(target_gaps) and target_gaps[0][0] == starttime):
                self.run_as_update((starttime - (endtime - starttime)),
    
                    (starttime - TUtils.get_seconds_of_interval(options.interval)),
                    options)
    
            for target_gap in target_gaps:
                if not TUtils.gap_is_new_data(source_gaps, target_gap):
                    continue
    
                self.run(target_gap[0], target_gap[1], options)
    
    
    Hal Simpson's avatar
    Hal Simpson committed
        def _get_output_channels(self, algorithm_channels, commandline_channels):
            """get output channels
    
            Parameters
            ----------
            algorithm_channels: array_like
                list of channels required by the algorithm
            commandline_channels: array_like
                list of channels requested by the user
            Notes
            -----
            We want to return the channels requested by the user, but we require
                that they be in the list of channels for the algorithm.
            """
    
            if commandline_channels is not None:
                for channel in commandline_channels:
                    if channel not in algorithm_channels:
                        raise TimeseriesFactoryException(
                            'Output "%s" Channel not in Algorithm'
                                % channel)
                return commandline_channels
            return algorithm_channels