CLIMATE-583 - Add subregion plot support

- Move subregion checking above plot validity checks.
- When checking for plots, if the config is deemed valid then we need to
  check to ensure that subregion information is provided for the plots
  that require it. At the moment this check is only done for subregion
  plots.
- Add required keys for subregion plots


Project: http://git-wip-us.apache.org/repos/asf/climate/repo
Commit: http://git-wip-us.apache.org/repos/asf/climate/commit/f9e13d7f
Tree: http://git-wip-us.apache.org/repos/asf/climate/tree/f9e13d7f
Diff: http://git-wip-us.apache.org/repos/asf/climate/diff/f9e13d7f

Branch: refs/heads/master
Commit: f9e13d7f4bb737d54b71b8bdd71b9b786be833e9
Parents: ba85562
Author: Michael Joyce <[email protected]>
Authored: Mon Jun 1 15:01:46 2015 -0700
Committer: Michael Joyce <[email protected]>
Committed: Thu Jun 4 14:44:29 2015 -0700

----------------------------------------------------------------------
 ocw-config-runner/configuration_parsing.py     | 27 +++++--
 ocw-config-runner/example/subregion.yaml       | 30 ++++++++
 ocw-config-runner/plot_generation.py           | 23 +++++-
 ocw-config-runner/tests/test_config_parsing.py | 82 +++++++++++++++++++++
 4 files changed, 153 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/climate/blob/f9e13d7f/ocw-config-runner/configuration_parsing.py
----------------------------------------------------------------------
diff --git a/ocw-config-runner/configuration_parsing.py 
b/ocw-config-runner/configuration_parsing.py
index a0643de..283a39d 100644
--- a/ocw-config-runner/configuration_parsing.py
+++ b/ocw-config-runner/configuration_parsing.py
@@ -112,15 +112,28 @@ def _config_is_well_formed(config_data):
             logger.warn(warning)
             is_well_formed = False
 
+    if 'subregions' in config_data:
+        for subregion in config_data['subregions']:
+            if not _valid_subregion_config_data(subregion):
+                is_well_formed = False
+
     if 'plots' in config_data:
         for plot in config_data['plots']:
             if not _valid_plot_config_data(plot):
                 is_well_formed = False
+            # Ensure that if we're trying to make a plot that require
+            # subregion info that the config has this present.
+            elif plot['type'] in ['subregion']:
+                if ('subregions' not in config_data or
+                    len(config_data['subregions'] < 1)):
+                    logger.error(
+                        'Plot config that requires subregion information is 
present '
+                        'in a config file without adequate subregion 
information '
+                        'provided. Please ensure that you have properly 
supplied 1 or '
+                        'more subregion config values.'
+                    )
+                    is_well_formed = False
 
-    if 'subregions' in config_data:
-        for subregion in config_data['subregions']:
-            if not _valid_subregion_config_data(subregion):
-                is_well_formed = False
 
     return is_well_formed
 
@@ -219,7 +232,11 @@ def _valid_plot_config_data(plot_config_data):
             'output_name'
         ])
     elif plot_type == 'subregion':
