def test_get_between_use_bounds(self): value = [3., 5.] bounds = [[2., 4.], [4., 6.]] vdim = VectorDimension(value=value, bounds=bounds) ret = vdim.get_between(3, 4.5, use_bounds=False) self.assertNumpyAll(ret.value, np.array([3.])) self.assertNumpyAll(ret.bounds, np.array([[2., 4.]]))
def test_value(self): vdim = VectorDimension(value=[4, 5, 6]) self.assertIsInstance(vdim.value, np.ndarray) # Test passing a single value. values = [5, np.array([5])] for value in values: vdim = VectorDimension(value=value, src_idx=10) self.assertEqual(vdim.value[0], 5) self.assertEqual(vdim.uid[0], 1) self.assertEqual(len(vdim.uid), 1) self.assertEqual(vdim.shape, (1,)) self.assertIsNone(vdim.bounds) self.assertEqual(vdim[0].value[0], 5) self.assertEqual(vdim[0].uid[0], 1) self.assertEqual(vdim[0]._src_idx[0], 10) self.assertIsNone(vdim[0].bounds) with self.assertRaises(ResolutionError): vdim.resolution # Test conforming units. for seb in [True, False]: if seb: v = VectorDimension(value=[4, 5, 6], units='celsius', conform_units_to='kelvin') v.set_extrapolated_bounds() else: v = VectorDimension(value=[4, 5, 6], bounds=[[3.5, 4.5], [4.5, 5.5], [5.5, 6.5]], units='celsius', conform_units_to='kelvin') self.assertGreater(v.value.mean(), 200) self.assertGreater(v.bounds.mean(), 200) # Test with a request dataset, conforming units, and no initial value. v = VectorDimension(conform_units_to='kelvin', units='celsius', request_dataset='foo') self.assertIsNone(v._value)
def test_write_netcdf_unlimited_to_fixedsize(self): v = VectorDimension(value=[1, 2, 3], name='foo', unlimited=True) path = self.get_temporary_file_path('foobar.nc') with self.nc_scope(path, 'w') as ds: v.write_netcdf(ds, unlimited_to_fixedsize=True) with self.nc_scope(path) as ds: d = ds.dimensions['foo'] self.assertFalse(d.isunlimited())
def test_get_between(self): vdim = VectorDimension(value=[0]) with self.assertRaises(EmptySubsetError): vdim.get_between(100,200) vdim = VectorDimension(value=[100,200,300,400]) vdim_between = vdim.get_between(100,200) self.assertEqual(len(vdim_between),2)
def test_get_between_bounds(self): vdim = VectorDimension(value=[0.,5.,10.],bounds=[[-2.5,2.5],[2.5,7.5],[7.5,12.5]]) vdim_between = vdim.get_between(1,3) self.assertEqual(len(vdim_between),2) self.assertEqual(vdim.resolution,5.0) vdim_between = vdim.get_between(2.5,2.5) self.assertEqual(len(vdim_between),2)
def test_interpolate_bounds(self): value = [10, 20, 30, 40, 50] vdim = VectorDimension(value=value) self.assertEqual(vdim.bounds, None) vdim = VectorDimension(value=value) vdim.set_extrapolated_bounds() self.assertEqual(vdim.bounds.tostring(), '\x05\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00\x00\x00\x00\x007\x00\x00\x00\x00\x00\x00\x00')
def test_write_netcdf_bounds_dimension_exists(self): """Test writing with bounds when the bounds dimension has already been created.""" vd = VectorDimension(value=[3., 7.], name='one') vd.set_extrapolated_bounds() vd2 = VectorDimension(value=[5., 6.], name='two') vd2.set_extrapolated_bounds() path = os.path.join(self.current_dir_output, 'foo.nc') with nc_scope(path, 'w') as ds: vd.write_netcdf(ds) vd2.write_netcdf(ds) self.assertEqual(ds.variables.keys(), ['one', 'one_bounds', 'two', 'two_bounds'])
def test_set_reference(self): vdim = VectorDimension(value=[4,5,6]) vdim_slc = vdim[1] self.assertEqual(vdim_slc.uid[0],2) vdim_slc2 = vdim[:] self.assertNumpyAll(vdim_slc2.value,vdim.value) vdim._value[1] = 500 self.assertNumpyAll(vdim.value,[4,500,6]) with self.assertRaises(TypeError): vdim.bounds[1,:] self.assertNumpyAll(vdim.value,vdim_slc2.value) vdim_slc2._value[2] = 1000 self.assertNumpyAll(vdim.value,vdim_slc2.value)
def create_data(): col = np.linspace(-104., -100., 100) row = np.linspace(32, 36, 100) col = VectorDimension(value=col, name='longitude', name_bounds='longitude_bounds', attrs={'standard_name': 'longitude', 'units': 'degrees_east'}) col.set_extrapolated_bounds() row = VectorDimension(value=row, name='latitude', name_bounds='latitude_bounds', attrs={'standard_name': 'latitude', 'units': 'degrees_north'}) row.set_extrapolated_bounds() grid = ocgis.SpatialGridDimension(row=row, col=col) sdim = ocgis.SpatialDimension(grid=grid) start = datetime.datetime(2000, 1, 1) stop = datetime.datetime(2000, 12, 31) days = 1 ret = [] delta = datetime.timedelta(days=days) check = start while check <= stop: ret.append(check) check += delta temporal = ocgis.TemporalDimension(value=ret, unlimited=True) var_value = np.ones((1, temporal.shape[0], 1, row.shape[0], col.shape[0]), dtype=float) variable = ocgis.Variable(value=var_value, name='pr') field = ocgis.Field(spatial=sdim, temporal=temporal, variables=variable) ds = nc.Dataset(PATH_FAKE_DATA, 'w', format='NETCDF3_CLASSIC') field.write_netcdf(ds) ds.close()
def test_set_reference(self): """Test setting values on the internal value array using indexing.""" vdim = VectorDimension(value=[4, 5, 6]) vdim_slc = vdim[1] self.assertEqual(vdim_slc.uid[0], 2) vdim_slc2 = vdim[:] self.assertNumpyAll(vdim_slc2.value, vdim.value) vdim._value[1] = 500 self.assertNumpyAll(vdim.value, np.array([4, 500, 6])) with self.assertRaises(TypeError): vdim.bounds[1, :] self.assertNumpyAll(vdim.value, vdim_slc2.value) vdim_slc2._value[2] = 1000 self.assertNumpyAll(vdim.value, vdim_slc2.value)
def test_get_report(self): keywords = dict(value=[[10, 20, 30, 40, 50]], name=['vdim_test', None], use_bounds=[True, False]) for k in self.iter_product_keywords(keywords): kwds = k._asdict() use_bounds = kwds.pop('use_bounds') vdim = VectorDimension(**kwds) if use_bounds: vdim.set_extrapolated_bounds() target = vdim.get_report() self.assertEqual(len(target), 4) if use_bounds: actual = 'True' else: actual = 'False' self.assertTrue(target[-2].endswith(actual))
def test_cfunits_conform(self): vdim = VectorDimension(value=[5., 10., 15.], units='celsius') vdim.set_extrapolated_bounds() vdim.cfunits_conform(get_units_object('kelvin')) self.assertNumpyAll(vdim.bounds, np.array([[275.65, 280.65], [280.65, 285.65], [285.65, 290.65]])) # Test conforming without bounds. vdim = VectorDimension(value=[5., 10., 15.], units='celsius') vdim.cfunits_conform('kelvin') self.assertNumpyAll(vdim.value, np.array([278.15, 283.15, 288.15]))
def get_spherical_global_grid(self, resolution=3.0, with_bounds=True, wrapped=False): # Column (longitude) coordinates. if wrapped: start = -180.0 + (0.5 * resolution) stop = 180.0 + (0.5 * resolution) else: start = 0.5 * resolution stop = 360.0 + (0.5 * resolution) col = np.arange(start, stop, resolution) # Row (latitude) coordinates. start = -90.0 + (0.5 * resolution) stop = 90.0 + (0.5 * resolution) row = np.arange(start, stop, resolution) # The origin should be the upper left. row = np.flipud(row) col = VectorDimension(name="col", value=col) row = VectorDimension(name="row", value=row) if with_bounds: col.set_extrapolated_bounds() row.set_extrapolated_bounds() grid = SpatialGridDimension(row=row, col=col) return grid
def get_field(self, nlevel=None, nrlz=None, crs=None, ntime=2, with_bounds=False): """ :param int nlevel: The number of level elements. :param int nrlz: The number of realization elements. :param crs: The coordinate system for the field. :type crs: :class:`ocgis.interface.base.crs.CoordinateReferenceSystem` :param ntime: The number of time elements. :type ntime: int :param with_bounds: If ``True``, extrapolate bounds on spatial dimensions. :type with_bounds: bool :returns: A small field object for testing. :rtype: `~ocgis.Field` """ np.random.seed(1) row = VectorDimension(value=[4.0, 5.0], name="row") col = VectorDimension(value=[40.0, 50.0], name="col") if with_bounds: row.set_extrapolated_bounds() col.set_extrapolated_bounds() grid = SpatialGridDimension(row=row, col=col) sdim = SpatialDimension(grid=grid, crs=crs) if ntime == 2: value_temporal = [datetime.datetime(2000, 1, 1), datetime.datetime(2000, 2, 1)] else: value_temporal = [] start = datetime.datetime(2000, 1, 1) delta = datetime.timedelta(days=1) ctr = 0 while ctr < ntime: value_temporal.append(start) start += delta ctr += 1 temporal = TemporalDimension(value=value_temporal) if nlevel is None: nlevel = 1 level = None else: level = VectorDimension(value=range(1, nlevel + 1), name="level") if nrlz is None: nrlz = 1 realization = None else: realization = VectorDimension(value=range(1, nrlz + 1), name="realization") variable = Variable(name="foo", value=np.random.rand(nrlz, ntime, nlevel, 2, 2)) field = Field(spatial=sdim, temporal=temporal, variables=variable, level=level, realization=realization) return field
def test_get_iter(self): vdim = VectorDimension(value=[10,20,30,40,50]) with self.assertRaises(ValueError): list(vdim.get_iter()) vdim = VectorDimension(value=[10,20,30,40,50],name='foo') tt = list(vdim.get_iter()) self.assertEqual(tt[3],(3, {'foo_uid': 4, 'foo': 40, 'foo_bnds_lower': None, 'foo_bnds_upper': None})) vdim = VectorDimension(value=[10,20,30,40,50],bounds=[(ii-5,ii+5) for ii in [10,20,30,40,50]],name='foo',name_uid='hi') tt = list(vdim.get_iter()) self.assertEqual(tt[3],(3, {'hi': 4, 'foo': 40, 'foo_bnds_lower': 35, 'foo_bnds_upper': 45}))
def test_get_iter(self): vdim = VectorDimension(value=[10, 20, 30, 40, 50]) with self.assertRaises(ValueError): list(vdim.get_iter()) vdim = VectorDimension(value=[10, 20, 30, 40, 50], name='foo') tt = list(vdim.get_iter()) self.assertEqual(tt[3], (3, {'foo_uid': 4, 'foo': 40, 'lb_foo': None, 'ub_foo': None})) self.assertIsInstance(tt[0][1], OrderedDict) vdim = VectorDimension(value=[10, 20, 30, 40, 50], bounds=[(ii - 5, ii + 5) for ii in [10, 20, 30, 40, 50]], name='foo', name_uid='hi') tt = list(vdim.get_iter()) self.assertEqual(tt[3], (3, {'hi': 4, 'foo': 40, 'lb_foo': 35, 'ub_foo': 45})) vdim = VectorDimension(value=[4, 5, 6, 7, 8, 9, 10], name='new') for slc, row in vdim.get_iter(with_bounds=False): for k in row.iterkeys(): self.assertFalse(OCGIS_BOUNDS in k)
def test_set_extrapolated_bounds(self): value = np.array([1, 2, 3, 4], dtype=float) vd = VectorDimension(value=value) self.assertIsNone(vd.bounds) vd.set_extrapolated_bounds() actual = np.array([[0.5, 1.5], [1.5, 2.5], [2.5, 3.5], [3.5, 4.5]], dtype=float) self.assertNumpyAll(vd.bounds, actual) # attempt to extrapolate when the bound are already present value = np.array([1.5]) bounds = np.array([[1.0, 2.0]]) vd = VectorDimension(value=value, bounds=bounds) with self.assertRaises(BoundsAlreadyAvailableError): vd.set_extrapolated_bounds()
def test_get_between_bounds(self): value = [0., 5., 10.] bounds = [[-2.5, 2.5], [2.5, 7.5], [7.5, 12.5]] # # a reversed copy of these bounds are created here value_reverse = deepcopy(value) value_reverse.reverse() bounds_reverse = deepcopy(bounds) bounds_reverse.reverse() for ii in range(len(bounds)): bounds_reverse[ii].reverse() data = {'original': {'value': value, 'bounds': bounds}, 'reversed': {'value': value_reverse, 'bounds': bounds_reverse}} for key in ['original', 'reversed']: vdim = VectorDimension(value=data[key]['value'], bounds=data[key]['bounds']) vdim_between = vdim.get_between(1, 3) self.assertEqual(len(vdim_between), 2) if key == 'original': self.assertEqual(vdim_between.bounds.tostring(), '\x00\x00\x00\x00\x00\x00\x04\xc0\x00\x00\x00\x00\x00\x00\x04@\x00\x00\x00\x00\x00\x00\x04@\x00\x00\x00\x00\x00\x00\x1e@') else: self.assertEqual(vdim_between.bounds.tostring(), '\x00\x00\x00\x00\x00\x00\x1e@\x00\x00\x00\x00\x00\x00\x04@\x00\x00\x00\x00\x00\x00\x04@\x00\x00\x00\x00\x00\x00\x04\xc0') self.assertEqual(vdim.resolution, 5.0) ## preference is given to the lower bound in the case of "ties" where ## the value could be assumed part of the lower or upper cell vdim_between = vdim.get_between(2.5, 2.5) self.assertEqual(len(vdim_between), 1) if key == 'original': self.assertNumpyAll(vdim_between.bounds, np.array([[2.5, 7.5]])) else: self.assertNumpyAll(vdim_between.bounds, np.array([[7.5, 2.5]])) ## if the interval is closed and the subset range falls only on bounds ## value then the subset will be empty with self.assertRaises(EmptySubsetError): vdim.get_between(2.5, 2.5, closed=True) vdim_between = vdim.get_between(2.5, 7.5) if key == 'original': self.assertEqual(vdim_between.bounds.tostring(), '\x00\x00\x00\x00\x00\x00\x04@\x00\x00\x00\x00\x00\x00\x1e@\x00\x00\x00\x00\x00\x00\x1e@\x00\x00\x00\x00\x00\x00)@') else: self.assertEqual(vdim_between.bounds.tostring(), '\x00\x00\x00\x00\x00\x00)@\x00\x00\x00\x00\x00\x00\x1e@\x00\x00\x00\x00\x00\x00\x1e@\x00\x00\x00\x00\x00\x00\x04@')
def test_with_units(self): vdim = VectorDimension(value=[5, 10, 15], units='celsius') self.assertEqual(vdim.cfunits, Units('celsius')) vdim.cfunits_conform(Units('kelvin')) self.assertNumpyAll(vdim.value, np.array([278.15, 283.15, 288.15]))
def test_get_wrapped_state(self): refv = WrappableCoordinateReferenceSystem refm = refv.get_wrapped_state ## test grid ## row = VectorDimension(value=[50, 60]) col = VectorDimension(value=[0, 90, 180]) grid = SpatialGridDimension(row=row, col=col) sdim = SpatialDimension(grid=grid) self.assertEqual(refm(sdim), refv._flag_unknown) col = VectorDimension(value=[-170, 0, 30]) grid = SpatialGridDimension(row=row, col=col) sdim = SpatialDimension(grid=grid) self.assertEqual(refm(sdim), refv._flag_wrapped) col = VectorDimension(value=[0, 90, 180, 270]) grid = SpatialGridDimension(row=row, col=col) sdim = SpatialDimension(grid=grid) self.assertEqual(refm(sdim), refv._flag_unwrapped) ## test geom ## for with_polygon in [True, False]: row = VectorDimension(value=[50, 60]) col = VectorDimension(value=[155, 165, 175]) if with_polygon: row.set_extrapolated_bounds() col.set_extrapolated_bounds() grid = SpatialGridDimension(row=row, col=col) sdim = SpatialDimension(grid=grid) sdim.grid = None self.assertEqual(refm(sdim), refv._flag_unknown) row = VectorDimension(value=[50, 60]) col = VectorDimension(value=[160, 170, 180]) if with_polygon: row.set_extrapolated_bounds() col.set_extrapolated_bounds() grid = SpatialGridDimension(row=row, col=col) sdim = SpatialDimension(grid=grid) sdim.grid = None if with_polygon: actual = refv._flag_unwrapped else: actual = refv._flag_unknown self.assertEqual(refm(sdim), actual) row = VectorDimension(value=[50, 60]) col = VectorDimension(value=[-160, -150, -140]) if with_polygon: row.set_extrapolated_bounds() col.set_extrapolated_bounds() grid = SpatialGridDimension(row=row, col=col) sdim = SpatialDimension(grid=grid) sdim.grid = None self.assertEqual(refm(sdim), refv._flag_wrapped)
def test_get_ocgis_field_from_esmpy_field(self): np.random.seed(1) temporal = TemporalDimension(value=[3000.0, 4000.0, 5000.0]) level = VectorDimension(value=[10, 20, 30, 40]) realization = VectorDimension(value=[100, 200]) kwds = dict( crs=[None, CoordinateReferenceSystem(epsg=4326), Spherical()], with_mask=[False, True], with_corners=[False, True], dimensions=[False, True], drealization=[False, True], dtemporal=[False, True], dlevel=[False, True], ) for k in self.iter_product_keywords(kwds): row = VectorDimension(value=[1.0, 2.0]) col = VectorDimension(value=[3.0, 4.0]) if k.with_corners: row.set_extrapolated_bounds() col.set_extrapolated_bounds() value_tmin = np.random.rand(2, 3, 4, 2, 2) tmin = Variable(value=value_tmin, name="tmin") variables = VariableCollection([tmin]) grid = SpatialGridDimension(row=row, col=col) sdim = SpatialDimension(grid=grid, crs=k.crs) field = Field(variables=variables, spatial=sdim, temporal=temporal, level=level, realization=realization) if k.with_mask: mask = np.zeros(value_tmin.shape[-2:], dtype=bool) mask[0, 1] = True set_new_value_mask_for_field(field, mask) sdim.set_mask(mask) self.assertTrue(tmin.value.mask.any()) self.assertTrue(sdim.get_mask().any()) else: self.assertFalse(tmin.value.mask.any()) self.assertFalse(sdim.get_mask().any()) coll = SpatialCollection() coll[1] = {field.name: field} conv = ESMPyConverter([coll]) efield = conv.write() if k.dimensions: dimensions = {} if k.drealization: dimensions["realization"] = realization if k.dtemporal: dimensions["temporal"] = temporal if k.dlevel: dimensions["level"] = level else: dimensions = None ofield = get_ocgis_field_from_esmf_field(efield, crs=k.crs, dimensions=dimensions) self.assertIsInstance(ofield, Field) self.assertEqual(ofield.shape, efield.data.shape) # Test a default CRS is applied for the spherical case. if k.crs is None: self.assertEqual(ofield.spatial.crs, Spherical()) if k.drealization and k.dimensions: target = realization.value else: target = np.array([1, 2]) self.assertNumpyAll(ofield.realization.value, target) if k.dtemporal and k.dimensions: target = temporal.value else: target = np.array([1, 1, 1]) with self.assertRaises(CannotFormatTimeError): ofield.temporal.value_datetime self.assertFalse(ofield.temporal.format_time) self.assertNumpyAll(ofield.temporal.value, target) if k.dlevel and k.dimensions: target = level.value else: target = np.array([1, 2, 3, 4]) self.assertNumpyAll(ofield.level.value, target) self.assertNumpyAll(field.spatial.grid.value, ofield.spatial.grid.value) if k.with_corners: self.assertIsNotNone(ofield.spatial.grid.corners) self.assertNumpyAll(field.spatial.grid.corners, ofield.spatial.grid.corners) try: self.assertEqual(ofield.spatial.crs, sdim.crs) except AssertionError: # A "None" "crs" argument results in a default coordinate system applied to the output OCGIS field. self.assertIsNone(k.crs) ofield_tmin_value = ofield.variables[efield.name].value for arr1, arr2 in itertools.combinations([tmin.value.data, efield.data, ofield_tmin_value.data], r=2): self.assertNumpyAll(arr1, arr2, check_arr_type=False) rows = list(ofield.get_iter()) try: self.assertEqual(len(rows), len(value_tmin.flatten())) except AssertionError: self.assertTrue(k.with_mask) self.assertEqual(len(rows), len(tmin.value.compressed())) self.assertTrue(np.may_share_memory(ofield_tmin_value, efield.data)) self.assertFalse(np.may_share_memory(ofield_tmin_value, tmin.value))
def test_write_netcdf(self): path = os.path.join(self.current_dir_output, 'foo.nc') other_bounds_name = 'bnds' keywords = dict(with_bounds=[True, False], with_attrs=[True, False], unlimited=[False, True], kwargs=[{}, {'zlib': True}], bounds_dimension_name=[None, other_bounds_name], axis=[None, 'GG'], name=[None, 'temporal'], name_bounds=[None, 'time_bounds'], name_value=[None, 'time'], format=[None, 'NETCDF4_CLASSIC']) for k in itr_products_keywords(keywords, as_namedtuple=True): if k.with_attrs: attrs = {'a': 5, 'b': np.array([5, 6])} else: attrs = None vd = VectorDimension(value=[2., 4.], attrs=attrs, name=k.name, name_bounds=k.name_bounds, name_value=k.name_value, axis=k.axis, unlimited=k.unlimited) if k.with_bounds: vd.set_extrapolated_bounds() with nc_scope(path, 'w') as ds: try: vd.write_netcdf(ds, bounds_dimension_name=k.bounds_dimension_name, **k.kwargs) except ValueError: self.assertIsNone(vd.name) continue with nc_scope(path, 'r') as ds: var = ds.variables[vd.name_value] if k.axis is None: axis_actual = '' else: axis_actual = vd.axis self.assertEqual(var.axis, axis_actual) try: self.assertIn(constants.OCGIS_BOUNDS, ds.dimensions) except AssertionError: try: self.assertFalse(k.with_bounds) except AssertionError: try: self.assertEqual(k.bounds_dimension_name, other_bounds_name) except AssertionError: self.assertIsNotNone(k.name_bounds_suffix) self.assertIsNone(k.bounds_dimension_name) self.assertIn(k.name_bounds_suffix, ds.variables[vd.name_bounds].dimensions) try: self.assertFalse(ds.dimensions[vd.name].isunlimited()) except AssertionError: self.assertTrue(k.unlimited) try: self.assertEqual(var.a, attrs['a']) self.assertNumpyAll(var.b, attrs['b']) except AttributeError: self.assertFalse(k.with_attrs) try: self.assertEqual(var.bounds, vd.name_bounds) self.assertNumpyAll(vd.bounds, ds.variables[vd.name_bounds][:]) except (AttributeError, KeyError): self.assertFalse(k.with_bounds) self.assertEqual(var._name, vd.name_value) self.assertEqual(var.dimensions, (vd.name,)) self.assertNumpyAll(vd.value, var[:])
def test_units_with_bounds(self): value = [5., 10., 15.] vdim = VectorDimension(value=value, units='celsius', bounds=get_bounds_from_1d(np.array(value))) vdim.cfunits_conform(get_units_object('kelvin')) self.assertNumpyAll(vdim.bounds, np.array([[275.65, 280.65], [280.65, 285.65], [285.65, 290.65]]))
def test_with_units_and_bounds_interpolation(self): vdim = VectorDimension(value=[5., 10., 15.], units='celsius') vdim.set_extrapolated_bounds() vdim.cfunits_conform(Units('kelvin')) self.assertNumpyAll(vdim.bounds, np.array([[275.65, 280.65], [280.65, 285.65], [285.65, 290.65]]))
def test_remove_bounds(self): vd = VectorDimension(value=[1, 2, 3]) vd.set_extrapolated_bounds() self.assertIsNotNone(vd.bounds) vd.remove_bounds() self.assertIsNone(vd.bounds)