You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@climate.apache.org by jo...@apache.org on 2015/06/01 20:02:34 UTC

[1/8] climate git commit: CLIMATE-636 - Fix Bounds __str__ formatting

Repository: climate
Updated Branches:
  refs/heads/master 6ab02d8f6 -> e8384204c


CLIMATE-636 - Fix Bounds __str__ formatting


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

Branch: refs/heads/master
Commit: 52d222b8f978c9ac9d072239f7387713e7880a01
Parents: 6ab02d8
Author: Michael Joyce <jo...@apache.org>
Authored: Wed May 27 15:38:55 2015 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Wed May 27 15:38:55 2015 -0700

----------------------------------------------------------------------
 ocw/dataset.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/climate/blob/52d222b8/ocw/dataset.py
----------------------------------------------------------------------
diff --git a/ocw/dataset.py b/ocw/dataset.py
index d33bdd4..e432928 100644
--- a/ocw/dataset.py
+++ b/ocw/dataset.py
@@ -360,8 +360,8 @@ class Bounds(object):
         self._end = value
 
     def __str__(self):
-        lat_range = "({}, {})".format(self._lat_min, self._lon_min)
-        lon_range = "({}, {})".format(self._lon_min, self._lon_min)
+        lat_range = "({}, {})".format(self._lat_min, self._lat_max)
+        lon_range = "({}, {})".format(self._lon_min, self._lon_max)
         time_range = "({}, {})".format(self._start, self._end)
 
         formatted_repr = (


[2/8] climate git commit: CLIMATE-637 - Subregion clean up and improvements

Posted by jo...@apache.org.
CLIMATE-637 - Subregion clean up and improvements

- Add tests for unary/binary evaluation results output formatting to
  ensure that data is nested properly in the results lists.
- Add subregion support for unary metrics.
- Adjust the ordering that subregions are computed during an evaluation
  for performance improvements.


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

Branch: refs/heads/master
Commit: f4849f272a71a73ce955828deb811f625305d85a
Parents: 6ab02d8
Author: Michael Joyce <jo...@apache.org>
Authored: Thu May 28 09:37:14 2015 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Thu May 28 09:37:14 2015 -0700

----------------------------------------------------------------------
 ocw/evaluation.py            |  42 ++++++++++++---
 ocw/tests/test_evaluation.py | 107 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 143 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/climate/blob/f4849f27/ocw/evaluation.py
----------------------------------------------------------------------
diff --git a/ocw/evaluation.py b/ocw/evaluation.py
index 96c19ad..9581d96 100644
--- a/ocw/evaluation.py
+++ b/ocw/evaluation.py
@@ -234,7 +234,10 @@ class Evaluation(object):
                 self.results = self._run_no_subregion_evaluation()
 
         if self._should_run_unary_metrics():
-            self.unary_results = self._run_unary_metric_evaluation()
+            if self.subregions:
+                self.unary_results = self._run_subregion_unary_evaluation()
+            else:
+                self.unary_results = self._run_unary_metric_evaluation()
 
     def _evaluation_is_valid(self):
         '''Check if the evaluation is well-formed.
@@ -267,15 +270,18 @@ class Evaluation(object):
 
     def _run_subregion_evaluation(self):
         results = []
+        new_refs = [DSP.subset(s, self.ref_dataset) for s in self.subregions]
+
         for target in self.target_datasets:
             results.append([])
+            new_targets = [DSP.subset(s, target) for s in self.subregions]
+
             for metric in self.metrics:
                 results[-1].append([])
-                for subregion in self.subregions:
-                    # Subset the reference and target dataset with the 
-                    # subregion information.
-                    new_ref = DSP.subset(subregion, self.ref_dataset)
-                    new_tar = DSP.subset(subregion, target)
+
+                for i in range(len(self.subregions)):
+                    new_ref = new_refs[i]
+                    new_tar = new_targets[i]
 
                     run_result = metric.run(new_ref, new_tar)
                     results[-1][-1].append(run_result)
@@ -302,6 +308,30 @@ class Evaluation(object):
                 unary_results[-1].append(metric.run(target))
         return unary_results
 
+    def _run_subregion_unary_evaluation(self):
+        unary_results = []
+        if self.ref_dataset:
+            new_refs = [DSP.subset(s, self.ref_dataset) for s in self.subregions]
+
+        new_targets = [
+            [DSP.subset(s, t) for s in self.subregions]
+            for t in self.target_datasets
+        ]
+
+        for metric in self.unary_metrics:
+            unary_results.append([])
+
+            for i in range(len(self.subregions)):
+                unary_results[-1].append([])
+
+                if self.ref_dataset:
+                    unary_results[-1][-1].append(metric.run(new_refs[i]))
+
+                for t in range(len(self.target_datasets)):
+                    unary_results[-1][-1].append(metric.run(new_targets[t][i]))
+
+        return unary_results
+
     def __str__(self):
         formatted_repr = (
             "<Evaluation - ref_dataset: {}, "

http://git-wip-us.apache.org/repos/asf/climate/blob/f4849f27/ocw/tests/test_evaluation.py
----------------------------------------------------------------------
diff --git a/ocw/tests/test_evaluation.py b/ocw/tests/test_evaluation.py
index 9e8d126..4a02714 100644
--- a/ocw/tests/test_evaluation.py
+++ b/ocw/tests/test_evaluation.py
@@ -125,5 +125,112 @@ class TestEvaluation(unittest.TestCase):
         bias_results_shape = tuple(bias_eval.results[0][0].shape)
         self.assertEqual(input_shape, bias_results_shape)
 
+    def test_result_shape(self):
+        bias_eval = Evaluation(
+            self.test_dataset,
+            [self.another_test_dataset, self.another_test_dataset],
+            [Bias()]
+        )
+        bias_eval.run()
+
+        # Expected result shape is
+        # [
+        #   [
+        #       bias.run(reference, target1)
+        #   ],
+        #   [
+        #       bias.run(reference, target2)
+        #   ]
+        # ]
+        self.assertTrue(len(bias_eval.results) == 2)
+        self.assertTrue(len(bias_eval.results[0]) == 1)
+        self.assertTrue(len(bias_eval.results[1]) == 1)
+
+    def test_unary_result_shape(self):
+        new_eval = Evaluation(
+            self.test_dataset,
+            [self.another_test_dataset, self.another_test_dataset],
+            [TemporalStdDev()]
+        )
+        new_eval.run()
+
+        # Expected result shape is
+        # [
+        #   temporalstddev.run(reference),
+        #   temporalstddev.run(target1),
+        #   temporalstddev.run(target2)
+        # ]
+        self.assertTrue(len(new_eval.unary_results) == 1)
+        self.assertTrue(len(new_eval.unary_results[0]) == 3)
+
+    def test_subregion_result_shape(self):
+        bound = Bounds(
+                10, 18, 
+                100, 108, 
+                dt.datetime(2000, 1, 1), dt.datetime(2000, 3, 1))
+
+        bias_eval = Evaluation(
+            self.test_dataset,
+            [self.another_test_dataset, self.another_test_dataset],
+            [Bias()],
+            [bound]
+        )
+        bias_eval.run()
+
+        # Expected result shape is
+        # [
+        #   [
+        #       [   # Subregions cause this extra layer
+        #           bias.run(reference, target1)
+        #       ]
+        #   ],
+        #   [
+        #       [
+        #           bias.run(reference, target2)
+        #       ]
+        #   ]
+        # ]
+        self.assertTrue(len(bias_eval.results) == 2)
+
+        self.assertTrue(len(bias_eval.results[0]) == 1)
+        self.assertTrue(type(bias_eval.results[0]) == type([]))
+        self.assertTrue(len(bias_eval.results[1]) == 1)
+        self.assertTrue(type(bias_eval.results[1]) == type([]))
+
+        self.assertTrue(len(bias_eval.results[0][0]) == 1)
+        self.assertTrue(len(bias_eval.results[1][0]) == 1)
+
+    def test_subregion_unary_result_shape(self):
+        bound = Bounds(
+                10, 18, 
+                100, 108, 
+                dt.datetime(2000, 1, 1), dt.datetime(2000, 3, 1))
+
+        new_eval = Evaluation(
+            self.test_dataset,
+            [self.another_test_dataset, self.another_test_dataset],
+            [TemporalStdDev()],
+            [bound]
+        )
+        new_eval.run()
+
+        # Expected result shape is
+        # [
+        #   [   
+        #       [   # Subregions cause this extra layer
+        #           temporalstddev.run(reference),
+        #           temporalstddev.run(target1),
+        #           temporalstddev.run(target2)
+        #       ]
+        #   ]
+        # ]
+        self.assertTrue(len(new_eval.unary_results) == 1)
+        self.assertTrue(type(new_eval.unary_results) == type([]))
+
+        self.assertTrue(len(new_eval.unary_results[0]) == 1)
+
+        self.assertTrue(len(new_eval.unary_results[0][0]) == 3)
+
+
 if __name__  == '__main__':
     unittest.main()


[3/8] climate git commit: CLIMATE-639 - Add subregion support to configuration parsing

Posted by jo...@apache.org.
CLIMATE-639 - Add subregion support to configuration parsing

- Add subregion support to config parsing.
- Add tests for parsing bad subregion information.


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

Branch: refs/heads/master
Commit: 2357078afc91f1abcb8b5887cf3905f95628a261
Parents: 6ab02d8
Author: Michael Joyce <jo...@apache.org>
Authored: Thu May 28 11:01:19 2015 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Thu May 28 11:01:19 2015 -0700

----------------------------------------------------------------------
 ocw-config-runner/configuration_parsing.py     | 24 +++++++++++++
 ocw-config-runner/tests/test_config_parsing.py | 38 +++++++++++++++++++++
 2 files changed, 62 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/climate/blob/2357078a/ocw-config-runner/configuration_parsing.py
----------------------------------------------------------------------
diff --git a/ocw-config-runner/configuration_parsing.py b/ocw-config-runner/configuration_parsing.py
index 477488e..be8bd00 100644
--- a/ocw-config-runner/configuration_parsing.py
+++ b/ocw-config-runner/configuration_parsing.py
@@ -117,6 +117,11 @@ def _config_is_well_formed(config_data):
             if not _valid_plot_config_data(plot):
                 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
 
 def _contains_unary_metrics(config_metric_data):
@@ -233,3 +238,22 @@ def _valid_plot_config_data(plot_config_data):
 
     return True
 
+def _valid_subregion_config_data(subregion_config_data):
+    """"""
+    if type(subregion_config_data) != type([]):
+        logger.error(
+            'Subregions should be passed as a list of lists where '
+            'each sub-list contains a bounding box of the form: '
+            '[lat_min, lat_max, lon_min, lon_max].'
+        )
+        return False
+
+    if len(subregion_config_data) != 4:
+        logger.error(
+            'Subregions should be passed as a list of lists where '
+            'each sub-list contains a bounding box of the form: '
+            '[lat_min, lat_max, lon_min, lon_max].'
+        )
+        return False
+
+    return True

http://git-wip-us.apache.org/repos/asf/climate/blob/2357078a/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 9df9980..88a08f7 100644
--- a/ocw-config-runner/tests/test_config_parsing.py
+++ b/ocw-config-runner/tests/test_config_parsing.py
@@ -290,6 +290,36 @@ class TestConfigIsWellFormed(unittest.TestCase):
         """
         bad_plot = yaml.load(bad_plot_config)
 
+        bad_subregion_config_type = """
+            datasets:
+                reference:
+                    data_source: dap
+                    url: afakeurl.com
+                    variable: pr
+
+            metrics:
+                - Bias
+
+            subregions:
+                - this is a string instead of a list
+        """
+        self.bad_subregion_type = yaml.load(bad_subregion_config_type)
+
+        bad_subregion_config_length = """
+            datasets:
+                reference:
+                    data_source: dap
+                    url: afakeurl.com
+                    variable: pr
+
+            metrics:
+                - Bias
+
+            subregions:
+                - [1, 2, 3, 4, 5]
+        """
+        self.bad_subregion_length = yaml.load(bad_subregion_config_length)
+
     def test_malformed_reference_config(self):
         ret = parser._config_is_well_formed(self.malformed_reference_conf)
         self.assertFalse(ret)
@@ -320,6 +350,14 @@ class TestConfigIsWellFormed(unittest.TestCase):
     def test_bad_plot_config(self):
         ret = parser._config_is_well_formed(self.missing_metric_name)
         self.assertFalse(ret)
+    
+    def test_bad_subregion_type(self):
+        ret = parser._config_is_well_formed(self.bad_subregion_type)
+        self.assertFalse(ret)
+
+    def test_bad_subregion_length(self):
+        ret = parser._config_is_well_formed(self.bad_subregion_length)
+        self.assertFalse(ret)
 
 
 class MetricFetchTest(unittest.TestCase):


[7/8] climate git commit: Resolve CLIMATE-637. Merge PR #201.

Posted by jo...@apache.org.
Resolve CLIMATE-637. Merge PR #201.


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

Branch: refs/heads/master
Commit: 8c6bf05423688ede48f4d48f03eef41d73df3db7
Parents: f87a875 f4849f2
Author: Michael Joyce <jo...@apache.org>
Authored: Mon Jun 1 10:59:58 2015 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Mon Jun 1 10:59:58 2015 -0700

----------------------------------------------------------------------
 ocw/evaluation.py            |  42 ++++++++++++---
 ocw/tests/test_evaluation.py | 107 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 143 insertions(+), 6 deletions(-)
----------------------------------------------------------------------



[8/8] climate git commit: Resolve CLIMATE-639. Resolve PR #203.

Posted by jo...@apache.org.
Resolve CLIMATE-639. Resolve PR #203.


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

Branch: refs/heads/master
Commit: e8384204c66ee283be6cabd901a171ecb8b6dc59
Parents: 8c6bf05 19d861c
Author: Michael Joyce <jo...@apache.org>
Authored: Mon Jun 1 11:01:07 2015 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Mon Jun 1 11:01:07 2015 -0700

----------------------------------------------------------------------
 ocw-config-runner/configuration_parsing.py     | 24 +++++++++++++
 ocw-config-runner/configuration_writer.py      | 17 +++++++++
 ocw-config-runner/evaluation_creation.py       | 14 +++++++-
 ocw-config-runner/tests/test_config_parsing.py | 38 +++++++++++++++++++++
 ocw-config-runner/tests/test_config_writer.py  | 37 ++++++++++++++++++--
 5 files changed, 127 insertions(+), 3 deletions(-)
----------------------------------------------------------------------



[6/8] climate git commit: Resolve CLIMATE-636. Merge PR #200

Posted by jo...@apache.org.
Resolve CLIMATE-636. Merge PR #200


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

Branch: refs/heads/master
Commit: f87a8751c8d4f8ceac90a5d5450b0ac93a6a3e70
Parents: 6ab02d8 52d222b
Author: Michael Joyce <jo...@apache.org>
Authored: Mon Jun 1 10:59:25 2015 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Mon Jun 1 10:59:25 2015 -0700

----------------------------------------------------------------------
 ocw/dataset.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------



[4/8] climate git commit: CLIMATE-639 - Add subregion handling to evaluation creation

Posted by jo...@apache.org.
CLIMATE-639 - Add subregion handling to evaluation creation


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

Branch: refs/heads/master
Commit: 917dbdb56e73202d470d2e48eb3625bcd3ede943
Parents: 2357078
Author: Michael Joyce <jo...@apache.org>
Authored: Thu May 28 11:13:10 2015 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Thu May 28 11:13:10 2015 -0700

----------------------------------------------------------------------
 ocw-config-runner/evaluation_creation.py | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/climate/blob/917dbdb5/ocw-config-runner/evaluation_creation.py
----------------------------------------------------------------------
diff --git a/ocw-config-runner/evaluation_creation.py b/ocw-config-runner/evaluation_creation.py
index 3502186..94967d3 100644
--- a/ocw-config-runner/evaluation_creation.py
+++ b/ocw-config-runner/evaluation_creation.py
@@ -58,7 +58,12 @@ def generate_evaluation_from_config(config_data):
     # Load metrics
     eval_metrics = [_load_metric(m)() for m in config_data['metrics']]
 
-    return Evaluation(reference, targets, eval_metrics)
+    # Load Subregions (if present)
+    subregions = None
+    if 'subregions' in config_data:
+        subregions = [_load_subregion(s) for s in config_data['subregions']]
+
+    return Evaluation(reference, targets, eval_metrics, subregions=subregions)
 
 def _load_dataset(dataset_config_data):
     """"""
@@ -147,3 +152,10 @@ def _load_metric(metric_config_data):
         return None
 
     return getattr(metrics, metric_config_data)
+
+def _load_subregion(subregion_config_data):
+    """"""
+    return Bounds(float(subregion_config_data[0]),
+                  float(subregion_config_data[1]),
+                  float(subregion_config_data[2]),
+                  float(subregion_config_data[3]))


[5/8] climate git commit: CLIMATE-639 - Add subregion support to config writing

Posted by jo...@apache.org.
CLIMATE-639 - Add subregion support to config writing


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

Branch: refs/heads/master
Commit: 19d861cfbbd11eb32f6d466fe9ea3e8add35f827
Parents: 917dbdb
Author: Michael Joyce <jo...@apache.org>
Authored: Thu May 28 12:31:28 2015 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Thu May 28 12:31:28 2015 -0700

----------------------------------------------------------------------
 ocw-config-runner/configuration_writer.py     | 17 ++++++++++
 ocw-config-runner/tests/test_config_writer.py | 37 ++++++++++++++++++++--
 2 files changed, 52 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/climate/blob/19d861cf/ocw-config-runner/configuration_writer.py
----------------------------------------------------------------------
diff --git a/ocw-config-runner/configuration_writer.py b/ocw-config-runner/configuration_writer.py
index f7fb1c9..8fc9242 100644
--- a/ocw-config-runner/configuration_writer.py
+++ b/ocw-config-runner/configuration_writer.py
@@ -37,6 +37,7 @@ def export_evaluation_to_config(evaluation, file_path='./exported_eval.yaml'):
     config['evaluation'] = generate_evaluation_information(evaluation)
     config['datasets'] = generate_dataset_information(evaluation)
     config['metrics'] = generate_metric_information(evaluation)
+    config['subregions'] = generate_subregion_information(evaluation)
 
     yaml.dump(config, file(file_path, 'w'))
 
@@ -158,6 +159,22 @@ def generate_evaluation_information(evaluation):
 
     return eval_config
 
+def generate_subregion_information(evaluation):
+    ''' Generate subregion config file output from a given Evaluation object.
+
+    :param evaluation: The evaluation object from which to extract metrics.
+    :type evaluation: :class:`evaluation.Evaluation`
+
+    :returns: A :func:`list` of :func:`list` objects containing bounding
+        box info for export into a configuration file
+    :rtype: :func:`list` of :func:`list`
+    '''
+    subregions = []
+    for s in evaluation.subregions:
+        subregions.append([s.lat_min, s.lat_max, s.lon_min, s.lon_max])
+
+    return subregions
+
 def _extract_local_dataset_info(dataset):
     ''''''
     dataset_info = {'optional_args': {}}

http://git-wip-us.apache.org/repos/asf/climate/blob/19d861cf/ocw-config-runner/tests/test_config_writer.py
----------------------------------------------------------------------
diff --git a/ocw-config-runner/tests/test_config_writer.py b/ocw-config-runner/tests/test_config_writer.py
index 97b7e01..f163989 100644
--- a/ocw-config-runner/tests/test_config_writer.py
+++ b/ocw-config-runner/tests/test_config_writer.py
@@ -19,7 +19,7 @@ from mock import patch
 import os
 import unittest
 
-from ocw.dataset import Dataset
+from ocw.dataset import Dataset, Bounds
 from ocw.evaluation import Evaluation
 import ocw.metrics as metrics
 import configuration_writer as writer
@@ -651,10 +651,16 @@ class FullExportTest(unittest.TestCase):
             origin=self.dap_origin
         )
 
+        self.subregions = [
+            Bounds(-10, 10, -20, 20),
+            Bounds(-5, 5, -15, 15)
+        ]
+
         self.evaluation = Evaluation(
             self.local_ds,
             [self.rcmed_ds, self.esgf_ds, self.dap_ds],
-            [metrics.Bias(), metrics.TemporalStdDev()]
+            [metrics.Bias(), metrics.TemporalStdDev()],
+            subregions=self.subregions
         )
 
     @classmethod
@@ -733,3 +739,30 @@ class FullExportTest(unittest.TestCase):
             writer.generate_evaluation_information(self.evaluation),
             data['evaluation']
         )
+
+    def test_proper_subregion_export(self):
+        file_path = '/tmp/test_config.yaml'
+        writer.export_evaluation_to_config(
+            self.evaluation,
+            file_path=file_path
+        )
+
+        data = yaml.load(open(file_path, 'r'))
+
+        self.assertTrue('subregions' in data)
+
+        first_bounds = [
+            self.subregions[0].lat_min,
+            self.subregions[0].lat_max,
+            self.subregions[0].lon_min,
+            self.subregions[0].lon_max,
+        ]
+        second_bounds = [
+            self.subregions[1].lat_min,
+            self.subregions[1].lat_max,
+            self.subregions[1].lon_min,
+            self.subregions[1].lon_max,
+        ]
+
+        self.assertEqual(first_bounds, data['subregions'][0])
+        self.assertEqual(second_bounds, data['subregions'][1])