From 2357078afc91f1abcb8b5887cf3905f95628a261 Mon Sep 17 00:00:00 2001 From: Michael Joyce Date: Thu, 28 May 2015 11:01:19 -0700 Subject: [PATCH 1/3] CLIMATE-639 - Add subregion support to configuration parsing - Add subregion support to config parsing. - Add tests for parsing bad subregion information. --- ocw-config-runner/configuration_parsing.py | 24 ++++++++++++ .../tests/test_config_parsing.py | 38 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/ocw-config-runner/configuration_parsing.py b/ocw-config-runner/configuration_parsing.py index 477488ed..be8bd000 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 diff --git a/ocw-config-runner/tests/test_config_parsing.py b/ocw-config-runner/tests/test_config_parsing.py index 9df99802..88a08f7b 100644 --- a/ocw-config-runner/tests/test_config_parsing.py +++ b/ocw-config-runner/tests/test_config_parsing.py @@ -290,6 +290,36 @@ def setUpClass(self): """ 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 @@ def test_warns_regarding_not_builtin_metric(self, mock_logger): 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): From 917dbdb56e73202d470d2e48eb3625bcd3ede943 Mon Sep 17 00:00:00 2001 From: Michael Joyce Date: Thu, 28 May 2015 11:13:10 -0700 Subject: [PATCH 2/3] CLIMATE-639 - Add subregion handling to evaluation creation --- ocw-config-runner/evaluation_creation.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ocw-config-runner/evaluation_creation.py b/ocw-config-runner/evaluation_creation.py index 35021861..94967d3b 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])) From 19d861cfbbd11eb32f6d466fe9ea3e8add35f827 Mon Sep 17 00:00:00 2001 From: Michael Joyce Date: Thu, 28 May 2015 12:31:28 -0700 Subject: [PATCH 3/3] CLIMATE-639 - Add subregion support to config writing --- ocw-config-runner/configuration_writer.py | 17 +++++++++ ocw-config-runner/tests/test_config_writer.py | 37 ++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/ocw-config-runner/configuration_writer.py b/ocw-config-runner/configuration_writer.py index f7fb1c93..8fc9242a 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': {}} diff --git a/ocw-config-runner/tests/test_config_writer.py b/ocw-config-runner/tests/test_config_writer.py index 97b7e01c..f163989a 100644 --- a/ocw-config-runner/tests/test_config_writer.py +++ b/ocw-config-runner/tests/test_config_writer.py @@ -19,7 +19,7 @@ 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 @@ def setUpClass(self): 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 @@ def test_proper_evaluation_setting_export(self): 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])