def test_real_set_lazy(self): # Setting new lazy data does not make a copy. ancill_var = AncillaryVariable(self.data_real) new_data = self.data_lazy + 102.3 ancill_var.data = new_data result = ancill_var.core_data() self.assertEqualLazyArraysAndDtypes(result, new_data)
def test_lazy_data(self): # Getting lazy data realises them. ancill_var = AncillaryVariable(self.data_lazy) self.assertTrue(ancill_var.has_lazy_data()) result = ancill_var.data self.assertFalse(ancill_var.has_lazy_data()) self.assertEqualRealArraysAndDtypes(result, self.data_real)
def test_preserves_lazy(self): test_data = np.array([[11.1, 12.2, 13.3], [21.4, 22.5, 23.6]]) lazy_data = as_lazy_data(test_data) ancill_var = AncillaryVariable(data=lazy_data, units="m") ancill_var.convert_units("ft") self.assertTrue(ancill_var.has_lazy_data()) test_data_ft = Unit("m").convert(test_data, "ft") self.assertArrayAllClose(ancill_var.data, test_data_ft)
def test_real_data(self): ancill_var = AncillaryVariable(self.data_real) result = ancill_var.core_data() self.assertArraysShareData( result, self.data_real, "core_data() do not share data with the internal array.", )
def test_masked_data_real(self): data = self.masked_data_real self.assertTrue(ma.isMaskedArray(data)) self.assertTrue(ma.count_masked(data)) ancill_var = AncillaryVariable(data) self.assertFalse(ancill_var.has_lazy_data()) self.assertTrue(ma.isMaskedArray(ancill_var.data)) self.assertTrue(ma.count_masked(ancill_var.data))
def test_masked_data_lazy(self): data = self.masked_data_lazy computed = data.compute() self.assertTrue(ma.isMaskedArray(computed)) self.assertTrue(ma.count_masked(computed)) ancill_var = AncillaryVariable(data) self.assertTrue(ancill_var.has_lazy_data()) self.assertTrue(ma.isMaskedArray(ancill_var.data)) self.assertTrue(ma.count_masked(ancill_var.data))
def test_real_set_real(self): # Setting new real data does not make a copy. ancill_var = AncillaryVariable(self.data_real) new_data = self.data_real + 102.3 ancill_var.data = new_data result = ancill_var.core_data() self.assertArraysShareData( result, new_data, 'Data values do not share data with the assigned array.')
def test_time_values(self): ancillary_var = AncillaryVariable( np.array([2, 5, 9]), units='hours since 1970-01-01 01:00', long_name='time of previous valid detection') expected = ("AncillaryVariable(array([2, 5, 9]), standard_name=None, " "units=Unit('hours since 1970-01-01 01:00', " "calendar='gregorian'), " "long_name='time of previous valid detection')") self.assertEqual(expected, ancillary_var.__repr__())
def setUp(self): self.setupTestArrays() self.real_ancill_var = AncillaryVariable(self.data_real) self.lazy_ancill_var = AncillaryVariable(self.data_lazy) self.test_combinations = [ (self.real_ancill_var, self.data_real, "real"), (self.lazy_ancill_var, self.data_lazy, "lazy"), ]
def test(self): # Check that "coord.cube_dims(cube)" calls "cube.coord_dims(coord)". mock_dims_result = mock.sentinel.AV_DIMS mock_dims_call = mock.Mock(return_value=mock_dims_result) mock_cube = mock.Mock(Cube, ancillary_variable_dims=mock_dims_call) test_var = AncillaryVariable([1], long_name="test_name") result = test_var.cube_dims(mock_cube) self.assertEqual(result, mock_dims_result) self.assertEqual(mock_dims_call.call_args_list, [mock.call(test_var)])
def test_time_values(self): ancillary_var = AncillaryVariable( np.array([2, 5, 9]), units="hours since 1970-01-01 01:00", long_name="time of previous valid detection", ) expected = ( "<AncillaryVariable: time of previous valid detection / (hours since 1970-01-01 01:00) " "[...] shape(3,)>") self.assertEqual(expected, ancillary_var.__repr__())
def test_non_time_values(self): ancillary_var = AncillaryVariable( np.array([2, 5, 9]), standard_name="height", long_name="height of detector", var_name="height", units="m", attributes={"notes": "Measured from sea level"}, ) expected = "<AncillaryVariable: height / (m) [2, 5, 9] shape(3,)>" self.assertEqual(expected, ancillary_var.__repr__())
def test_time_values(self): ancillary_var = AncillaryVariable( np.array([2, 5, 9]), units="hours since 1970-01-01 01:00", long_name="time of previous valid detection", ) expected = ( "AncillaryVariable([1970-01-01 03:00:00, " "1970-01-01 06:00:00, 1970-01-01 10:00:00], " "standard_name=None, calendar='gregorian', " "long_name='time of previous valid detection')" ) self.assertEqual(expected, ancillary_var.__str__())
class Test_is_compatible(tests.IrisTest): def setUp(self): self.ancill_var = AncillaryVariable( [1.0, 8.0, 22.0], standard_name="number_of_observations", units="1" ) self.modified_ancill_var = self.ancill_var.copy() def test_not_compatible_diff_name(self): # Different name() - not compatible self.modified_ancill_var.rename("air_temperature") self.assertFalse( self.ancill_var.is_compatible(self.modified_ancill_var) ) def test_not_compatible_diff_units(self): # Different units- not compatible self.modified_ancill_var.units = "m" self.assertFalse( self.ancill_var.is_compatible(self.modified_ancill_var) ) def test_not_compatible_diff_common_attrs(self): # Different common attributes - not compatible. self.ancill_var.attributes["source"] = "A" self.modified_ancill_var.attributes["source"] = "B" self.assertFalse( self.ancill_var.is_compatible(self.modified_ancill_var) ) def test_compatible_diff_data(self): # Different data values - compatible. self.modified_ancill_var.data = [10.0, 20.0, 100.0] self.assertTrue( self.ancill_var.is_compatible(self.modified_ancill_var) ) def test_compatible_diff_var_name(self): # Different var_name (but same name()) - compatible. self.modified_ancill_var.var_name = "obs_num" self.assertTrue( self.ancill_var.is_compatible(self.modified_ancill_var) ) def test_compatible_diff_non_common_attributes(self): # Different non-common attributes - compatible. self.ancill_var.attributes["source"] = "A" self.modified_ancill_var.attributes["origin"] = "B" self.assertTrue( self.ancill_var.is_compatible(self.modified_ancill_var) ) def test_compatible_ignore_common_attribute(self): # ignore different common attributes - compatible. self.ancill_var.attributes["source"] = "A" self.modified_ancill_var.attributes["source"] = "B" self.assertTrue( self.ancill_var.is_compatible( self.modified_ancill_var, ignore="source" ) )
def test_non_time_values(self): ancillary_var = AncillaryVariable( np.array([2, 5, 9]), standard_name="height", long_name="height of detector", var_name="height", units="m", attributes={"notes": "Measured from sea level"}, ) expected = ( "AncillaryVariable(array([2, 5, 9]), " "standard_name='height', units=Unit('m'), " "long_name='height of detector', var_name='height', " "attributes={'notes': 'Measured from sea level'})" ) self.assertEqual(expected, ancillary_var.__repr__())
def test_time_values(self): ancillary_var = AncillaryVariable( np.array([2, 5, 9]), units="hours since 1970-01-01 01:00", long_name="time of previous valid detection", ) expected = "\n".join([ ("AncillaryVariable : time of previous valid detection / " "(hours since 1970-01-01 01:00, gregorian calendar)"), (" data: [1970-01-01 03:00:00, 1970-01-01 06:00:00, " "1970-01-01 10:00:00]"), " shape: (3,)", " dtype: int64", " long_name: 'time of previous valid detection'", ]) self.assertEqual(expected, ancillary_var.__str__())
def test_real_data(self): # Getting real data does not change or copy them. ancill_var = AncillaryVariable(self.data_real) result = ancill_var.data self.assertArraysShareData( result, self.data_real, 'Data values do not share data with the provided array.')
def test_mutable_real_data(self): # Check that ancill_var.data returns a modifiable array, and changes # to it are reflected to the ancillary_var. data = np.array([1.0, 2.0, 3.0, 4.0]) ancill_var = AncillaryVariable(data) initial_values = data.copy() ancill_var.data[1:2] += 33.1 result = ancill_var.data self.assertFalse(np.all(result == initial_values))
class Test_is_compatible(tests.IrisTest): def setUp(self): self.ancill_var = AncillaryVariable( [1., 8., 22.], standard_name='number_of_observations', units='1') self.modified_ancill_var = self.ancill_var.copy() def test_not_compatible_diff_name(self): # Different name() - not compatible self.modified_ancill_var.rename('air_temperature') self.assertFalse( self.ancill_var.is_compatible(self.modified_ancill_var)) def test_not_compatible_diff_units(self): # Different units- not compatible self.modified_ancill_var.units = 'm' self.assertFalse( self.ancill_var.is_compatible(self.modified_ancill_var)) def test_not_compatible_diff_common_attrs(self): # Different common attributes - not compatible. self.ancill_var.attributes['source'] = 'A' self.modified_ancill_var.attributes['source'] = 'B' self.assertFalse( self.ancill_var.is_compatible(self.modified_ancill_var)) def test_compatible_diff_data(self): # Different data values - compatible. self.modified_ancill_var.data = [10., 20., 100.] self.assertTrue(self.ancill_var.is_compatible( self.modified_ancill_var)) def test_compatible_diff_var_name(self): # Different var_name (but same name()) - compatible. self.modified_ancill_var.var_name = 'obs_num' self.assertTrue(self.ancill_var.is_compatible( self.modified_ancill_var)) def test_compatible_diff_non_common_attributes(self): # Different non-common attributes - compatible. self.ancill_var.attributes['source'] = 'A' self.modified_ancill_var.attributes['origin'] = 'B' self.assertTrue(self.ancill_var.is_compatible( self.modified_ancill_var)) def test_compatible_ignore_common_attribute(self): # ignore different common attributes - compatible. self.ancill_var.attributes['source'] = 'A' self.modified_ancill_var.attributes['source'] = 'B' self.assertTrue( self.ancill_var.is_compatible(self.modified_ancill_var, ignore='source'))
def test_ancillary_variable(self): cube = self.cube cell_measure = AncillaryVariable([1, 2, 3], long_name="foo") cube.add_ancillary_variable(cell_measure, 0) rep = iris._representation.CubeSummary(cube) av_section = rep.vector_sections["Ancillary variables:"] self.assertEqual(len(av_section.contents), 1) av_summary = av_section.contents[0] self.assertEqual(av_summary.name, "foo") self.assertEqual(av_summary.dim_chars, ["x", "-"])
def test_section_vector_ancils(self): cube = Cube(np.zeros((2, 3)), long_name="name", units=1) cube.add_ancillary_variable(AncillaryVariable([0, 1], long_name="av1"), 0) rep = cube_replines(cube) expected = [ "name / (1) (-- : 2; -- : 3)", " Ancillary variables:", " av1 x -", ] self.assertEqual(rep, expected)
def test_section_scalar_ancillaries(self): # There *is* no section for this. But there probably ought to be. cube = Cube(np.zeros((2, 3)), long_name="name", units=1) cube.add_ancillary_variable(AncillaryVariable([0], long_name="av")) rep = cube_replines(cube) expected = [ "name / (1) (-- : 2; -- : 3)", " Ancillary variables:", " av - -", ] self.assertEqual(rep, expected)
def setUp(self): self.cube = stock.realistic_4d() cmth = CellMethod("mean", "time", "6hr") self.cube.add_cell_method(cmth) cms = CellMeasure([0, 1, 2, 3, 4, 5], long_name="foo") self.cube.add_cell_measure(cms, 0) avr = AncillaryVariable([0, 1, 2, 3, 4, 5], long_name="bar") self.cube.add_ancillary_variable(avr, 0) scms = CellMeasure([0], long_name="baz") self.cube.add_cell_measure(scms) self.representer = CubeRepresentation(self.cube) self.representer._get_bits(self.representer._get_lines())
def test_non_time_values(self): ancillary_var = AncillaryVariable( np.array([2, 5, 9]), standard_name="height", long_name="height of detector", var_name="height", units="m", attributes={"notes": "Measured from sea level"}, ) expected = "\n".join([ "AncillaryVariable : height / (m)", " data: [2, 5, 9]", " shape: (3,)", " dtype: int64", " standard_name: 'height'", " long_name: 'height of detector'", " var_name: 'height'", " attributes:", " notes 'Measured from sea level'", ]) self.assertEqual(expected, ancillary_var.__str__())
def setUp(self): self.cube = stock.realistic_4d() cmth = CellMethod('mean', 'time', '6hr') self.cube.add_cell_method(cmth) cms = CellMeasure([0, 1, 2, 3, 4, 5], measure='area', long_name='foo') self.cube.add_cell_measure(cms, 0) avr = AncillaryVariable([0, 1, 2, 3, 4, 5], long_name='bar') self.cube.add_ancillary_variable(avr, 0) scms = CellMeasure([0], measure='area', long_name='baz') self.cube.add_cell_measure(scms) self.representer = CubeRepresentation(self.cube) self.representer._get_bits(self.representer._get_lines())
def data_all_dtypes_and_lazynesses(self): # Generate ancillary variables with real and lazy data, and a few different # dtypes. data_types = ["real", "lazy"] dtypes = [np.int16, np.int32, np.float32, np.float64] for dtype in dtypes: for data_type_name in data_types: data = np.asarray(self.data_real, dtype=dtype) if data_type_name == "lazy": data = da.from_array(data, data.shape) ancill_var = AncillaryVariable(data) result = (ancill_var, data_type_name) yield result
def test_ancillary(self): # Check we can print an AncillaryVariable # Practically, ~identical to an AuxCoord, but without bounds, and the # array is called 'data'. data = self.sample_data() ancil = AncillaryVariable(data, long_name="v_aux", units="m s-1") result = self.repr_str_strings(ancil) expected = [ "<AncillaryVariable: v_aux / (m s-1) [0., ...] shape(5,)>", "AncillaryVariable : v_aux / (m s-1)", " data: [0., 1., 2., 3., 4.]", " shape: (5,)", " dtype: float64", " long_name: 'v_aux'", ] self.assertLines(expected, result)
def test_status_flags(self): # Note: using a CDL string as a test data reference, rather than a binary file. ref_cdl = """ netcdf cm_attr { dimensions: axv = 3 ; variables: int64 qqv(axv) ; qqv:long_name = "qq" ; qqv:units = "1" ; qqv:ancillary_variables = "my_av" ; int64 axv(axv) ; axv:units = "1" ; axv:long_name = "x" ; byte my_av(axv) ; my_av:long_name = "qq status_flag" ; my_av:flag_values = 1b, 2b ; my_av:flag_meanings = "a b" ; data: axv = 11, 21, 31; my_av = 1b, 1b, 2b; } """ nc_path = cdl_to_nc(ref_cdl) # Load with iris.fileformats.netcdf.load_cubes, and check expected content. cubes = list(load_cubes(nc_path)) self.assertEqual(len(cubes), 1) avs = cubes[0].ancillary_variables() self.assertEqual(len(avs), 1) expected = AncillaryVariable( np.ma.array([1, 1, 2], dtype=np.int8), long_name="qq status_flag", var_name="my_av", units="no_unit", attributes={ "flag_values": np.array([1, 2], dtype=np.int8), "flag_meanings": "a b", }, ) self.assertEqual(avs[0], expected)
def test_ancillary_variables(self): # Note: using a CDL string as a test data reference, rather than a # binary file. ref_cdl = """ netcdf cm_attr { dimensions: axv = 3 ; variables: int64 qqv(axv) ; qqv:long_name = "qq" ; qqv:units = "1" ; qqv:ancillary_variables = "my_av" ; int64 axv(axv) ; axv:units = "1" ; axv:long_name = "x" ; double my_av(axv) ; my_av:units = "1" ; my_av:long_name = "refs" ; my_av:custom = "extra-attribute"; data: axv = 1, 2, 3; my_av = 11., 12., 13.; } """ nc_path = cdl_to_nc(ref_cdl) # Load with iris.fileformats.netcdf.load_cubes, and check expected content. cubes = list(load_cubes(nc_path)) self.assertEqual(len(cubes), 1) avs = cubes[0].ancillary_variables() self.assertEqual(len(avs), 1) expected = AncillaryVariable( np.ma.array([11.0, 12.0, 13.0]), long_name="refs", var_name="my_av", units="1", attributes={"custom": "extra-attribute"}, ) self.assertEqual(avs[0], expected)
def _make_cube(x, y, data, aux=None, cell_measure=None, ancil=None, offset=0, scalar=None): """ A convenience test function that creates a custom 2D cube. Args: * x: A (start, stop, step) tuple for specifying the x-axis dimensional coordinate points. Bounds are automatically guessed. * y: A (start, stop, step) tuple for specifying the y-axis dimensional coordinate points. Bounds are automatically guessed. * data: The data payload for the cube. Kwargs: * aux: A CSV string specifying which points only auxiliary coordinates to create. Accepts either of 'x', 'y', 'xy'. * offset: Offset value to be added to the 'xy' auxiliary coordinate points. * scalar: Create a 'height' scalar coordinate with the given value. Returns: The newly created 2D :class:`iris.cube.Cube`. """ x_range = np.arange(*x, dtype=np.float32) y_range = np.arange(*y, dtype=np.float32) x_size = len(x_range) y_size = len(y_range) cube_data = np.empty((y_size, x_size), dtype=np.float32) cube_data[:] = data cube = iris.cube.Cube(cube_data) coord = DimCoord(y_range, long_name="y", units="1") coord.guess_bounds() cube.add_dim_coord(coord, 0) coord = DimCoord(x_range, long_name="x", units="1") coord.guess_bounds() cube.add_dim_coord(coord, 1) if aux is not None: aux = aux.split(",") if "y" in aux: coord = AuxCoord(y_range * 10, long_name="y-aux", units="1") cube.add_aux_coord(coord, (0, )) if "x" in aux: coord = AuxCoord(x_range * 10, long_name="x-aux", units="1") cube.add_aux_coord(coord, (1, )) if "xy" in aux: payload = np.arange(y_size * x_size, dtype=np.float32).reshape(y_size, x_size) coord = AuxCoord(payload * 100 + offset, long_name="xy-aux", units="1") cube.add_aux_coord(coord, (0, 1)) if cell_measure is not None: cell_measure = cell_measure.split(",") if "y" in cell_measure: cm = CellMeasure(y_range * 10, long_name="y-aux", units="1") cube.add_cell_measure(cm, (0, )) if "x" in cell_measure: cm = CellMeasure(x_range * 10, long_name="x-aux", units="1") cube.add_cell_measure(cm, (1, )) if "xy" in cell_measure: payload = x_range + y_range[:, np.newaxis] cm = CellMeasure(payload * 100 + offset, long_name="xy-aux", units="1") cube.add_cell_measure(cm, (0, 1)) if ancil is not None: ancil = ancil.split(",") if "y" in ancil: av = AncillaryVariable(y_range * 10, long_name="y-aux", units="1") cube.add_ancillary_variable(av, (0, )) if "x" in ancil: av = AncillaryVariable(x_range * 10, long_name="x-aux", units="1") cube.add_ancillary_variable(av, (1, )) if "xy" in ancil: payload = x_range + y_range[:, np.newaxis] av = AncillaryVariable(payload * 100 + offset, long_name="xy-aux", units="1") cube.add_ancillary_variable(av, (0, 1)) if scalar is not None: data = np.array([scalar], dtype=np.float32) coord = AuxCoord(data, long_name="height", units="m") cube.add_aux_coord(coord, ()) return cube