Skip to content
Snippets Groups Projects
Controller.py 5.68 KiB
Newer Older
"""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
    update: boolean
        indicates that data is to be updated.
    interval: string
        the data interval {daily, hourly, minute, second}
    update_realtime: boolean
        indicates

    Notes
    -----
    Has 2(3) 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
        the target during a given timeframe. If the update_realtime flag
        is set, it will attempt to recursively backup so it can update all
        missing data.
    def __init__(self, inputFactory, outputFactory, algorithm, update=False,
            interval='minute', update_realtime=False):
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
        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

        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.
        If the update_realtime flag is set, 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