Newer
Older
Hal Simpson
committed
"""Controller class for geomag algorithms"""
Hal Simpson
committed
import TimeseriesUtilities as TUtils
import TimeseriesFactoryException
Hal Simpson
committed
import copy
class Controller(object):
"""Controller for geomag algorithms.
Parameters
----------
the factory that will read in timeseries data
the factory that will output the timeseries data
Hal Simpson
committed
algorithm: Algorithm
the algorithm(s) that will procees the timeseries data
Notes
-----
Hal Simpson
committed
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. It will also attempt to
recursively backup so it can update all missing data.
def __init__(self, inputFactory, outputFactory, algorithm):
self._inputFactory = inputFactory
self._algorithm = algorithm
self._outputFactory = outputFactory
Hal Simpson
committed
def run(self, options):
Hal Simpson
committed
"""run controller
options: dictionary
The dictionary of all the command line arguments. Could in theory
contain other options passed in by the controller.
Hal Simpson
committed
input_channels = self._algorithm.get_input_channels()
Hal Simpson
committed
algorithm_start, algorithm_end = self._algorithm.get_input_interval(
Hal Simpson
committed
options.starttime, options.endtime)
Hal Simpson
committed
Hal Simpson
committed
timeseries = self._inputFactory.get_timeseries(algorithm_start,
algorithm_end, channels=input_channels)
Hal Simpson
committed
Hal Simpson
committed
processed = self._algorithm.process(timeseries)
Hal Simpson
committed
output_channels = self._get_output_channels(output_channels,
options.outchannels)
Hal Simpson
committed
self._outputFactory.put_timeseries(timeseries=processed,
Hal Simpson
committed
starttime=options.starttime, endtime=options.endtime,
Hal Simpson
committed
channels=output_channels)
Hal Simpson
committed
Hal Simpson
committed
def run_as_update(self, options):
Hal Simpson
committed
"""Updates data.
Parameters
----------
options: dictionary
The dictionary of all the command line arguments. Could in theory
contain other options passed in by the controller.
Hal Simpson
committed
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.
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
committed
"""
input_channels = self._algorithm.get_input_channels()
Hal Simpson
committed
output_channels = self._algorithm.get_output_channels()
Hal Simpson
committed
output_channels = self._get_output_channels(output_channels,
options.outchannels)
Hal Simpson
committed
timeseries_source = self._inputFactory.get_timeseries(
options.starttime, options.endtime, channels=input_channels)
timeseries_target = self._outputFactory.get_timeseries(
options.starttime, options.endtime, channels=output_channels)
Hal Simpson
committed
Hal Simpson
committed
source_gaps = TUtils.get_timeseries_gaps(
Hal Simpson
committed
timeseries_source, input_channels, options.starttime,
options.endtime)
Hal Simpson
committed
target_gaps = TUtils.get_timeseries_gaps(
Hal Simpson
committed
timeseries_target, output_channels, options.starttime,
options.endtime)
source_gaps = TUtils.get_merged_gaps(source_gaps, input_channels)
target_gaps = TUtils.get_merged_gaps(target_gaps, output_channels)
Hal Simpson
committed
del timeseries_source
del timeseries_target
Hal Simpson
committed
if ((not len(source_gaps) or
Hal Simpson
committed
len(source_gaps) and source_gaps[0][0] != options.starttime)
and
len(target_gaps) and target_gaps[0][0] == options.starttime):
new_options = copy.deepcopy(options)
new_options.starttime = (options.starttime -
(options.endtime - options.starttime))
new_options.endtime = (options.starttime -
TUtils.get_seconds_of_interval(options.interval))
self.run_as_update(new_options)
Hal Simpson
committed
for target_gap in target_gaps:
if not TUtils.gap_is_new_data(source_gaps, target_gap):
continue
Hal Simpson
committed
new_options = copy.deepcopy(options)
new_options.starttime = target_gap[0]
new_options.endtime = target_gap[1]
self.run(new_options)
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