From 92cea08efedd785ff818bb1aaec5acec1340923e Mon Sep 17 00:00:00 2001 From: Jeremy Fee <jmfee@usgs.gov> Date: Wed, 20 Jan 2016 12:12:16 -0700 Subject: [PATCH] Move algorithms to separate package, abstract algorithm arguments --- geomagio/Controller.py | 33 +++------ geomagio/__init__.py | 5 -- geomagio/{ => algorithm}/Algorithm.py | 24 +++++- .../{ => algorithm}/AlgorithmException.py | 0 geomagio/{ => algorithm}/DeltaFAlgorithm.py | 37 ++++++++-- geomagio/{ => algorithm}/XYZAlgorithm.py | 73 ++++++++++++++----- geomagio/algorithm/__init__.py | 28 +++++++ test/Controller_test.py | 3 +- test/__init__.py | 0 test/{ => algorithm_test}/Algorithm_test.py | 2 +- .../{ => algorithm_test}/XYZAlgorithm_test.py | 4 +- test/algorithm_test/__init__.py | 0 test/edge_test/__init__.py | 0 test/iaga2002_test/__init__.py | 0 test/imfv283_test/__init__.py | 0 test/pcdcp_test/__init__.py | 0 16 files changed, 149 insertions(+), 60 deletions(-) rename geomagio/{ => algorithm}/Algorithm.py (79%) rename geomagio/{ => algorithm}/AlgorithmException.py (100%) rename geomagio/{ => algorithm}/DeltaFAlgorithm.py (66%) rename geomagio/{ => algorithm}/XYZAlgorithm.py (62%) create mode 100644 geomagio/algorithm/__init__.py create mode 100644 test/__init__.py rename test/{ => algorithm_test}/Algorithm_test.py (95%) rename test/{ => algorithm_test}/XYZAlgorithm_test.py (92%) create mode 100644 test/algorithm_test/__init__.py create mode 100644 test/edge_test/__init__.py create mode 100644 test/iaga2002_test/__init__.py create mode 100644 test/imfv283_test/__init__.py create mode 100644 test/pcdcp_test/__init__.py diff --git a/geomagio/Controller.py b/geomagio/Controller.py index 60094a117..f6142619a 100644 --- a/geomagio/Controller.py +++ b/geomagio/Controller.py @@ -4,7 +4,7 @@ import argparse import sys from obspy.core import UTCDateTime -from Algorithm import Algorithm +from algorithm import algorithms import TimeseriesUtility from TimeseriesFactoryException import TimeseriesFactoryException from Util import ObjectView @@ -14,9 +14,6 @@ import iaga2002 import pcdcp import imfv283 -from DeltaFAlgorithm import DeltaFAlgorithm -from XYZAlgorithm import XYZAlgorithm - class Controller(object): """Controller for geomag algorithms. @@ -301,17 +298,8 @@ def main(args): else: print >> sys.stderr, "Missing required output directive" - if args.xyz is not None: - algorithm = XYZAlgorithm(informat=args.xyz[0], - outformat=args.xyz[1]) - elif args.deltaf is not None: - algorithm = DeltaFAlgorithm(informat=args.deltaf) - else: - # TODO get smarter on inchannels/outchannels since input doesn't always - # need to use the --inchannels argument, but might (as in iaga2002), - # get it from the file. - algorithm = Algorithm(inchannels=args.inchannels, - outchannels=args.outchannels or args.inchannels) + algorithm = algorithms[args.algorithm]() + algorithm.configure(args) # TODO check for unused arguments. @@ -481,14 +469,11 @@ def parse_args(args): help='Edge IP #. See --output-edge-* for other optional arguments') # Algorithms group - algorithm_group = parser.add_mutually_exclusive_group() - algorithm_group.add_argument('--xyz', - nargs=2, - choices=['geo', 'mag', 'obs', 'obsd'], - help='Enter the geomagnetic orientation(s) you want to read from' + - ' and to respectfully.') - algorithm_group.add_argument('--deltaf', - choices=['geo', 'obs', 'obsd'], - help='Enter the geomagnetic orientation you want to read from') + parser.add_argument('--algorithm', + choices=[k for k in algorithms], + default='default') + + for k in algorithms: + algorithms[k].add_arguments(parser) return parser.parse_args(args) diff --git a/geomagio/__init__.py b/geomagio/__init__.py index 4b0f6a79f..9e086ee63 100644 --- a/geomagio/__init__.py +++ b/geomagio/__init__.py @@ -4,19 +4,14 @@ Geomag Algorithm Module import ChannelConverter import StreamConverter -from Algorithm import Algorithm -from AlgorithmException import AlgorithmException from Controller import Controller from ObservatoryMetadata import ObservatoryMetadata from TimeseriesFactory import TimeseriesFactory from TimeseriesFactoryException import TimeseriesFactoryException import TimeseriesUtility import Util -from XYZAlgorithm import XYZAlgorithm __all__ = [ - 'Algorithm', - 'AlgorithmException', 'ChannelConverter', 'Controller', 'DeltaFAlgorithm', diff --git a/geomagio/Algorithm.py b/geomagio/algorithm/Algorithm.py similarity index 79% rename from geomagio/Algorithm.py rename to geomagio/algorithm/Algorithm.py index bd7699089..fed7196b9 100644 --- a/geomagio/Algorithm.py +++ b/geomagio/algorithm/Algorithm.py @@ -1,6 +1,6 @@ """Algorithm Interface.""" -import TimeseriesUtility +from .. import TimeseriesUtility class Algorithm(object): @@ -91,3 +91,25 @@ class Algorithm(object): endtime < input_gap[2]): return False return True + + @classmethod + def add_arguments(cls, parser): + """Add command line arguments to argparse parser. + + Parameters + ---------- + parser: ArgumentParser + command line argument parser + """ + pass + + def configure(self, arguments): + """Configure algorithm using comand line arguments. + + Parameters + ---------- + arguments: Namespace + parsed command line arguments + """ + self._inchannels = arguments.inchannels + self._outchannels = arguments.outchannels or arguments.inchannels diff --git a/geomagio/AlgorithmException.py b/geomagio/algorithm/AlgorithmException.py similarity index 100% rename from geomagio/AlgorithmException.py rename to geomagio/algorithm/AlgorithmException.py diff --git a/geomagio/DeltaFAlgorithm.py b/geomagio/algorithm/DeltaFAlgorithm.py similarity index 66% rename from geomagio/DeltaFAlgorithm.py rename to geomagio/algorithm/DeltaFAlgorithm.py index d0619dee6..616c83d87 100644 --- a/geomagio/DeltaFAlgorithm.py +++ b/geomagio/algorithm/DeltaFAlgorithm.py @@ -4,7 +4,7 @@ from Algorithm import Algorithm from AlgorithmException import AlgorithmException -import StreamConverter as StreamConverter +from .. import StreamConverter # List of channels by geomagnetic observatory orientation. # geo represents a geographic north/south orientation @@ -27,10 +27,10 @@ class DeltaFAlgorithm(Algorithm): will be converting from. """ - def __init__(self, informat=None): + def __init__(self, informat='obs'): Algorithm.__init__(self, inchannels=CHANNELS[informat], outchannels=['G']) - self.informat = informat + self._informat = informat def check_stream(self, timeseries): """checks a stream to make certain all the required channels @@ -61,10 +61,35 @@ class DeltaFAlgorithm(Algorithm): """ self.check_stream(timeseries) out_stream = None - - if self.informat == 'geo': + informat = self._informat + if informat == 'geo': out_stream = StreamConverter.get_deltaf_from_geo(timeseries) - elif self.informat == 'obs' or self.informat == 'obsd': + elif informat == 'obs' or informat == 'obsd': out_stream = StreamConverter.get_deltaf_from_obs(timeseries) return out_stream + + @classmethod + def add_arguments(cls, parser): + """Add command line arguments to argparse parser. + + Parameters + ---------- + parser: ArgumentParser + command line argument parser + """ + parser.add_argument('--deltaf-from', + choices=['geo', 'obs', 'obsd'], + default='obs', + help='Geomagnetic orientation to read from') + + def configure(self, arguments): + """Configure algorithm using comand line arguments. + + Parameters + ---------- + arguments: Namespace + parsed command line arguments + """ + self._informat = arguments.deltaf_from + self._inchannels = CHANNELS[self._informat] diff --git a/geomagio/XYZAlgorithm.py b/geomagio/algorithm/XYZAlgorithm.py similarity index 62% rename from geomagio/XYZAlgorithm.py rename to geomagio/algorithm/XYZAlgorithm.py index 12c3a1e0c..64d1e9158 100644 --- a/geomagio/XYZAlgorithm.py +++ b/geomagio/algorithm/XYZAlgorithm.py @@ -5,7 +5,7 @@ from Algorithm import Algorithm from AlgorithmException import AlgorithmException -import StreamConverter as StreamConverter +from .. import StreamConverter # List of channels by geomagnetic observatory orientation. # geo represents a geographic north/south orientation @@ -33,11 +33,11 @@ class XYZAlgorithm(Algorithm): be converting to. """ - def __init__(self, informat=None, outformat=None): + def __init__(self, informat='obs', outformat='geo'): Algorithm.__init__(self, inchannels=CHANNELS[informat], outchannels=CHANNELS[outformat]) - self.informat = informat - self.outformat = outformat + self._informat = informat + self._outformat = outformat def check_stream(self, timeseries): """checks an stream to make certain all the required channels @@ -69,36 +69,69 @@ class XYZAlgorithm(Algorithm): """ self.check_stream(timeseries) out_stream = None - if self.outformat == 'geo': - if self.informat == 'geo': + informat = self._informat + outformat = self._outformat + if outformat == 'geo': + if informat == 'geo': out_stream = timeseries - elif self.informat == 'mag': + elif informat == 'mag': out_stream = StreamConverter.get_geo_from_mag(timeseries) - elif self.informat == 'obs' or self.informat == 'obsd': + elif informat == 'obs' or informat == 'obsd': out_stream = StreamConverter.get_geo_from_obs(timeseries) - elif self.outformat == 'mag': - if self.informat == 'geo': + elif outformat == 'mag': + if informat == 'geo': out_stream = StreamConverter.get_mag_from_geo(timeseries) - elif self.informat == 'mag': + elif informat == 'mag': out_stream = timeseries - elif self.informat == 'obs' or self.informat == 'obsd': + elif informat == 'obs' or informat == 'obsd': out_stream = StreamConverter.get_mag_from_obs(timeseries) - elif self.outformat == 'obs': - if self.informat == 'geo': + elif outformat == 'obs': + if informat == 'geo': out_stream = StreamConverter.get_obs_from_geo(timeseries) - elif self.informat == 'mag': + elif informat == 'mag': out_stream = StreamConverter.get_obs_from_mag(timeseries) - elif self.informat == 'obs' or self.informat == 'obsd': + elif informat == 'obs' or informat == 'obsd': out_stream = StreamConverter.get_obs_from_obs(timeseries, include_e=True) - elif self.outformat == 'obsd': - if self.informat == 'geo': + elif outformat == 'obsd': + if informat == 'geo': out_stream = StreamConverter.get_obs_from_geo(timeseries, include_d=True) - elif self.informat == 'mag': + elif informat == 'mag': out_stream = StreamConverter.get_obs_from_mag(timeseries, include_d=True) - elif self.informat == 'obs' or self.informat == 'obsd': + elif informat == 'obs' or informat == 'obsd': out_stream = StreamConverter.get_obs_from_obs(timeseries, include_d=True) return out_stream + + @classmethod + def add_arguments(cls, parser): + """Add command line arguments to argparse parser. + + Parameters + ---------- + parser: ArgumentParser + command line argument parser + """ + parser.add_argument('--xyz-from', + choices=['geo', 'mag', 'obs', 'obsd'], + default='obs', + help='Geomagnetic orientation to read from') + parser.add_argument('--xyz-to', + choices=['geo', 'mag', 'obs', 'obsd'], + default='geo', + help='Geomagnetic orientation to convert to') + + def configure(self, arguments): + """Configure algorithm using comand line arguments. + + Parameters + ---------- + arguments: Namespace + parsed command line arguments + """ + self._informat = arguments.xyz_from + self._outformat = arguments.xyz_to + self._inchannels = CHANNELS[self._informat] + self._outchannels = CHANNELS[self._outformat] diff --git a/geomagio/algorithm/__init__.py b/geomagio/algorithm/__init__.py new file mode 100644 index 000000000..caaabb0c7 --- /dev/null +++ b/geomagio/algorithm/__init__.py @@ -0,0 +1,28 @@ +""" +Geomag Algorithms module +""" + +# base classes +from Algorithm import Algorithm +from AlgorithmException import AlgorithmException +# algorithms +from DeltaFAlgorithm import DeltaFAlgorithm +from XYZAlgorithm import XYZAlgorithm + + +# algorithms is used by Controller to auto generate arguments +algorithms = { + 'identity': Algorithm, + 'deltaf': DeltaFAlgorithm, + 'xyz': XYZAlgorithm +} + + +__all__ = [ + # base classes + 'Algorithm', + 'AlgorithmException', + # algorithms + 'DeltaFAlgorithm', + 'XYZAlgorithm' +] diff --git a/test/Controller_test.py b/test/Controller_test.py index e407a9eca..4b1992c98 100644 --- a/test/Controller_test.py +++ b/test/Controller_test.py @@ -1,5 +1,6 @@ #! /usr/bin/env python -from geomagio import Algorithm, Controller, TimeseriesFactory +from geomagio import Controller, TimeseriesFactory +from geomagio.algorithm import Algorithm from nose.tools import assert_is_instance diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/Algorithm_test.py b/test/algorithm_test/Algorithm_test.py similarity index 95% rename from test/Algorithm_test.py rename to test/algorithm_test/Algorithm_test.py index cf4d2e3cb..8ce878f1d 100644 --- a/test/Algorithm_test.py +++ b/test/algorithm_test/Algorithm_test.py @@ -2,7 +2,7 @@ from obspy.core.stream import Stream from nose.tools import assert_equals from nose.tools import assert_is_instance -from geomagio import Algorithm +from geomagio.algorithm import Algorithm def test_algorithm_process(): diff --git a/test/XYZAlgorithm_test.py b/test/algorithm_test/XYZAlgorithm_test.py similarity index 92% rename from test/XYZAlgorithm_test.py rename to test/algorithm_test/XYZAlgorithm_test.py index b84f87198..0ffcfb3ec 100644 --- a/test/XYZAlgorithm_test.py +++ b/test/algorithm_test/XYZAlgorithm_test.py @@ -2,8 +2,8 @@ from obspy.core.stream import Stream from nose.tools import assert_equals from nose.tools import assert_is -from geomagio import XYZAlgorithm -from StreamConverter_test import __create_trace +from geomagio.algorithm import XYZAlgorithm +from ..StreamConverter_test import __create_trace def test_xyzalgorithm_process(): diff --git a/test/algorithm_test/__init__.py b/test/algorithm_test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/edge_test/__init__.py b/test/edge_test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/iaga2002_test/__init__.py b/test/iaga2002_test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/imfv283_test/__init__.py b/test/imfv283_test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/pcdcp_test/__init__.py b/test/pcdcp_test/__init__.py new file mode 100644 index 000000000..e69de29bb -- GitLab