CLIMATE-827 - Adding spatial masking options - new masking options, CORDEX, us_states, countires and user have been added - dataset_processor.subset will be updated later.
Project: http://git-wip-us.apache.org/repos/asf/climate/repo Commit: http://git-wip-us.apache.org/repos/asf/climate/commit/02dfdec6 Tree: http://git-wip-us.apache.org/repos/asf/climate/tree/02dfdec6 Diff: http://git-wip-us.apache.org/repos/asf/climate/diff/02dfdec6 Branch: refs/heads/master Commit: 02dfdec65adb81cdc659764008045e99f61bbf4d Parents: 0cc4b1e Author: huikyole <[email protected]> Authored: Tue Aug 2 16:35:28 2016 -0700 Committer: huikyole <[email protected]> Committed: Tue Aug 2 16:35:28 2016 -0700 ---------------------------------------------------------------------- RCMES/cli_app.py | 2 +- RCMES/run_RCMES.py | 2 +- RCMES/test/test.py | 2 +- examples/knmi_to_cru31_full_bias.py | 2 +- examples/model_ensemble_to_rcmed.py | 2 +- examples/multi_model_evaluation.py | 2 +- examples/multi_model_taylor_diagram.py | 2 +- examples/taylor_diagram_example.py | 2 +- examples/time_series_with_regions.py | 2 +- ocw/dataset.py | 176 +++++++-------------- ocw/dataset_processor.py | 113 ++++++------- ocw/tests/test_dataset.py | 126 ++++----------- ocw/tests/test_dataset_processor.py | 62 ++++---- ocw/tests/test_evaluation.py | 18 +-- ocw_config_runner/tests/test_config_writer.py | 4 +- 15 files changed, 201 insertions(+), 316 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/RCMES/cli_app.py ---------------------------------------------------------------------- diff --git a/RCMES/cli_app.py b/RCMES/cli_app.py index 9894a35..22572db 100644 --- a/RCMES/cli_app.py +++ b/RCMES/cli_app.py @@ -634,7 +634,7 @@ def run_screen(model_datasets, models_info, observations_info, screen.addstr(4, 4, "--> Data retrieved.") screen.refresh() - EVAL_BOUNDS = Bounds(overlap_min_lat, overlap_max_lat, overlap_min_lon, overlap_max_lon, overlap_start_time, overlap_end_time) + EVAL_BOUNDS = Bounds(lat_min=overlap_min_lat, lat_max=overlap_max_lat, lon_min=overlap_min_lon, lon_max=overlap_max_lon, start=overlap_start_time, end=overlap_end_time) screen.addstr(5, 4, "Temporally regridding...") screen.refresh() http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/RCMES/run_RCMES.py ---------------------------------------------------------------------- diff --git a/RCMES/run_RCMES.py b/RCMES/run_RCMES.py index cd69bc4..d026ec3 100644 --- a/RCMES/run_RCMES.py +++ b/RCMES/run_RCMES.py @@ -144,7 +144,7 @@ if ref_data_info['data_source'] == 'rcmed': max_lat = np.min([max_lat, ref_dataset.lats.max()]) min_lon = np.max([min_lon, ref_dataset.lons.min()]) max_lon = np.min([max_lon, ref_dataset.lons.max()]) -bounds = Bounds(min_lat, max_lat, min_lon, max_lon, start_time, end_time) +bounds = Bounds(lat_min=min_lat, lat_max=max_lat, lon_min=min_lon, lon_max=max_lon, start=start_time, end=end_time) ref_dataset = dsp.subset(ref_dataset, bounds) if ref_dataset.temporal_resolution() != temporal_resolution: http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/RCMES/test/test.py ---------------------------------------------------------------------- diff --git a/RCMES/test/test.py b/RCMES/test/test.py index 677a13f..a62d781 100644 --- a/RCMES/test/test.py +++ b/RCMES/test/test.py @@ -111,7 +111,7 @@ print("KNMI_Dataset.values shape: (times, lats, lons) - %s" % (knmi_dataset.valu print("Our two datasets have a mis-match in time. We will subset on time to %s years\n" % YEARS) # Create a Bounds object to use for subsetting -new_bounds = Bounds(min_lat, max_lat, min_lon, max_lon, start_time, end_time) +new_bounds = Bounds(lat_min=min_lat, lat_max=max_lat, lon_min=min_lon, lon_max=max_lon, start=start_time, end=end_time) knmi_dataset = dsp.subset(knmi_dataset, new_bounds) print("CRU31_Dataset.values shape: (times, lats, lons) - %s" % (cru31_dataset.values.shape,)) http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/examples/knmi_to_cru31_full_bias.py ---------------------------------------------------------------------- diff --git a/examples/knmi_to_cru31_full_bias.py b/examples/knmi_to_cru31_full_bias.py index 4c0abd9..dd70341 100644 --- a/examples/knmi_to_cru31_full_bias.py +++ b/examples/knmi_to_cru31_full_bias.py @@ -111,7 +111,7 @@ print("KNMI_Dataset.values shape: (times, lats, lons) - %s" % (knmi_dataset.valu print("Our two datasets have a mis-match in time. We will subset on time to %s years\n" % YEARS) # Create a Bounds object to use for subsetting -new_bounds = Bounds(min_lat, max_lat, min_lon, max_lon, start_time, end_time) +new_bounds = Bounds(lat_min=min_lat, lat_max=max_lat, lon_min=min_lon, lon_max=max_lon, start=start_time, end=end_time) knmi_dataset = dsp.subset(knmi_dataset, new_bounds) print("CRU31_Dataset.values shape: (times, lats, lons) - %s" % (cru31_dataset.values.shape,)) http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/examples/model_ensemble_to_rcmed.py ---------------------------------------------------------------------- diff --git a/examples/model_ensemble_to_rcmed.py b/examples/model_ensemble_to_rcmed.py index fef1f9d..7b82197 100644 --- a/examples/model_ensemble_to_rcmed.py +++ b/examples/model_ensemble_to_rcmed.py @@ -128,7 +128,7 @@ cru31_dataset = dsp.temporal_rebin(cru31_dataset, temporal_resolution = 'annual' # Running Temporal Rebin early helps negate the issue of datasets being on different # days of the month (1st vs. 15th) # Create a Bounds object to use for subsetting -new_bounds = Bounds(min_lat, max_lat, min_lon, max_lon, start_time, end_time) +new_bounds = Bounds(lat_min=min_lat, lat_max=max_lat, lon_min=min_lon, lon_max=max_lon, start=start_time, end=end_time) # Subset our model datasets so they are the same size knmi_dataset = dsp.subset(knmi_dataset, new_bounds) http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/examples/multi_model_evaluation.py ---------------------------------------------------------------------- diff --git a/examples/multi_model_evaluation.py b/examples/multi_model_evaluation.py index 0755279..97c96d9 100644 --- a/examples/multi_model_evaluation.py +++ b/examples/multi_model_evaluation.py @@ -50,7 +50,7 @@ LON_MIN = -24.0 LON_MAX = 60.0 START = datetime.datetime(2000, 1, 1) END = datetime.datetime(2007, 12, 31) -EVAL_BOUNDS = Bounds(LAT_MIN, LAT_MAX, LON_MIN, LON_MAX, START, END) +EVAL_BOUNDS = Bounds(lat_min=LAT_MIN, lat_max=LAT_MAX, lon_min=LON_MIN, lon_max=LON_MAX, start=START, end=END) #regridding parameters gridLonStep=0.5 http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/examples/multi_model_taylor_diagram.py ---------------------------------------------------------------------- diff --git a/examples/multi_model_taylor_diagram.py b/examples/multi_model_taylor_diagram.py index 9ba8746..b7daf61 100644 --- a/examples/multi_model_taylor_diagram.py +++ b/examples/multi_model_taylor_diagram.py @@ -34,7 +34,7 @@ LON_MIN = -24.0 LON_MAX = 60.0 START = datetime.datetime(2000, 01, 1) END = datetime.datetime(2007, 12, 31) -EVAL_BOUNDS = Bounds(LAT_MIN, LAT_MAX, LON_MIN, LON_MAX, START, END) +EVAL_BOUNDS = Bounds(lat_min=LAT_MIN, lat_max=LAT_MAX, lon_min=LON_MIN, lon_max=LON_MAX, start=START, end=END) #variable that we are analyzing varName = 'pr' http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/examples/taylor_diagram_example.py ---------------------------------------------------------------------- diff --git a/examples/taylor_diagram_example.py b/examples/taylor_diagram_example.py index 66ca175..bae85be 100644 --- a/examples/taylor_diagram_example.py +++ b/examples/taylor_diagram_example.py @@ -61,7 +61,7 @@ wrf_dataset = dsp.normalize_dataset_datetimes(wrf_dataset, 'monthly') # We're only going to run this evaluation over a years worth of data. We'll # make a Bounds object and use it to subset our datasets. ################################################################################ -subset = Bounds(-45, 42, -24, 60, datetime.datetime(1989, 1, 1), datetime.datetime(1989, 12, 1)) +subset = Bounds(lat_min=-45, lat_max=42, lon_min=-24, lon_max=60, start=datetime.datetime(1989, 1, 1), end=datetime.datetime(1989, 12, 1)) knmi_dataset = dsp.subset(knmi_dataset, subset) wrf_dataset = dsp.subset(wrf_dataset, subset) http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/examples/time_series_with_regions.py ---------------------------------------------------------------------- diff --git a/examples/time_series_with_regions.py b/examples/time_series_with_regions.py index 8d9e5c0..15e2ee2 100644 --- a/examples/time_series_with_regions.py +++ b/examples/time_series_with_regions.py @@ -32,7 +32,7 @@ LON_MAX = 60.0 START = datetime.datetime(2000, 01, 1) END = datetime.datetime(2007, 12, 31) -EVAL_BOUNDS = Bounds(LAT_MIN, LAT_MAX, LON_MIN, LON_MAX, START, END) +EVAL_BOUNDS = Bounds(lat_min=LAT_MIN, lat_max=LAT_MAX, lon_min=LON_MIN, lon_max=LON_MAX, start=START, end=END) varName = 'pr' gridLonStep=0.44 http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/ocw/dataset.py ---------------------------------------------------------------------- diff --git a/ocw/dataset.py b/ocw/dataset.py index 509c04a..52e610a 100644 --- a/ocw/dataset.py +++ b/ocw/dataset.py @@ -28,6 +28,7 @@ import datetime as dt from mpl_toolkits.basemap import Basemap import netCDF4 +import ocw import ocw.utils as utils logger = logging.getLogger(__name__) @@ -295,32 +296,6 @@ class Bounds(object): else: self._end = None - @property - def start(self): - return self._start - - @start.setter - def start(self, value): - if self._end: - if not (type(value) is dt.datetime and value < self._end): - error = "Attempted to set start to invalid value: %s" % (value) - logger.error(error) - raise ValueError(error) - - self._start = value - - @property - def end(self): - return self._end - - @end.setter - def end(self, value): - if self._start: - if not (type(value) is dt.datetime and value > self._start): - error = "Attempted to set end to invalid value: %s" % (value) - logger.error(error) - raise ValueError(error) - if boundary_type == 'us_states': self.masked_regions = shapefile_boundary(boundary_type, us_states) if boundary_type == 'countries': @@ -331,91 +306,62 @@ class Bounds(object): mask_longitude = file_object.variables[longitude_name][:] mask_latitude = file_object.variables[latitude_name][:] if mask_longitude.ndim == 1 and mask_latitude.ndim == 1: - self.mask_longitude, self.mask_latitude = np.meshgrid(mask_longitude, mask_latitude) + self.mask_longitude, self.mask_latitude = numpy.meshgrid(mask_longitude, mask_latitude) elif mask_longitude.ndim == 2 and mask_latitude.ndim == 2: self.mask_longitude = mask_longitude self.mask_latitude = mask_latitude - if boundary_type == 'rectangular' or boundary_type[:6].upper() == 'CORDEX': - if boundary_type == 'rectangular': - self._lat_min = float(lat_min) - self._lat_max = float(lat_max) - self._lon_min = float(lon_min) - self._lon_max = float(lon_max) - if boundary_type[:6].upper() == 'CORDEX': - self._lat_min, self._lat_max, self._lon_min, self._lon_max = CORDEX_boundary(boundary_type[6:].replace(" ","").lower()) - - - @property - def lat_min(self): - return self._lat_min - - @lat_min.setter - def lat_min(self, value): - if not (-90 <= value <= 90 and value < self._lat_max): - error = "Attempted to set lat_min to invalid value: %s" % (value) - logger.error(error) - raise ValueError(error) - - self._lat_min = value - - @property - def lat_max(self): - return self._lat_max - - @lat_max.setter - def lat_max(self, value): - if not (-90 <= value <= 90 and value > self._lat_min): - error = "Attempted to set lat_max to invalid value: %s" % (value) - logger.error(error) - raise ValueError(error) - - self._lat_max = value - - @property - def lon_min(self): - return self._lon_min - - @lon_min.setter - def lon_min(self, value): - if not (-180 <= value <= 180 and value < self._lon_max): - error = "Attempted to set lon_min to invalid value: %s" % (value) - logger.error(error) - raise ValueError(error) - - self._lon_min = value - - @property - def lon_max(self): - return self._lon_max - - @lon_max.setter - def lon_max(self, value): - if not (-180 <= value <= 180 and value > self._lon_min): - error = "Attempter to set lon_max to invalid value: %s" % (value) - logger.error(error) - raise ValueError(error) - - self._lon_max = value - - - def __str__(self): - lat_range = "({}, {})".format(self._lat_min, self._lat_max) - lon_range = "({}, {})".format(self._lon_min, self._lon_max) - temporal_boundaries = "({}, {})".format(self._start, self._end) - - formatted_repr = ( - "<Bounds - " - "lat-range: {}, " - "lon-range: {}, " - "temporal_boundaries: {}> " - ) - - return formatted_repr.format( - lat_range, - lon_range, - temporal_boundaries, - ) - + if boundary_type == 'rectangular': + if not (-90 <= float(lat_min) <=90) or float(lat_min) > float(lat_max): + error = "Attempted to set lat_min to invalid value: %s" % (lat_min) + logger.error(error) + raise ValueError(error) + if not (-90 <= float(lat_max) <=90): + error = "Attempted to set lat_max to invalid value: %s" % (lat_max) + logger.error(error) + raise ValueError(error) + if not (-180 <= float(lon_min) <=180) or float(lon_min) > float(lon_max): + error = "Attempted to set lon_min to invalid value: %s" % (lon_min) + logger.error(error) + raise ValueError(error) + if not (-180 <= float(lon_max) <=180): + error = "Attempted to set lat_max to invalid value: %s" % (lon_max) + logger.error(error) + raise ValueError(error) + + self.lat_min = float(lat_min) + self.lat_max = float(lat_max) + self.lon_min = float(lon_min) + self.lon_max = float(lon_max) + if boundary_type[:6].upper() == 'CORDEX': + self.lat_min, self.lat_max, self.lon_min, self.lon_max = CORDEX_boundary(boundary_type[6:].replace(" ","").lower()) + + @property + def start(self): + return self._start + + @start.setter + def start(self, value): + if self._end: + if not (type(value) is dt.datetime and value < self._end): + error = "Attempted to set start to invalid value: %s" % (value) + logger.error(error) + raise ValueError(error) + + self._start = value + + @property + def end(self): + return self._end + + @end.setter + def end(self, value): + if self._start: + if not (type(value) is dt.datetime and value > self._start): + error = "Attempted to set end to invalid value: %s" % (value) + logger.error(error) + raise ValueError(error) + + self._end = value def shapefile_boundary(boundary_type, region_names): ''' @@ -426,22 +372,22 @@ def shapefile_boundary(boundary_type, region_names): :type region_names: :mod:'list' ''' - map_read = Basemap + map_read = Basemap() regions =[] if boundary_type == 'us_states': - #map_read.readshapefile(ocw.__path__[0]+'/shape/usa_states','usa_states') - map_read.readshapefile('/home/huikyole/climate/ocw'+'/shape/usa_states','usa_states') + map_read.readshapefile(ocw.__path__[0]+'/shape/usa_states','usa_states') + #map_read.readshapefile('/home/huikyole/climate/ocw'+'/shape/usa_states','usa_states') for region_name in region_names: for iregion, region_info in enumerate(map_read.usa_states_info): if region_info['st'] == region_name: - regions.append(np.array(map_read.usa_states[iregion])) + regions.append(numpy.array(map_read.usa_states[iregion])) if boundary_type == 'countries': - #map_read.readshapefile(ocw.__path__[0]+'/shape/countries','countries') - map_read.readshapefile('/home/huikyole/climate/ocw'+'/shape/countries','countries') + map_read.readshapefile(ocw.__path__[0]+'/shape/countries','countries') + #map_read.readshapefile('/home/huikyole/climate/ocw'+'/shape/countries','countries') for region_name in region_names: for iregion, region_info in enumerate(map_read.countries_info): if region_info['COUNTRY'] == region_name: - regions.append(np.array(map_read.countries[iregion])) + regions.append(numpy.array(map_read.countries[iregion])) return regions def CORDEX_boundary(domain_name): http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/ocw/dataset_processor.py ---------------------------------------------------------------------- diff --git a/ocw/dataset_processor.py b/ocw/dataset_processor.py index 2b5dc9b..8b817a2 100755 --- a/ocw/dataset_processor.py +++ b/ocw/dataset_processor.py @@ -383,57 +383,58 @@ def subset(target_dataset, subregion, subregion_name=None): if not subregion.start: subregion.start = target_dataset.times[0] subregion.end = target_dataset.times[-1] - - # Ensure that the subregion information is well formed - _are_bounds_contained_by_dataset(target_dataset, subregion) - + if not subregion_name: subregion_name = target_dataset.name - if target_dataset.lats.ndim == 2 and target_dataset.lons.ndim == 2: - start_time_index = np.where( - target_dataset.times == subregion.start)[0][0] - end_time_index = np.where(target_dataset.times == subregion.end)[0][0] - target_dataset = temporal_slice( - target_dataset, start_time_index, end_time_index) - nt, ny, nx = target_dataset.values.shape - y_index, x_index = np.where( - (target_dataset.lats >= subregion.lat_max) | ( - target_dataset.lats <= subregion.lat_min) | - (target_dataset.lons >= subregion.lon_max) | ( - target_dataset.lons <= subregion.lon_min)) - for it in np.arange(nt): - target_dataset.values[it, y_index, x_index] = 1.e+20 - target_dataset.values = ma.masked_equal(target_dataset.values, 1.e+20) - return target_dataset - - elif target_dataset.lats.ndim == 1 and target_dataset.lons.ndim == 1: - # Get subregion indices into subregion data - dataset_slices = _get_subregion_slice_indices(target_dataset, - subregion) - # Slice the values array with our calculated slice indices - if target_dataset.values.ndim == 2: - subset_values = ma.zeros([len(target_dataset.values[ - dataset_slices["lat_start"]:dataset_slices["lat_end"]]), - len(target_dataset.values[ - dataset_slices["lon_start"]:dataset_slices["lon_end"]])]) - - subset_values = target_dataset.values[ - dataset_slices["lat_start"]:dataset_slices["lat_end"] + 1, - dataset_slices["lon_start"]:dataset_slices["lon_end"] + 1] - - elif target_dataset.values.ndim == 3: - subset_values = ma.zeros([len(target_dataset.values[ - dataset_slices["time_start"]:dataset_slices["time_end"]]), - len(target_dataset.values[ + if subregion.lat_min: + # If boundary_type is 'rectangular' or 'CORDEX ***', ensure that the subregion information is well formed + _are_bounds_contained_by_dataset(target_dataset, subregion) + + if target_dataset.lats.ndim == 2 and target_dataset.lons.ndim == 2: + start_time_index = np.where( + target_dataset.times == subregion.start)[0][0] + end_time_index = np.where(target_dataset.times == subregion.end)[0][0] + target_dataset = temporal_slice( + target_dataset, start_time_index, end_time_index) + nt, ny, nx = target_dataset.values.shape + y_index, x_index = np.where( + (target_dataset.lats >= subregion.lat_max) | ( + target_dataset.lats <= subregion.lat_min) | + (target_dataset.lons >= subregion.lon_max) | ( + target_dataset.lons <= subregion.lon_min)) + for it in np.arange(nt): + target_dataset.values[it, y_index, x_index] = 1.e+20 + target_dataset.values = ma.masked_equal(target_dataset.values, 1.e+20) + return target_dataset + + elif target_dataset.lats.ndim == 1 and target_dataset.lons.ndim == 1: + # Get subregion indices into subregion data + dataset_slices = _get_subregion_slice_indices(target_dataset, + subregion) + # Slice the values array with our calculated slice indices + if target_dataset.values.ndim == 2: + subset_values = ma.zeros([len(target_dataset.values[ dataset_slices["lat_start"]:dataset_slices["lat_end"]]), - len(target_dataset.values[ - dataset_slices["lon_start"]:dataset_slices["lon_end"]])]) - - subset_values = target_dataset.values[ - dataset_slices["time_start"]:dataset_slices["time_end"] + 1, - dataset_slices["lat_start"]:dataset_slices["lat_end"] + 1, - dataset_slices["lon_start"]:dataset_slices["lon_end"] + 1] + len(target_dataset.values[ + dataset_slices["lon_start"]:dataset_slices["lon_end"]])]) + + subset_values = target_dataset.values[ + dataset_slices["lat_start"]:dataset_slices["lat_end"] + 1, + dataset_slices["lon_start"]:dataset_slices["lon_end"] + 1] + + elif target_dataset.values.ndim == 3: + subset_values = ma.zeros([len(target_dataset.values[ + dataset_slices["time_start"]:dataset_slices["time_end"]]), + len(target_dataset.values[ + dataset_slices["lat_start"]:dataset_slices["lat_end"]]), + len(target_dataset.values[ + dataset_slices["lon_start"]:dataset_slices["lon_end"]])]) + + subset_values = target_dataset.values[ + dataset_slices["time_start"]:dataset_slices["time_end"] + 1, + dataset_slices["lat_start"]:dataset_slices["lat_end"] + 1, + dataset_slices["lon_start"]:dataset_slices["lon_end"] + 1] # Build new dataset with subset information return ds.Dataset( @@ -505,18 +506,18 @@ def safe_subset(target_dataset, subregion, subregion_name=None): lat_min, lat_max, lon_min, lon_max = target_dataset.spatial_boundaries() start, end = target_dataset.temporal_boundaries() + if subregion.lat_min: + if subregion.lat_min < lat_min: + subregion.lat_min = lat_min - if subregion.lat_min < lat_min: - subregion.lat_min = lat_min - - if subregion.lat_max > lat_max: - subregion.lat_max = lat_max + if subregion.lat_max > lat_max: + subregion.lat_max = lat_max - if subregion.lon_min < lon_min: - subregion.lon_min = lon_min + if subregion.lon_min < lon_min: + subregion.lon_min = lon_min - if subregion.lon_max > lon_max: - subregion.lon_max = lon_max + if subregion.lon_max > lon_max: + subregion.lon_max = lon_max if subregion.start: if subregion.start < start: http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/ocw/tests/test_dataset.py ---------------------------------------------------------------------- diff --git a/ocw/tests/test_dataset.py b/ocw/tests/test_dataset.py index 8b666c1..9d77400 100644 --- a/ocw/tests/test_dataset.py +++ b/ocw/tests/test_dataset.py @@ -214,120 +214,58 @@ class TestDatasetFunctions(unittest.TestCase): class TestBounds(unittest.TestCase): def setUp(self): - self.bounds = Bounds(-80, 80, # Lats - -160, 160, # Lons - dt.datetime(2000, 1, 1), # Start time - dt.datetime(2002, 1, 1)) # End time - self.another_bounds = Bounds(-80, 80, # Lats - -160, 160) - - def test_setter_methods(self): - self.bounds.lat_min = -10 - self.bounds.lat_max = 10 - self.bounds.lon_min = -120 - self.bounds.lon_max = 120 - self.bounds.start = dt.datetime(2000, 1, 2) - self.bounds.end = dt.datetime(2002, 1, 4) - - self.assertEqual(self.bounds.lat_min, -10) - self.assertEqual(self.bounds.lat_max, 10) - self.assertEqual(self.bounds.lon_min, -120) - self.assertEqual(self.bounds.lon_max, 120) - self.assertEqual(self.bounds.start, dt.datetime(2000, 1, 2)) - self.assertEqual(self.bounds.end, dt.datetime(2002, 1, 4)) - - # Latitude tests - def test_inverted_min_max_lat(self): - with self.assertRaises(ValueError): - self.bounds.lat_min = 81 - - with self.assertRaises(ValueError): - self.bounds.lat_max = -81 - - # Lat Min - def test_out_of_bounds_lat_min(self): - with self.assertRaises(ValueError): - self.bounds.lat_min = -91 - - with self.assertRaises(ValueError): - self.bounds.lat_min = 91 - - # Lat Max - def test_out_of_bounds_lat_max(self): - with self.assertRaises(ValueError): - self.bounds.lat_max = -91 - - with self.assertRaises(ValueError): - self.bounds.lat_max = 91 - - # Longitude tests - def test_inverted_max_max_lon(self): - with self.assertRaises(ValueError): - self.bounds.lon_min = 161 - - with self.assertRaises(ValueError): - self.bounds.lon_max = -161 - - # Lon Min - def test_out_of_bounds_lon_min(self): - with self.assertRaises(ValueError): - self.bounds.lon_min = -181 - - with self.assertRaises(ValueError): - self.bounds.lon_min = 181 - - # Lon Max - def test_out_of_bounds_lon_max(self): - with self.assertRaises(ValueError): - self.bounds.lon_max = -181 - - with self.assertRaises(ValueError): - self.bounds.lon_max = 181 + self.bounds_rectangular = Bounds(lat_min=-80, lat_max=80, # Lats + lon_min=-160, lon_max=160, # Lons + start=dt.datetime(2000, 1, 1), # Start time + end=dt.datetime(2002, 1, 1)) # End time + self.bounds_CORDEX = Bounds(boundary_type='CORDEX South Asia') + self.bounds_us_states = Bounds(boundary_type='us_states', us_states=['CA','NV','AZ']) + self.bounds_countries = Bounds(boundary_type='countries', countries=['United States','Canada','Mexico']) + + def test_keywords(self): + self.assertEqual(self.bounds_rectangular.boundary_type, 'rectangular') + self.assertEqual(self.bounds_rectangular.lat_min, -80) + self.assertEqual(self.bounds_rectangular.lat_max, 80) + self.assertEqual(self.bounds_rectangular.lon_min, -160) + self.assertEqual(self.bounds_rectangular.lon_max, 160) + self.assertEqual(self.bounds_rectangular.start, dt.datetime(2000,1,1)) + self.assertEqual(self.bounds_rectangular.end, dt.datetime(2002,1,1)) + + self.assertEqual(self.bounds_CORDEX.boundary_type, 'CORDEX South Asia') + self.assertEqual(self.bounds_CORDEX.lat_min, -15.23) + self.assertEqual(self.bounds_CORDEX.lat_max, 45.07) + self.assertEqual(self.bounds_CORDEX.lon_min, 19.88) + self.assertEqual(self.bounds_CORDEX.lon_max, 115.55) + + self.assertEqual(self.bounds_us_states.boundary_type, 'us_states') + + self.assertEqual(self.bounds_countries.boundary_type, 'countries') # Temporal tests def test_inverted_start_end_times(self): with self.assertRaises(ValueError): - self.bounds.start = dt.datetime(2003, 1, 1) + self.bounds_rectangular.start = dt.datetime(2003, 1, 1) with self.assertRaises(ValueError): - self.bounds.end = dt.datetime(1999, 1, 1) + self.bounds_rectangular.end = dt.datetime(1999, 1, 1) # Start tests def test_invalid_start(self): with self.assertRaises(ValueError): - self.bounds.start = "This is not a date time object" + self.bounds_rectangular.start = "This is not a date time object" # End tests def test_invalid_end(self): with self.assertRaises(ValueError): - self.bounds.end = "This is not a date time object" + self.bounds_rectangular.end = "This is not a date time object" # Start tests def test_none_value_start(self): - self.assertEqual(self.another_bounds.start, None) + self.assertEqual(self.bounds_CORDEX.start, None) # End tests def test_none_value_end(self): - self.assertEqual(self.another_bounds.end, None) - - def test__str__(self): - lat_range = "({}, {})".format(self.bounds.lat_min, self.bounds.lat_max) - lon_range = "({}, {})".format(self.bounds.lon_min, self.bounds.lon_max) - temporal_boundaries = "({}, {})".format(self.bounds.start, self.bounds.end) - - formatted_repr = ( - "<Bounds - " - "lat-range: {}, " - "lon-range: {}, " - "temporal_boundaries: {}> " - ) - - output = formatted_repr.format( - lat_range, - lon_range, - temporal_boundaries, - ) - self.assertEqual(str(self.bounds), output) + self.assertEqual(self.bounds_CORDEX.end, None) if __name__ == '__main__': unittest.main() http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/ocw/tests/test_dataset_processor.py ---------------------------------------------------------------------- diff --git a/ocw/tests/test_dataset_processor.py b/ocw/tests/test_dataset_processor.py index 627955a..0f8131e 100644 --- a/ocw/tests/test_dataset_processor.py +++ b/ocw/tests/test_dataset_processor.py @@ -431,22 +431,22 @@ class TestSubset(unittest.TestCase): self.name = 'foo' self.subregion = ds.Bounds( - -81, 81, - -161, 161, - datetime.datetime(2001, 1, 1), - datetime.datetime(2004, 1, 1) + lat_min=-81, lat_max=81, + lon_min=-161, lon_max=161, + start=datetime.datetime(2001, 1, 1), + end=datetime.datetime(2004, 1, 1) ) self.non_exact_spatial_subregion = ds.Bounds( - -80.25, 80.5, - -160.25, 160.5, - datetime.datetime(2001, 1, 1), - datetime.datetime(2004, 1, 1) + lat_min=-80.25, lat_max=80.5, + lon_min=-160.25, lon_max=160.5, + start=datetime.datetime(2001, 1, 1), + end=datetime.datetime(2004, 1, 1) ) self.non_exact_temporal_subregion = ds.Bounds( - -80.25, 80.5, - -160.25, 160.5, - datetime.datetime(2001, 1, 15), - datetime.datetime(2004, 2, 15) + lat_min=-80.25, lat_max=80.5, + lon_min=-160.25, lon_max=160.5, + start=datetime.datetime(2001, 1, 15), + end=datetime.datetime(2004, 2, 15) ) def test_subset(self): @@ -491,8 +491,8 @@ class TestSubset(unittest.TestCase): def test_subset_without_start_index(self): self.subregion = ds.Bounds( - -81, 81, - -161, 161, + lat_min=-81, lat_max=81, + lon_min=-161, lon_max=161, ) subset = dp.subset(self.target_dataset, self.subregion) times = np.array([datetime.datetime(year, month, 1) @@ -524,24 +524,24 @@ class TestSafeSubset(unittest.TestCase): name='foo') self.spatial_out_of_bounds = ds.Bounds( - -165, 165, - -180, 180, - datetime.datetime(2001, 1, 1), - datetime.datetime(2004, 1, 1) + lat_min=-65, lat_max=65, + lon_min=-180, lon_max=180, + start=datetime.datetime(2001, 1, 1), + end=datetime.datetime(2004, 1, 1) ) self.temporal_out_of_bounds = ds.Bounds( - -40, 40, - -160.25, 160.5, - datetime.datetime(1999, 1, 15), - datetime.datetime(2222, 2, 15) + lat_min=-40, lat_max=40, + lon_min=-160.25, lon_max=160.5, + start=datetime.datetime(1999, 1, 15), + end=datetime.datetime(2222, 2, 15) ) self.everything_out_of_bounds = ds.Bounds( - -165, 165, - -180, 180, - datetime.datetime(1999, 1, 15), - datetime.datetime(2222, 2, 15) + lat_min=-65, lat_max=65, + lon_min=-180, lon_max=180, + start=datetime.datetime(1999, 1, 15), + end=datetime.datetime(2222, 2, 15) ) def test_partial_spatial_overlap(self): @@ -556,7 +556,7 @@ class TestSafeSubset(unittest.TestCase): def test_partial_temporal_overlap(self): '''Ensure that safe_subset can handle out of bounds temporal values''' ds = dp.safe_subset(self.target_dataset, self.temporal_out_of_bounds) - temporal_bounds = ds.time_range() + temporal_bounds = ds.temporal_boundaries() start = datetime.datetime(2000, 1, 1) end = datetime.datetime(2009, 12, 1) @@ -585,10 +585,10 @@ class TestFailingSubset(unittest.TestCase): self.target_dataset.lons = np.array(range(-179, 178, 2)) self.subregion = ds.Bounds( - -81, 81, - -161, 161, - datetime.datetime(2001, 1, 1), - datetime.datetime(2004, 1, 1) + lat_min=-81, lat_max=81, + lon_min=-161, lon_max=161, + start=datetime.datetime(2001, 1, 1), + end=datetime.datetime(2004, 1, 1) ) def test_out_of_dataset_bounds_lat_min(self): http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/ocw/tests/test_evaluation.py ---------------------------------------------------------------------- diff --git a/ocw/tests/test_evaluation.py b/ocw/tests/test_evaluation.py index e348fd9..9053e52 100644 --- a/ocw/tests/test_evaluation.py +++ b/ocw/tests/test_evaluation.py @@ -98,9 +98,9 @@ class TestEvaluation(unittest.TestCase): def test_valid_subregion(self): bound = Bounds( - -10, 10, - -20, 20, - dt.datetime(2000, 1, 1), dt.datetime(2001, 1, 1)) + lat_min=-10, lat_max=10, + lon_min=-20, lon_max=20, + start=dt.datetime(2000, 1, 1), end=dt.datetime(2001, 1, 1)) self.eval.subregions = [bound, bound] self.assertEquals(len(self.eval.subregions), 2) @@ -198,9 +198,9 @@ class TestEvaluation(unittest.TestCase): def test_subregion_result_shape(self): bound = Bounds( - 10, 18, - 100, 108, - dt.datetime(2000, 1, 1), dt.datetime(2000, 3, 1)) + lat_min=10, lat_max=18, + lon_min=100, lon_max=108, + start=dt.datetime(2000, 1, 1), end=dt.datetime(2000, 3, 1)) bias_eval = Evaluation( self.test_dataset, @@ -223,9 +223,9 @@ class TestEvaluation(unittest.TestCase): def test_subregion_unary_result_shape(self): bound = Bounds( - 10, 18, - 100, 108, - dt.datetime(2000, 1, 1), dt.datetime(2000, 3, 1)) + lat_min=10, lat_max=18, + lon_min=100, lon_max=108, + start=dt.datetime(2000, 1, 1), end=dt.datetime(2000, 3, 1)) new_eval = Evaluation( self.test_dataset, http://git-wip-us.apache.org/repos/asf/climate/blob/02dfdec6/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 ed22417..ceaa2b1 100644 --- a/ocw_config_runner/tests/test_config_writer.py +++ b/ocw_config_runner/tests/test_config_writer.py @@ -652,8 +652,8 @@ class FullExportTest(unittest.TestCase): ) self.subregions = [ - Bounds(-10, 10, -20, 20), - Bounds(-5, 5, -15, 15) + Bounds(lat_min=-10, lat_max=10, lon_min=-20, lon_max=20), + Bounds(lat_min=-5, lat_max=5, lon_min=-15, lon_max=15) ] self.evaluation = Evaluation(