-        logger.warn('Subregion plots are currently unsupported. Skipping 
validation')
+        required_keys = set([
+            'lats',
+            'lons',
+            'output_name'
+        ])
     elif plot_type == 'time_series':
         logger.warn('Time series plots are currently unsupported. Skipping 
validation')
     elif plot_type == 'portrait':

http://git-wip-us.apache.org/repos/asf/climate/blob/f9e13d7f/ocw-config-runner/example/subregion.yaml
----------------------------------------------------------------------
diff --git a/ocw-config-runner/example/subregion.yaml 
b/ocw-config-runner/example/subregion.yaml
new file mode 100644
index 0000000..d39e39b
--- /dev/null
+++ b/ocw-config-runner/example/subregion.yaml
@@ -0,0 +1,30 @@
+subregions:
+    - [-10.0, 0.0, 29.0, 36.5]
+    - [0.0, 10.0,  29.0, 37.5]
+    - [10.0, 20.0, 25.0, 32.5]
+    - [20.0, 33.0, 25.0, 32.5]
+    - [-19.3,-10.2,12.0, 20.0]
+    - [15.0, 30.0, 15.0, 25.0]
+    - [-10.0, 10.0, 7.3, 15.0]
+    - [-10.9, 10.0, 5.0, 7.3]
+    - [33.9, 40.0,  6.9, 15.0]
+    - [10.0, 25.0,  0.0, 10.0]
+    - [10.0, 25.0,-10.0,  0.0]
+    - [30.0, 40.0,-15.0,  0.0]
+    - [33.0, 40.0, 25.0, 35.0]
+
+datasets:
+
+metrics:
+
+plots:
+    - type: subregion
+      output_name: subregion_plot
+      lats:
+          range_min: -45.0
+          range_max: 42.24
+          range_step: 0.5
+      lons:
+          range_min: -24.0
+          range_max: 60.0
+          range_step: 0.5

http://git-wip-us.apache.org/repos/asf/climate/blob/f9e13d7f/ocw-config-runner/plot_generation.py
----------------------------------------------------------------------
diff --git a/ocw-config-runner/plot_generation.py 
b/ocw-config-runner/plot_generation.py
index 677188a..9da97c2 100644
--- a/ocw-config-runner/plot_generation.py
+++ b/ocw-config-runner/plot_generation.py
@@ -37,7 +37,7 @@ def plot_from_config(evaluation, config_data):
         if plot['type'] == 'contour':
             _draw_contour_plot(evaluation, plot)
         elif plot['type'] == 'subregion':
-            logger.warn('Subregion plots are currently unsupported. Skipping 
...')
+            _draw_subregion_diagram(evaluation, plot)
         elif plot['type'] == 'taylor':
             _draw_taylor_diagram(evaluation, plot)
         elif plot['type'] == 'time_series':
@@ -51,12 +51,11 @@ def _draw_contour_plot(evaluation, plot_config):
     """"""
     lats = plot_config['lats']
     if type(lats) != type(list):
-        lats = range(lats['range_min'], lats['range_max'], lats['range_step'])
+        lats = np.arange(lats['range_min'], lats['range_max'], 
lats['range_step'])
 
     lons = plot_config['lons']
     if type(lons) != type(list):
-        lons = range(lons['range_min'], lons['range_max'], lons['range_step'])
-
+        lons = np.arange(lons['range_min'], lons['range_max'], 
lons['range_step'])
 
     for i, (row, col) in enumerate(plot_config['results_indices']):
         plot_name = plot_config['output_name'] + '_{}'.format(i)
@@ -89,3 +88,19 @@ def _draw_taylor_diagram(evaluation, plot_config):
                               ref_dataset_name,
                               fname=plot_name,
                               **plot_config.get('optional_args', {}))
+
+def _draw_subregion_diagram(evaluation, plot_config):
+    """"""
+    lats = plot_config['lats']
+    if type(lats) != type(list):
+        lats = np.arange(lats['range_min'], lats['range_max'], 
lats['range_step'])
+
+    lons = plot_config['lons']
+    if type(lons) != type(list):
+        lons = np.arange(lons['range_min'], lons['range_max'], 
lons['range_step'])
+
+    plots.draw_subregions(evaluation.subregions,
+                          lats,
+                          lons,
+                          plot_config['output_name'],
+                          **plot_config.get('optional_args', {}))

http://git-wip-us.apache.org/repos/asf/climate/blob/f9e13d7f/ocw-config-runner/tests/test_config_parsing.py
----------------------------------------------------------------------
diff --git a/ocw-config-runner/tests/test_config_parsing.py 
b/ocw-config-runner/tests/test_config_parsing.py
index 88a08f7..e918405 100644
--- a/ocw-config-runner/tests/test_config_parsing.py
+++ b/ocw-config-runner/tests/test_config_parsing.py
@@ -682,6 +682,53 @@ class ContourMapConfig(unittest.TestCase):
         mock_logger.error.assert_called_with(err)
 
 
+class TestSubregionPlotConfig(unittest.TestCase):
+    @classmethod
+    def setUpClass(self):
+        valid_subregion_config = """
+            type: subregion
+            lats:
+                range_min: -20
+                range_max: 20
+                range_step: 1
+            lons:
+                range_min: -20
+                range_max: 20
+                range_step: 1
+            output_name: fake_plot_name
+        """
+        self.valid_subregion = yaml.load(valid_subregion_config)
+
+        missing_keys_subregion_config = """
+            type: subregion
+        """
+        self.missing_keys_subregion = yaml.load(missing_keys_subregion_config)
+
+        self.required_subregion_keys = set([
+            'lats',
+            'lons',
+            'output_name'
+        ])
+
+    def test_valid_subregion(self):
+        ret = parser._valid_plot_config_data(self.valid_subregion)
+        self.assertTrue(ret)
+
+    @patch('configuration_parsing.logger')
+    def test_missing_keys_subregion(self, mock_logger):
+        ret = parser._valid_plot_config_data(self.missing_keys_subregion)
+
+        present_keys = set(self.missing_keys_subregion.keys())
+        missing_keys = self.required_subregion_keys - present_keys
+        missing = sorted(list(missing_keys))
+
+        err = (
+            'Plot config does not contain required keys. '
+            'The following keys are missing: {}'
+        ).format(', '.join(missing))
+        mock_logger.error.assert_called_with(err)
+
+
 class TestInvalidPlotConfig(unittest.TestCase):
     @classmethod
     def setUpClass(self):
@@ -705,6 +752,29 @@ class TestInvalidPlotConfig(unittest.TestCase):
         """
         self.missing_plot_type = yaml.load(missing_plot_type_config)
 
+        missing_subregions_for_plot_type = """
+            datasets:
+                - blah
+
+            metrics:
+                - blah
+            
+            plots:
+                - type: subregion
+                  results_indices:
+                      - !!python/tuple [0, 0]
+                  lats:
+                      range_min: -20
+                      range_max: 20
+                      range_step: 1
+                  lons:
+                      range_min: -20
+                      range_max: 20
+                      range_step: 1
+                  output_name: wrf_bias_compared_to_knmi
+        """
+        self.missing_subregions = yaml.load(missing_subregions_for_plot_type)
+
     @patch('configuration_parsing.logger')
     def test_invalid_plot_type(self, mock_logger):
         ret = parser._valid_plot_config_data(self.bad_plot_type)
@@ -722,3 +792,15 @@ class TestInvalidPlotConfig(unittest.TestCase):
         mock_logger.error.assert_called_with(
             'Plot config does not include a type attribute.'
         )
+        
+    @patch('configuration_parsing.logger')
+    def test_missing_subregion(self, mock_logger):
+        ret = parser._config_is_well_formed(self.missing_subregions)
+        self.assertFalse(ret)
+
+        mock_logger.error.assert_called_with(
+            'Plot config that requires subregion information is present '
+            'in a config file without adequate subregion information '
+            'provided. Please ensure that you have properly supplied 1 or '
+            'more subregion config values.'
+        )

Reply via email to