def setUp(self): data = np.array([[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 9]], dtype=np.float32) cube = iris.cube.Cube(data, standard_name="x_wind", units="km/h") self.lonlat_cs = iris.coord_systems.GeogCS(6371229) cube.add_dim_coord( DimCoord(np.arange(4, dtype=np.float32) * 90 - 180, 'longitude', units='degrees', circular=True, coord_system=self.lonlat_cs), 0) cube.add_dim_coord( DimCoord(np.arange(5, dtype=np.float32) * 45 - 90, 'latitude', units='degrees', coord_system=self.lonlat_cs), 1) cube.add_aux_coord( DimCoord(np.arange(4, dtype=np.float32), long_name='x', units='count', circular=True), 0) cube.add_aux_coord( DimCoord(np.arange(5, dtype=np.float32), long_name='y', units='count'), 1) self.cube = cube
def test_dim_to_aux(self): cube = self.simple2d_cube other = iris.coords.DimCoord([1, 2, 3, 4], long_name='was_dim') cube.add_aux_coord(other, 0) r = iris.analysis.interpolate.linear(cube, [('dim1', [7, 3, 5])]) normalise_order(r) self.assertCML(r, ('analysis', 'interpolation', 'linear', 'dim_to_aux.cml'))
def _make_cube( self, data, dtype=np.dtype("int32"), fill_value=None, mask=None, lazy=False, N=3, ): x = np.arange(N) y = np.arange(N) payload = self._make_data(data, dtype=dtype, fill_value=fill_value, mask=mask, lazy=lazy, N=N) cube = iris.cube.Cube(payload) lat = DimCoord(y, standard_name="latitude", units="degrees") cube.add_dim_coord(lat, 0) lon = DimCoord(x, standard_name="longitude", units="degrees") cube.add_dim_coord(lon, 1) height = DimCoord(data, standard_name="height", units="m") cube.add_aux_coord(height) return cube
def _dereference_args(factory, reference_targets, regrid_cache, cube): """Converts all the arguments for a factory into concrete coordinates.""" args = [] for arg in factory.args: if isinstance(arg, Reference): if arg.name in reference_targets: src = reference_targets[arg.name].as_cube() # If necessary, regrid the reference cube to # match the grid of this cube. src = _ensure_aligned(regrid_cache, src, cube) if src is not None: new_coord = iris.coords.AuxCoord(src.data, src.standard_name, src.long_name, src.var_name, src.units, attributes=src.attributes) dims = [cube.coord_dims(src_coord)[0] for src_coord in src.dim_coords] cube.add_aux_coord(new_coord, dims) args.append(new_coord) else: raise _ReferenceError('Unable to regrid reference for' ' {!r}'.format(arg.name)) else: raise _ReferenceError("The source data contains no " "field(s) for {!r}.".format(arg.name)) else: # If it wasn't a Reference, then arg is a dictionary # of keyword arguments for cube.coord(...). args.append(cube.coord(**arg)) return args
def test_bounded_level(self): cube = iris.load_cube( tests.get_data_path(("GRIB", "uk_t", "uk_t.grib2"))) # Changing pressure to altitude due to grib api bug: # https://github.com/SciTools/iris/pull/715#discussion_r5901538 cube.remove_coord("pressure") cube.add_aux_coord( iris.coords.AuxCoord( 1030.0, long_name="altitude", units="m", bounds=np.array([111.0, 1949.0]), )) with self.temp_filename(".grib2") as testfile: iris.save(cube, testfile) with open(testfile, "rb") as saved_file: g = gribapi.grib_new_from_file(saved_file) self.assertEqual( gribapi.grib_get_double(g, "scaledValueOfFirstFixedSurface"), 111.0, ) self.assertEqual( gribapi.grib_get_double(g, "scaledValueOfSecondFixedSurface"), 1949.0, )
def test_dim_to_aux(self): cube = self.simple2d_cube other = iris.coords.DimCoord([1, 2, 3, 4], long_name='was_dim') cube.add_aux_coord(other, 0) r = iintrp.linear(cube, [('dim1', [7, 3, 5])]) normalise_order(r) self.assertCML(r, ('analysis', 'interpolation', 'linear', 'dim_to_aux.cml'))
def _dereference_args(factory, reference_targets, regrid_cache, cube): """Converts all the arguments for a factory into concrete coordinates.""" args = [] for arg in factory.args: if isinstance(arg, Reference): if arg.name in reference_targets: src = reference_targets[arg.name].as_cube() # If necessary, regrid the reference cube to # match the grid of this cube. src = _ensure_aligned(regrid_cache, src, cube) if src is not None: new_coord = iris.coords.AuxCoord(src.data, src.standard_name, src.long_name, src.var_name, src.units, attributes=src.attributes) dims = [cube.coord_dims(src_coord)[0] for src_coord in src.dim_coords] cube.add_aux_coord(new_coord, dims) args.append(new_coord) else: raise _ReferenceError('Unable to regrid reference for' ' {!r}'.format(arg.name)) else: raise _ReferenceError("The file(s) {{filenames}} don't contain" " field(s) for {!r}.".format(arg.name)) else: # If it wasn't a Reference, then arg is a dictionary # of keyword arguments for cube.coord(...). args.append(cube.coord(**arg)) return args
def setUp(self): data = np.array([[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 9]], dtype=np.float32) cube = iris.cube.Cube(data, standard_name="x_wind", units="km/h") self.lonlat_cs = iris.coord_systems.GeogCS(6371229) cube.add_dim_coord( DimCoord( np.arange(4, dtype=np.float32) * 90 - 180, "longitude", units="degrees", circular=True, coord_system=self.lonlat_cs, ), 0, ) cube.add_dim_coord( DimCoord( np.arange(5, dtype=np.float32) * 45 - 90, "latitude", units="degrees", coord_system=self.lonlat_cs ), 1, ) cube.add_aux_coord(DimCoord(np.arange(4, dtype=np.float32), long_name="x", units="count", circular=True), 0) cube.add_aux_coord(DimCoord(np.arange(5, dtype=np.float32), long_name="y", units="count"), 1) self.cube = cube
def test_circular_vs_non_circular_coord(self): cube = self.simple2d_cube_circular other = iris.coords.AuxCoord([10, 6, 7, 4], long_name='other') cube.add_aux_coord(other, 1) samples = [0, 60, 300] r = iris.analysis.interpolate.linear(cube, [('theta', samples)]) self.assertCML(r, ('analysis', 'interpolation', 'linear', 'circular_vs_non_circular.cml'))
def build_cube(data, spherical=False): """ Create a cube suitable for testing. """ cube = iris.cube.Cube(data, standard_name="x_wind", units="km/h") nx = data.shape[-1] ny = data.shape[-2] nz = data.shape[-3] if data.ndim > 2 else None dimx = data.ndim - 1 dimy = data.ndim - 2 dimz = data.ndim - 3 if data.ndim > 2 else None if spherical: hcs = iris.coord_systems.GeogCS(6321) cube.add_dim_coord(DimCoord(np.arange(-180, 180, 360./nx, dtype=np.float32), 'longitude', units='degrees', coord_system=hcs, circular=True), dimx) cube.add_dim_coord(DimCoord(np.arange(-90, 90, 180./ny, dtype=np.float32), 'latitude', units='degrees',coord_system=hcs), dimy) else: cube.add_dim_coord(DimCoord(np.arange(nx, dtype=np.float32) * 2.21 + 2, 'projection_x_coordinate', units='meters'), dimx) cube.add_dim_coord(DimCoord(np.arange(ny, dtype=np.float32) * 25 -50, 'projection_y_coordinate', units='meters'), dimy) if nz is None: cube.add_aux_coord(DimCoord(np.array([10], dtype=np.float32), long_name='z', units='meters', attributes={"positive":"up"})) else: cube.add_dim_coord(DimCoord(np.arange(nz, dtype=np.float32) * 2, long_name='z', units='meters', attributes={"positive":"up"}), dimz) return cube
def test_simple_intersect(self): cube = iris.cube.Cube(np.array([[1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7], [4,5,6,7,8], [5,6,7,8,9]], dtype=np.int32)) lonlat_cs = iris.coord_systems.RotatedGeogCS(10, 20) cube.add_dim_coord(iris.coords.DimCoord(np.arange(5, dtype=np.float32) * 90 - 180, 'longitude', units='degrees', coord_system=lonlat_cs), 1) cube.add_dim_coord(iris.coords.DimCoord(np.arange(5, dtype=np.float32) * 45 - 90, 'latitude', units='degrees', coord_system=lonlat_cs), 0) cube.add_aux_coord(iris.coords.DimCoord(points=np.int32(11), long_name='pressure', units='Pa')) cube.rename("temperature") cube.units = "K" cube2 = iris.cube.Cube(np.array([[1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7], [4,5,6,7,8], [5,6,7,8,50]], dtype=np.int32)) lonlat_cs = iris.coord_systems.RotatedGeogCS(10, 20) cube2.add_dim_coord(iris.coords.DimCoord(np.arange(5, dtype=np.float32) * 90, 'longitude', units='degrees', coord_system=lonlat_cs), 1) cube2.add_dim_coord(iris.coords.DimCoord(np.arange(5, dtype=np.float32) * 45 - 90, 'latitude', units='degrees', coord_system=lonlat_cs), 0) cube2.add_aux_coord(iris.coords.DimCoord(points=np.int32(11), long_name='pressure', units='Pa')) cube2.rename("") r = iris.analysis.maths.intersection_of_cubes(cube, cube2) self.assertCML(r, ('cdm', 'test_simple_cube_intersection.cml'))
def _cube_with_forecast(self): cube = self._cube_time_no_forecast() cube.add_aux_coord( iris.coords.AuxCoord(np.array([6], dtype=np.int32), 'forecast_period', units='hours')) return cube
def _make_cube(self, a, b, data=0, a_dim=False, b_dim=False): cube_data = np.empty((4, 5), dtype=np.float32) cube_data[:] = data cube = iris.cube.Cube(cube_data) cube.add_dim_coord( DimCoord( np.array([0, 1, 2, 3, 4], dtype=np.int32), long_name="x", units="1", ), 1, ) cube.add_dim_coord( DimCoord( np.array([0, 1, 2, 3], dtype=np.int32), long_name="y", units="1", ), 0, ) for name, value, dim in zip(["a", "b"], [a, b], [a_dim, b_dim]): dtype = np.str if isinstance(value, str) else np.float32 ctype = DimCoord if dim else AuxCoord coord = ctype( np.array([value], dtype=dtype), long_name=name, units="1" ) cube.add_aux_coord(coord) return cube
def build_cube(data, spherical=False): """ Create a cube suitable for testing. """ cube = iris.cube.Cube(data, standard_name="x_wind", units="km/h") nx = data.shape[-1] ny = data.shape[-2] nz = data.shape[-3] if data.ndim > 2 else None dimx = data.ndim - 1 dimy = data.ndim - 2 dimz = data.ndim - 3 if data.ndim > 2 else None if spherical: hcs = iris.coord_systems.LatLonCS( iris.coord_systems.SpheroidDatum(label="Tiny Earth", semi_major_axis=6321, flattening=0.0, units="m"), iris.coord_systems.PrimeMeridian(), iris.coord_systems.GeoPosition(90, 0), "reference_longitude?") cube.add_dim_coord(DimCoord(numpy.arange(-180, 180, 360./nx, dtype=numpy.float32), 'longitude', units='degrees', coord_system=hcs, circular=True), dimx) cube.add_dim_coord(DimCoord(numpy.arange(-90, 90, 180./ny, dtype=numpy.float32), 'latitude', units='degrees',coord_system=hcs), dimy) else: hcs = iris.coord_systems.HorizontalCS("Cartesian Datum?") cube.add_dim_coord(DimCoord(numpy.arange(nx, dtype=numpy.float32) * 2.21 + 2, 'projection_x_coordinate', units='meters', coord_system=hcs), dimx) cube.add_dim_coord(DimCoord(numpy.arange(ny, dtype=numpy.float32) * 25 -50, 'projection_y_coordinate', units='meters', coord_system=hcs), dimy) if nz is None: cube.add_aux_coord(DimCoord(numpy.array([10], dtype=numpy.float32), long_name='z', units='meters', attributes={"positive":"up"})) else: cube.add_dim_coord(DimCoord(numpy.arange(nz, dtype=numpy.float32) * 2, long_name='z', units='meters', attributes={"positive":"up"}), dimz) return cube
def _make_cube(self, a, b, c, d, data=0): cube_data = np.empty((4, 5), dtype=np.float32) cube_data[:] = data cube = iris.cube.Cube(cube_data) cube.add_dim_coord( DimCoord( np.array([0, 1, 2, 3, 4], dtype=np.int32), long_name="x", units="1", ), 1, ) cube.add_dim_coord( DimCoord( np.array([0, 1, 2, 3], dtype=np.int32), long_name="y", units="1", ), 0, ) for name, value in zip(["a", "b", "c", "d"], [a, b, c, d]): dtype = np.str if isinstance(value, str) else np.float32 cube.add_aux_coord( AuxCoord( np.array([value], dtype=dtype), long_name=name, units="1" ) ) return cube
def calc(names, cubelist, levels=None): """Wrapper function to ``calculate`` with the option to interpolate to a level Args: names (str or list[str]): The CF standard name(s) of the variable(s) to be calculated. cubelist (iris.cube.CubeList): Contains either the requested variable or the variables required to calculate the requested variable. levels (tuple or None): The name and levels to interpolate the requested variable to. Default is None. Returns: iris.cube.Cube or iris.cube.CubeList: The variable(s) requested. Optionally interpolated to the given level """ if type(names) == str: names = [names] # Call calculate to get the cube cubes = [calculate(name, cubelist) for name in names] # Return the cube if interpolation is not requested if levels is None: if len(names) == 1: return cubes[0] else: return iris.cube.CubeList(cubes) else: output = iris.cube.CubeList() # Extract the coordinate requested coord_name, values = levels for cube in cubes: # Extract the coordinate from the cubes try: coord = cube.coord(coord_name) # Alternatively use a cube from the cubelist except iris.exceptions.CoordinateNotFoundError: coord = calculate(coord_name, cubelist) coord = grid.make_coord(coord) cube.add_aux_coord(coord, range(cube.ndim)) # Interpolate to the requested coordinate levels if coord.points.ndim == 1: result = cube.interpolate([(coord_name, values)], iris.analysis.Linear()) else: result = interpolate.to_level(cube, **{coord_name: values}) output.append(result) if len(names) == 1: return output[0] else: return output
def setUp(self): cube = stock.simple_3d_w_multidim_coords() cube.add_aux_coord(iris.coords.DimCoord(np.arange(2), 'height'), 0) cube.add_dim_coord(iris.coords.DimCoord(np.arange(3), 'latitude'), 1) cube.add_dim_coord(iris.coords.DimCoord(np.arange(4), 'longitude'), 2) self.data = np.arange(24).reshape(2, 3, 4).astype(np.float32) cube.data = self.data self.cube = cube
def test_cube_summary_alignment(self): # Test the cube summary dimension alignment and coord name clipping cube = iris.tests.stock.simple_1d() aux = iris.coords.AuxCoord(range(11), long_name='This is a really, really, really long long_name that requires to be clipped because it is too long') cube.add_aux_coord(aux, 0) aux = iris.coords.AuxCoord(range(11), long_name='This is a short long_name') cube.add_aux_coord(aux, 0) self.assertString(str(cube), ('cdm', 'str_repr', 'simple.__str__.txt'))
def setUp(self): cube = stock.simple_3d_w_multidim_coords() cube.add_aux_coord(iris.coords.DimCoord(range(2), 'height'), 0) cube.add_dim_coord(iris.coords.DimCoord(range(3), 'latitude'), 1) cube.add_dim_coord(iris.coords.DimCoord(range(4), 'longitude'), 2) self.data = np.arange(24).reshape(2, 3, 4).astype(np.float32) cube.data = self.data self.cube = cube
def test_circular_vs_non_circular_coord(self): cube = self.simple2d_cube_circular other = iris.coords.AuxCoord([10, 6, 7, 4], long_name='other') cube.add_aux_coord(other, 1) samples = [0, 60, 300] r = iintrp.linear(cube, [('theta', samples)]) normalise_order(r) self.assertCML(r, ('analysis', 'interpolation', 'linear', 'circular_vs_non_circular.cml'))
def test_weighted_mean_little(self): data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float32) weights = np.array([[9, 8, 7], [6, 5, 4], [3, 2, 1]], dtype=np.float32) cube = iris.cube.Cube(data, long_name="test_data", units="1") hcs = iris.coord_systems.GeogCS(6371229) lat_coord = iris.coords.DimCoord(np.array([1, 2, 3], dtype=np.float32), long_name="lat", units="1", coord_system=hcs) lon_coord = iris.coords.DimCoord(np.array([1, 2, 3], dtype=np.float32), long_name="lon", units="1", coord_system=hcs) cube.add_dim_coord(lat_coord, 0) cube.add_dim_coord(lon_coord, 1) cube.add_aux_coord( iris.coords.AuxCoord(np.arange(3, dtype=np.float32), long_name="dummy", units=1), 1) self.assertCML(cube, ('analysis', 'weighted_mean_source.cml')) a = cube.collapsed('lat', iris.analysis.MEAN, weights=weights) # np.ma.average doesn't apply type promotion rules in some versions, # and instead makes the result type float64. To ignore that case we # fix up the dtype here if it is promotable from float32. We still want # to catch cases where there is a loss of precision however. if a.dtype > np.float32: a.data = a.data.astype(np.float32) self.assertCMLApproxData(a, ('analysis', 'weighted_mean_lat.cml')) b = cube.collapsed(lon_coord, iris.analysis.MEAN, weights=weights) if b.dtype > np.float32: b.data = b.data.astype(np.float32) b.data = np.asarray(b.data) self.assertCMLApproxData(b, ('analysis', 'weighted_mean_lon.cml')) self.assertEqual(b.coord('dummy').shape, (1, )) # test collapsing multiple coordinates (and the fact that one of the coordinates isn't the same coordinate instance as on the cube) c = cube.collapsed([lat_coord[:], lon_coord], iris.analysis.MEAN, weights=weights) if c.dtype > np.float32: c.data = c.data.astype(np.float32) self.assertCMLApproxData(c, ('analysis', 'weighted_mean_latlon.cml')) self.assertEqual(c.coord('dummy').shape, (1, )) # Check new coord bounds - made from points self.assertArrayEqual(c.coord('lat').bounds, [[1, 3]]) # Check new coord bounds - made from bounds cube.coord('lat').bounds = [[0.5, 1.5], [1.5, 2.5], [2.5, 3.5]] c = cube.collapsed(['lat', 'lon'], iris.analysis.MEAN, weights=weights) self.assertArrayEqual(c.coord('lat').bounds, [[0.5, 3.5]]) cube.coord('lat').bounds = None # Check there was no residual change self.assertCML(cube, ('analysis', 'weighted_mean_source.cml'))
def Eady(theta, u, P, pressure_levels=(85000, 40000), theta_0=iris.cube.Cube(300, units='K')): r"""Calculate the Eady growth rate :math:`\sigma = 0.31 \frac{f}{N} |\frac{dU}{dz}|` Where :math:`f = 2 \Omega sin(\phi)` and :math:`N^2 = \frac{g}{\theta_0} \frac{d \theta}{dz}` Args: theta (iris.cube.Cube): Air potential temperature u (iris.cube.Cube): Zonal wind speed P (iris.cube.Cube): Air pressure pressure_levels: theta_0: Returns: iris.cube.Cube: Eady growth rate """ # Calculate Coriolis parameter f = coriolis_parameter(theta) # Extract altitude as a cube z = grid.make_cube(P, 'altitude') # Add pressure as a coordinate to the cubes P = grid.make_coord(P) for cube in (theta, u, z): cube.add_aux_coord(P, [0, 1, 2]) # Interpolate variables to pressure levels theta = interpolate.to_level(theta, air_pressure=pressure_levels) u = interpolate.to_level(u, air_pressure=pressure_levels) z = interpolate.to_level(z, air_pressure=pressure_levels) # Calculate the Brunt-Vaisala frequency dtheta_dz = calculus.multidim(theta, z, 'z') N_sq = dtheta_dz * (constants.g / theta_0) N_sq.units = 's-2' N = N_sq**0.5 # Calclate the wind shear du_dz = calculus.multidim(u, z, P.name()) du_dz.data = np.abs(du_dz.data) # Calculate the Eady index sigma = 0.31 * (du_dz / N) * f return sigma
def test_irregular(self): cube = self._load_basic() lat_coord = cube.coord("latitude") cube.remove_coord("latitude") new_lats = np.append(lat_coord.points[:-1], lat_coord.points[0]) # Irregular cube.add_aux_coord(iris.coords.AuxCoord(new_lats, "latitude", units="degrees", coord_system=lat_coord.coord_system), 0) saved_grib = iris.util.create_temp_filename(suffix='.grib2') self.assertRaises(iris.exceptions.TranslationError, iris.save, cube, saved_grib) os.remove(saved_grib)
def _makecube(self, y, cm=False, av=False): cube = iris.cube.Cube([0, 0]) cube.add_dim_coord(iris.coords.DimCoord([0, 1], long_name="x"), 0) cube.add_aux_coord(iris.coords.DimCoord(y, long_name="y")) if cm: cube.add_cell_measure( iris.coords.CellMeasure([1, 1], long_name="foo"), 0) if av: cube.add_ancillary_variable( iris.coords.AncillaryVariable([1, 1], long_name="bar"), 0) return cube
def _cube_time_no_forecast(self): cube = self._lat_lon_cube_no_time() unit = iris.unit.Unit('hours since epoch', calendar=iris.unit.CALENDAR_GREGORIAN) dt = datetime.datetime(2010, 12, 31, 12, 0) cube.add_aux_coord( iris.coords.AuxCoord(np.array([unit.date2num(dt)], dtype=np.float64), 'time', units=unit)) return cube
def test_stats_type_max(self, mock_set): grib = None cube = iris.cube.Cube(np.array([1.0])) time_unit = Unit("hours since 1970-01-01 00:00:00") time_coord = iris.coords.DimCoord([0.0], bounds=[0.0, 1], standard_name="time", units=time_unit) cube.add_aux_coord(time_coord, ()) cube.add_cell_method(iris.coords.CellMethod("minimum", time_coord)) product_definition_template_8(cube, grib) mock_set.assert_any_call(grib, "typeOfStatisticalProcessing", 3)
def test_stats_type_max(self, mock_set_long): grib = None cube = iris.cube.Cube(np.array([1.0])) time_unit = iris.unit.Unit('hours since 1970-01-01 00:00:00') time_coord = iris.coords.DimCoord([0.0], bounds=[0.0, 1], standard_name='time', units=time_unit) cube.add_aux_coord(time_coord, ()) cube.add_cell_method(iris.coords.CellMethod('minimum', time_coord)) grib_save_rules.type_of_statistical_processing(cube, grib, time_coord) mock_set_long.assert_any_call(grib, "typeOfStatisticalProcessing", 3)
def _make_cube(self, a, b, c, d, data=0): cube_data = np.empty((4, 5), dtype=np.float32) cube_data[:] = data cube = iris.cube.Cube(cube_data) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3, 4], dtype=np.int32), long_name="x", units="1"), 1) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3], dtype=np.int32), long_name="y", units="1"), 0) for name, value in zip(["a", "b", "c", "d"], [a, b, c, d]): dtype = np.str if isinstance(value, six.string_types) else np.float32 cube.add_aux_coord(AuxCoord(np.array([value], dtype=dtype), long_name=name, units="1")) return cube
def test_stats_type_min(self, mock_set): grib = None cube = iris.cube.Cube(np.array([1.0])) time_unit = cf_units.Unit('hours since 1970-01-01 00:00:00') time_coord = iris.coords.DimCoord([0.0], bounds=[0.0, 1], standard_name='time', units=time_unit) cube.add_aux_coord(time_coord, ()) cube.add_cell_method(iris.coords.CellMethod('maximum', time_coord)) grib_save_rules.product_definition_template_8(cube, grib) mock_set.assert_any_call(grib, "typeOfStatisticalProcessing", 2)
def test_altitude_point(self, mock_set): grib = None cube = iris.cube.Cube([1, 2, 3, 4, 5]) cube.add_aux_coord(iris.coords.AuxCoord([12345], "altitude", units="m")) grib_save_rules.set_fixed_surfaces(cube, grib) mock_set.assert_any_call(grib, "typeOfFirstFixedSurface", 102) mock_set.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) mock_set.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 12345) mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", -1) mock_set.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1)
def test_bounded_altitude_feet(self): cube = iris.cube.Cube([0]) cube.add_aux_coord(iris.coords.AuxCoord( 1500.0, long_name='altitude', units='ft', bounds=np.array([1000.0, 2000.0]))) grib = gribapi.grib_new_from_samples("GRIB2") grib_save_rules.non_hybrid_surfaces(cube, grib) self.assertEqual( gribapi.grib_get_double(grib, "scaledValueOfFirstFixedSurface"), 304.0) self.assertEqual( gribapi.grib_get_double(grib, "scaledValueOfSecondFixedSurface"), 609.0)
def test_altitude_point(self, mock_set_long): grib = None cube = iris.cube.Cube([1,2,3,4,5]) cube.add_aux_coord(iris.coords.AuxCoord([12345], "altitude", units="m")) grib_save_rules.non_hybrid_surfaces(cube, grib) mock_set_long.assert_any_call(grib, "typeOfFirstFixedSurface", 102) mock_set_long.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) mock_set_long.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 12345) mock_set_long.assert_any_call(grib, "typeOfSecondFixedSurface", -1) mock_set_long.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) mock_set_long.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1)
def test_height_point(self, mock_set_long): grib = None cube = iris.cube.Cube([1, 2, 3, 4, 5]) cube.add_aux_coord(iris.coords.AuxCoord([12345], "height", units="m")) grib_save_rules.non_hybrid_surfaces(cube, grib) mock_set_long.assert_any_call(grib, "typeOfFirstFixedSurface", 103) mock_set_long.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) mock_set_long.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 12345) mock_set_long.assert_any_call(grib, "typeOfSecondFixedSurface", -1) mock_set_long.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) mock_set_long.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1)
def test_height_point(self, mock_set): grib = None cube = iris.cube.Cube([1, 2, 3, 4, 5]) cube.add_aux_coord(iris.coords.AuxCoord([12345], "height", units="m")) grib_save_rules.set_fixed_surfaces(cube, grib) mock_set.assert_any_call(grib, "typeOfFirstFixedSurface", 103) mock_set.assert_any_call(grib, "scaleFactorOfFirstFixedSurface", 0) mock_set.assert_any_call(grib, "scaledValueOfFirstFixedSurface", 12345) mock_set.assert_any_call(grib, "typeOfSecondFixedSurface", -1) mock_set.assert_any_call(grib, "scaleFactorOfSecondFixedSurface", 255) mock_set.assert_any_call(grib, "scaledValueOfSecondFixedSurface", -1)
def test_weighted_mean_little(self): data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float32) weights = np.array([[9, 8, 7], [6, 5, 4], [3, 2, 1]], dtype=np.float32) cube = iris.cube.Cube(data, long_name="test_data", units="1") hcs = iris.coord_systems.GeogCS(6371229) lat_coord = iris.coords.DimCoord(np.array([1, 2, 3], dtype=np.float32), long_name="lat", units="1", coord_system=hcs) lon_coord = iris.coords.DimCoord(np.array([1, 2, 3], dtype=np.float32), long_name="lon", units="1", coord_system=hcs) cube.add_dim_coord(lat_coord, 0) cube.add_dim_coord(lon_coord, 1) cube.add_aux_coord(iris.coords.AuxCoord(np.arange(3, dtype=np.float32), long_name="dummy", units=1), 1) self.assertCML(cube, ('analysis', 'weighted_mean_source.cml')) a = cube.collapsed('lat', iris.analysis.MEAN, weights=weights) # np.ma.average doesn't apply type promotion rules in some versions, # and instead makes the result type float64. To ignore that case we # fix up the dtype here if it is promotable from float32. We still want # to catch cases where there is a loss of precision however. if a.dtype > np.float32: cast_data = a.data.astype(np.float32) a.replace(cast_data, fill_value=a.fill_value) self.assertCMLApproxData(a, ('analysis', 'weighted_mean_lat.cml')) b = cube.collapsed(lon_coord, iris.analysis.MEAN, weights=weights) if b.dtype > np.float32: cast_data = b.data.astype(np.float32) b.replace(cast_data, fill_value=b.fill_value) b.data = np.asarray(b.data) self.assertCMLApproxData(b, ('analysis', 'weighted_mean_lon.cml')) self.assertEqual(b.coord('dummy').shape, (1, )) # test collapsing multiple coordinates (and the fact that one of the coordinates isn't the same coordinate instance as on the cube) c = cube.collapsed([lat_coord[:], lon_coord], iris.analysis.MEAN, weights=weights) if c.dtype > np.float32: cast_data = c.data.astype(np.float32) c.replace(cast_data, fill_value=c.fill_value) self.assertCMLApproxData(c, ('analysis', 'weighted_mean_latlon.cml')) self.assertEqual(c.coord('dummy').shape, (1, )) # Check new coord bounds - made from points self.assertArrayEqual(c.coord('lat').bounds, [[1, 3]]) # Check new coord bounds - made from bounds cube.coord('lat').bounds = [[0.5, 1.5], [1.5, 2.5], [2.5, 3.5]] c = cube.collapsed(['lat', 'lon'], iris.analysis.MEAN, weights=weights) self.assertArrayEqual(c.coord('lat').bounds, [[0.5, 3.5]]) cube.coord('lat').bounds = None # Check there was no residual change self.assertCML(cube, ('analysis', 'weighted_mean_source.cml'))
def setUp(self): data = np.array( [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 9], ], dtype=np.float32, ) cube = iris.cube.Cube(data, standard_name="x_wind", units="km/h") self.lonlat_cs = iris.coord_systems.GeogCS(6371229) cube.add_dim_coord( DimCoord( np.arange(4, dtype=np.float32) * 90 - 180, "longitude", units="degrees", circular=True, coord_system=self.lonlat_cs, ), 0, ) cube.add_dim_coord( DimCoord( np.arange(5, dtype=np.float32) * 45 - 90, "latitude", units="degrees", coord_system=self.lonlat_cs, ), 1, ) cube.add_aux_coord( DimCoord( np.arange(4, dtype=np.float32), long_name="x", units="count", circular=True, ), 0, ) cube.add_aux_coord( DimCoord(np.arange(5, dtype=np.float32), long_name="y", units="count"), 1, ) self.cube = cube
def test_bounded_level(self): cube = iris.load_cube(tests.get_data_path(("GRIB", "uk_t", "uk_t.grib2"))) # Changing pressure to altitude due to grib api bug: # https://github.com/SciTools/iris/pull/715#discussion_r5901538 cube.remove_coord("pressure") cube.add_aux_coord( iris.coords.AuxCoord(1030.0, long_name="altitude", units="m", bounds=np.array([111.0, 1949.0])) ) with self.temp_filename(".grib2") as testfile: iris.save(cube, testfile) with open(testfile, "rb") as saved_file: g = gribapi.grib_new_from_file(saved_file) self.assertEqual(gribapi.grib_get_double(g, "scaledValueOfFirstFixedSurface"), 111.0) self.assertEqual(gribapi.grib_get_double(g, "scaledValueOfSecondFixedSurface"), 1949.0)
def _expected_cube(self, data): cube = iris.cube.Cube(data) cube.metadata = copy.deepcopy(self.src) grid_x = self.grid.coord('longitude') grid_y = self.grid.coord('latitude') cube.add_dim_coord(grid_x.copy(), self.grid.coord_dims(grid_x)) cube.add_dim_coord(grid_y.copy(), self.grid.coord_dims(grid_y)) src_x = self.src.coord('longitude') src_y = self.src.coord('latitude') for coord in self.src.aux_coords: if coord is not src_x and coord is not src_y: if not self.src.coord_dims(coord): cube.add_aux_coord(coord) return cube
def _make_cube(self, a, b, data=0, a_dim=False, b_dim=False): cube_data = np.empty((4, 5), dtype=np.float32) cube_data[:] = data cube = iris.cube.Cube(cube_data) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3, 4], dtype=np.int32), long_name="x", units="1"), 1) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3], dtype=np.int32), long_name="y", units="1"), 0) for name, value, dim in zip(["a", "b"], [a, b], [a_dim, b_dim]): dtype = np.str if isinstance(value, six.string_types) else np.float32 ctype = DimCoord if dim else AuxCoord coord = ctype(np.array([value], dtype=dtype), long_name=name, units="1") cube.add_aux_coord(coord) return cube
def _make_cube(self, data, dtype=np.dtype('int32'), fill_value=None, mask=None, lazy=False, N=3): x = np.arange(N) y = np.arange(N) payload = self._make_data(data, dtype=dtype, fill_value=fill_value, mask=mask, lazy=lazy, N=N) cube = iris.cube.Cube(payload) lat = DimCoord(y, standard_name='latitude', units='degrees') cube.add_dim_coord(lat, 0) lon = DimCoord(x, standard_name='longitude', units='degrees') cube.add_dim_coord(lon, 1) height = DimCoord(data, standard_name='height', units='m') cube.add_aux_coord(height) return cube
def _make_cube(self, a, b, c, d, data=0): cube_data = np.empty((4, 5), dtype=np.float32) cube_data[:] = data cube = iris.cube.Cube(cube_data) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3, 4], dtype=np.int32), long_name='x', units='1'), 1) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3], dtype=np.int32), long_name='y', units='1'), 0) for name, value in zip(['a', 'b', 'c', 'd'], [a, b, c, d]): dtype = np.str if isinstance(value, six.string_types) else np.float32 cube.add_aux_coord(AuxCoord(np.array([value], dtype=dtype), long_name=name, units='1')) return cube
def _make_cube(self, a, b, c, d, data=0): cube_data = np.empty((4, 5), dtype=np.float32) cube_data[:] = data cube = iris.cube.Cube(cube_data) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3, 4], dtype=np.int32), long_name='x', units='1'), 1) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3], dtype=np.int32), long_name='y', units='1'), 0) for name, value in zip(['a', 'b', 'c', 'd'], [a, b, c, d]): dtype = np.str if isinstance(value, basestring) else np.float32 cube.add_aux_coord(AuxCoord(np.array([value], dtype=dtype), long_name=name, units='1')) return cube
def create_cube(self): data = np.arange(4).reshape(2, 2) lat = iris.coords.DimCoord([0, 30], standard_name="latitude", units="degrees") lon = iris.coords.DimCoord([0, 15], standard_name="longitude", units="degrees") height = iris.coords.AuxCoord([1.5], standard_name="height", units="m") t_unit = cf_units.Unit("hours since 1970-01-01 00:00:00", calendar="gregorian") time = iris.coords.DimCoord([0, 6], standard_name="time", units=t_unit) cube = iris.cube.Cube(data, standard_name="air_temperature", units="K") cube.add_dim_coord(time, 0) cube.add_dim_coord(lat, 1) cube.add_aux_coord(lon, 1) cube.add_aux_coord(height) return cube
def setUp(self): data = numpy.array( [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 9]], dtype=numpy.float32) cube = iris.cube.Cube(data, standard_name="x_wind", units="km/h") self.lonlat_cs = iris.coord_systems.LatLonCS(iris.coord_systems.SpheroidDatum(), iris.coord_systems.PrimeMeridian(), iris.coord_systems.GeoPosition(90, 0), "reference_longitude?") cube.add_dim_coord(DimCoord(numpy.arange(4, dtype=numpy.float32) * 90 -180, 'longitude', units='degrees', circular=True, coord_system=self.lonlat_cs), 0) cube.add_dim_coord(DimCoord(numpy.arange(5, dtype=numpy.float32) * 45 -90, 'latitude', units='degrees', coord_system=self.lonlat_cs), 1) cube.add_aux_coord(DimCoord(numpy.arange(4, dtype=numpy.float32), long_name='x', units='count', circular=True), 0) cube.add_aux_coord(DimCoord(numpy.arange(5, dtype=numpy.float32), long_name='y', units='count'), 1) self.cube = cube
def test_bounded_altitude_feet(self): cube = iris.cube.Cube([0]) cube.add_aux_coord( iris.coords.AuxCoord(1500.0, long_name='altitude', units='ft', bounds=np.array([1000.0, 2000.0]))) grib = gribapi.grib_new_from_samples("GRIB2") grib_save_rules.non_hybrid_surfaces(cube, grib) self.assertEqual( gribapi.grib_get_double(grib, "scaledValueOfFirstFixedSurface"), 304.0) self.assertEqual( gribapi.grib_get_double(grib, "scaledValueOfSecondFixedSurface"), 609.0)
def test_weighted_mean_little(self): data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float32) weights = np.array([[9, 8, 7], [6, 5, 4], [3, 2, 1]], dtype=np.float32) cube = iris.cube.Cube(data, long_name="test_data", units="1") hcs = iris.coord_systems.GeogCS(6371229) lat_coord = iris.coords.DimCoord(np.array([1, 2, 3], dtype=np.float32), long_name="lat", units="1", coord_system=hcs) lon_coord = iris.coords.DimCoord(np.array([1, 2, 3], dtype=np.float32), long_name="lon", units="1", coord_system=hcs) cube.add_dim_coord(lat_coord, 0) cube.add_dim_coord(lon_coord, 1) cube.add_aux_coord( iris.coords.AuxCoord(np.arange(3, dtype=np.float32), long_name="dummy", units=1), 1) self.assertCML(cube, ('analysis', 'weighted_mean_source.cml')) a = cube.collapsed('lat', iris.analysis.MEAN, weights=weights) self.assertCMLApproxData(a, ('analysis', 'weighted_mean_lat.cml')) b = cube.collapsed(lon_coord, iris.analysis.MEAN, weights=weights) b.data = np.asarray(b.data) self.assertCMLApproxData(b, ('analysis', 'weighted_mean_lon.cml')) self.assertEqual(b.coord('dummy').shape, (1, )) # test collapsing multiple coordinates (and the fact that one of the coordinates isn't the same coordinate instance as on the cube) c = cube.collapsed([lat_coord[:], lon_coord], iris.analysis.MEAN, weights=weights) self.assertCMLApproxData(c, ('analysis', 'weighted_mean_latlon.cml')) self.assertEqual(c.coord('dummy').shape, (1, )) # Check new coord bounds - made from points self.assertArrayEqual(c.coord('lat').bounds, [[1, 3]]) # Check new coord bounds - made from bounds cube.coord('lat').bounds = [[0.5, 1.5], [1.5, 2.5], [2.5, 3.5]] c = cube.collapsed(['lat', 'lon'], iris.analysis.MEAN, weights=weights) self.assertArrayEqual(c.coord('lat').bounds, [[0.5, 3.5]]) cube.coord('lat').bounds = None # Check there was no residual change self.assertCML(cube, ('analysis', 'weighted_mean_source.cml'))
def _make_cube(self, a, b, data=0, a_dim=False, b_dim=False): cube_data = np.empty((4, 5), dtype=np.float32) cube_data[:] = data cube = iris.cube.Cube(cube_data) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3, 4], dtype=np.int32), long_name='x', units='1'), 1) cube.add_dim_coord(DimCoord(np.array([0, 1, 2, 3], dtype=np.int32), long_name='y', units='1'), 0) for name, value, dim in zip(['a', 'b'], [a, b], [a_dim, b_dim]): dtype = np.str if isinstance(value, six.string_types) else np.float32 ctype = DimCoord if dim else AuxCoord coord = ctype(np.array([value], dtype=dtype), long_name=name, units='1') cube.add_aux_coord(coord) return cube
def create_cube(self): data = np.arange(4).reshape(2, 2) lat = iris.coords.DimCoord([0, 30], standard_name='latitude', units='degrees') lon = iris.coords.DimCoord([0, 15], standard_name='longitude', units='degrees') height = iris.coords.AuxCoord([1.5], standard_name='height', units='m') t_unit = cf_units.Unit('hours since 1970-01-01 00:00:00', calendar='gregorian') time = iris.coords.DimCoord([0, 6], standard_name='time', units=t_unit) cube = iris.cube.Cube(data, standard_name='air_temperature', units='K') cube.add_dim_coord(time, 0) cube.add_dim_coord(lat, 1) cube.add_aux_coord(lon, 1) cube.add_aux_coord(height) return cube
def test_similar_coord(self): cube = self.cube_2d.copy() lon = cube.coord("longitude") lon.attributes["flight"] = "218BX" lon.attributes["sensor_id"] = 808 lon.attributes["status"] = 2 lon2 = lon.copy() lon2.attributes["sensor_id"] = 810 lon2.attributes["ref"] = "A8T-22" del lon2.attributes["status"] cube.add_aux_coord(lon2, [1]) lat = cube.coord("latitude") lat2 = lat.copy() lat2.attributes["test"] = "True" cube.add_aux_coord(lat2, [0]) self.assertString(str(cube), ("cdm", "str_repr", "similar.__str__.txt"))
def test_add_aux_coord(self): y_another = iris.coords.DimCoord(np.array([ 2.5, 7.5, 12.5]), long_name='y_another') # DimCoords can live in cube.aux_coords self.cube.add_aux_coord(y_another, 0) self.assertEqual(self.cube.dim_coords, ()) self.assertEqual(self.cube.coords(), [y_another]) self.assertEqual(self.cube.aux_coords, (y_another,)) # AuxCoords in cube.aux_coords self.cube.add_aux_coord(self.xy, [0, 1]) self.assertEqual(self.cube.dim_coords, ()) self.assertEqual(self.cube.coords(), [y_another, self.xy]) self.assertEqual(set(self.cube.aux_coords), {y_another, self.xy}) # Lengths must match up cube = self.cube.copy() with self.assertRaises(ValueError): cube.add_aux_coord(self.xy, [1, 0])
def test_similar_coord(self): cube = self.cube_2d.copy() lon = cube.coord('longitude') lon.attributes['flight'] = '218BX' lon.attributes['sensor_id'] = 808 lon.attributes['status'] = 2 lon2 = lon.copy() lon2.attributes['sensor_id'] = 810 lon2.attributes['ref'] = 'A8T-22' del lon2.attributes['status'] cube.add_aux_coord(lon2, [1]) lat = cube.coord('latitude') lat2 = lat.copy() lat2.attributes['test'] = 'True' cube.add_aux_coord(lat2, [0]) self.assertString(str(cube), ('cdm', 'str_repr', 'similar.__str__.txt'))
def test_theta_level(self): cube = iris.cube.Cube([0]) cube.add_aux_coord(iris.coords.AuxCoord( 230.0, standard_name='air_potential_temperature', units='K', attributes={'positive': 'up'}, bounds=np.array([220.0, 240.0]))) grib = gribapi.grib_new_from_samples("GRIB2") set_fixed_surfaces(cube, grib) self.assertEqual( gribapi.grib_get_double(grib, "scaledValueOfFirstFixedSurface"), 220.0) self.assertEqual( gribapi.grib_get_double(grib, "scaledValueOfSecondFixedSurface"), 240.0) self.assertEqual( gribapi.grib_get_long(grib, "typeOfFirstFixedSurface"), 107) self.assertEqual( gribapi.grib_get_long(grib, "typeOfSecondFixedSurface"), 107)
def test_weighted_mean_little(self): data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float32) weights = np.array([[9, 8, 7], [6, 5, 4], [3, 2, 1]], dtype=np.float32) cube = iris.cube.Cube(data, long_name="test_data", units="1") hcs = iris.coord_systems.GeogCS(6371229) lat_coord = iris.coords.DimCoord( np.array([1, 2, 3], dtype=np.float32), long_name="lat", units="1", coord_system=hcs ) lon_coord = iris.coords.DimCoord( np.array([1, 2, 3], dtype=np.float32), long_name="lon", units="1", coord_system=hcs ) cube.add_dim_coord(lat_coord, 0) cube.add_dim_coord(lon_coord, 1) cube.add_aux_coord(iris.coords.AuxCoord(np.arange(3, dtype=np.float32), long_name="dummy", units=1), 1) self.assertCML(cube, ("analysis", "weighted_mean_source.cml")) a = cube.collapsed("lat", iris.analysis.MEAN, weights=weights) self.assertCMLApproxData(a, ("analysis", "weighted_mean_lat.cml")) b = cube.collapsed(lon_coord, iris.analysis.MEAN, weights=weights) b.data = np.asarray(b.data) self.assertCMLApproxData(b, ("analysis", "weighted_mean_lon.cml")) self.assertEquals(b.coord("dummy").shape, (1,)) # test collapsing multiple coordinates (and the fact that one of the coordinates isn't the same coordinate instance as on the cube) c = cube.collapsed([lat_coord[:], lon_coord], iris.analysis.MEAN, weights=weights) self.assertCMLApproxData(c, ("analysis", "weighted_mean_latlon.cml")) self.assertEquals(c.coord("dummy").shape, (1,)) # Check new coord bounds - made from points self.assertArrayEqual(c.coord("lat").bounds, [[1, 3]]) # Check new coord bounds - made from bounds cube.coord("lat").bounds = [[0.5, 1.5], [1.5, 2.5], [2.5, 3.5]] c = cube.collapsed(["lat", "lon"], iris.analysis.MEAN, weights=weights) self.assertArrayEqual(c.coord("lat").bounds, [[0.5, 3.5]]) cube.coord("lat").bounds = None # Check there was no residual change self.assertCML(cube, ("analysis", "weighted_mean_source.cml"))