def cl_cubes(): """Cubes for ``cl.``.""" b_coord = AuxCoord( [1.0], var_name='b', long_name='vertical coordinate formula term: b(k)', attributes={'a': 1, 'b': '2'}, ) cl_cube = Cube( [0.0], var_name='cl', standard_name='cloud_area_fraction_in_atmosphere_layer', aux_coords_and_dims=[(b_coord.copy(), 0)], ) x_cube = Cube([0.0], long_name='x', aux_coords_and_dims=[(b_coord.copy(), 0)]) cubes = CubeList([cl_cube, x_cube]) return cubes
def test_attributes_subtle_differences(self): cube = Cube([0]) # Add a pair that differ only in having a list instead of an array. co1a = DimCoord( [0], long_name="co1_list_or_array", attributes=dict(x=1, arr1=np.array(2), arr2=np.array([1, 2])), ) co1b = co1a.copy() co1b.attributes.update(dict(arr2=[1, 2])) for co in (co1a, co1b): cube.add_aux_coord(co) # Add a pair that differ only in an attribute array dtype. co2a = AuxCoord( [0], long_name="co2_dtype", attributes=dict(x=1, arr1=np.array(2), arr2=np.array([3, 4])), ) co2b = co2a.copy() co2b.attributes.update(dict(arr2=np.array([3.0, 4.0]))) assert co2b != co2a for co in (co2a, co2b): cube.add_aux_coord(co) # Add a pair that differ only in an attribute array shape. co3a = DimCoord( [0], long_name="co3_shape", attributes=dict(x=1, arr1=np.array([5, 6]), arr2=np.array([3, 4])), ) co3b = co3a.copy() co3b.attributes.update(dict(arr1=np.array([[5], [6]]))) for co in (co3a, co3b): cube.add_aux_coord(co) rep = iris._representation.CubeSummary(cube) co_summs = rep.scalar_sections["Scalar coordinates:"].contents co1a_summ, co1b_summ = co_summs[0:2] self.assertEqual(co1a_summ.extra, "arr2=array([1, 2])") self.assertEqual(co1b_summ.extra, "arr2=[1, 2]") co2a_summ, co2b_summ = co_summs[2:4] self.assertEqual(co2a_summ.extra, "arr2=array([3, 4])") self.assertEqual(co2b_summ.extra, "arr2=array([3., 4.])") co3a_summ, co3b_summ = co_summs[4:6] self.assertEqual(co3a_summ.extra, "arr1=array([5, 6])") self.assertEqual(co3b_summ.extra, "arr1=array([[5], [6]])")
def test_xy_dimensionality(self): u, v = uv_cubes() # Replace 1d lat with 2d lat. x = u.coord('grid_longitude').points y = u.coord('grid_latitude').points x2d, y2d = np.meshgrid(x, y) lat_2d = AuxCoord(y2d, 'grid_latitude', units='degrees', coord_system=u.coord('grid_latitude').coord_system) for cube in (u, v): cube.remove_coord('grid_latitude') cube.add_aux_coord(lat_2d.copy(), (0, 1)) with self.assertRaisesRegexp( ValueError, 'x and y coordinates must have the same number of dimensions'): rotate_winds(u, v, iris.coord_systems.OSGB())
def test_xy_dimensionality(self): u, v = uv_cubes() # Replace 1d lat with 2d lat. x = u.coord('grid_longitude').points y = u.coord('grid_latitude').points x2d, y2d = np.meshgrid(x, y) lat_2d = AuxCoord(y2d, 'grid_latitude', units='degrees', coord_system=u.coord('grid_latitude').coord_system) for cube in (u, v): cube.remove_coord('grid_latitude') cube.add_aux_coord(lat_2d.copy(), (0, 1)) with self.assertRaisesRegex( ValueError, 'x and y coordinates must have the same number of dimensions'): rotate_winds(u, v, iris.coord_systems.OSGB())
class Test_is_compatible(tests.IrisTest): def setUp(self): self.test_coord = AuxCoord([1.]) self.other_coord = self.test_coord.copy() def test_noncommon_array_attrs_compatible(self): # Non-common array attributes should be ok. self.test_coord.attributes['array_test'] = np.array([1.0, 2, 3]) self.assertTrue(self.test_coord.is_compatible(self.other_coord)) def test_matching_array_attrs_compatible(self): # Matching array attributes should be ok. self.test_coord.attributes['array_test'] = np.array([1.0, 2, 3]) self.other_coord.attributes['array_test'] = np.array([1.0, 2, 3]) self.assertTrue(self.test_coord.is_compatible(self.other_coord)) def test_different_array_attrs_incompatible(self): # Differing array attributes should make coords incompatible. self.test_coord.attributes['array_test'] = np.array([1.0, 2, 3]) self.other_coord.attributes['array_test'] = np.array([1.0, 2, 777.7]) self.assertFalse(self.test_coord.is_compatible(self.other_coord))
class Test_is_compatible(tests.IrisTest): def setUp(self): self.test_coord = AuxCoord([1.0]) self.other_coord = self.test_coord.copy() def test_noncommon_array_attrs_compatible(self): # Non-common array attributes should be ok. self.test_coord.attributes["array_test"] = np.array([1.0, 2, 3]) self.assertTrue(self.test_coord.is_compatible(self.other_coord)) def test_matching_array_attrs_compatible(self): # Matching array attributes should be ok. self.test_coord.attributes["array_test"] = np.array([1.0, 2, 3]) self.other_coord.attributes["array_test"] = np.array([1.0, 2, 3]) self.assertTrue(self.test_coord.is_compatible(self.other_coord)) def test_different_array_attrs_incompatible(self): # Differing array attributes should make coords incompatible. self.test_coord.attributes["array_test"] = np.array([1.0, 2, 3]) self.other_coord.attributes["array_test"] = np.array([1.0, 2, 777.7]) self.assertFalse(self.test_coord.is_compatible(self.other_coord))
def test_nanpoints_eq_copy(self): co1 = AuxCoord([1., np.nan, 2.]) co2 = co1.copy() self.assertEqual(co1, co2)
def _make_test_meshcoord( self, lazy_sources=False, location="face", inds_start_index=0, inds_location_axis=0, facenodes_changes=None, ): # Construct a miniature face-nodes mesh for testing. # NOTE: we will make our connectivity arrays with standard # start_index=0 and location_axis=0 : We only adjust that (if required) when # creating the actual connectivities. face_nodes_array = np.array( [ [0, 2, 1, 3], [1, 3, 10, 13], [2, 7, 9, 19], [ 3, 4, 7, -1, ], # This one has a "missing" point (it's a triangle) [8, 1, 7, 2], ] ) # Connectivity uses *masked* for missing points. face_nodes_array = np.ma.masked_less(face_nodes_array, 0) if facenodes_changes: facenodes_changes = facenodes_changes.copy() facenodes_changes.pop("n_extra_bad_points") for indices, value in facenodes_changes.items(): face_nodes_array[indices] = value # Construct a miniature edge-nodes mesh for testing. edge_nodes_array = np.array([[0, 2], [1, 3], [1, 4], [3, 7]]) # Connectivity uses *masked* for missing points. edge_nodes_array = np.ma.masked_less(edge_nodes_array, 0) n_faces = face_nodes_array.shape[0] n_edges = edge_nodes_array.shape[0] n_nodes = int(face_nodes_array.max() + 1) self.NODECOORDS_BASENUM = 1100.0 self.EDGECOORDS_BASENUM = 1200.0 self.FACECOORDS_BASENUM = 1300.0 node_xs = self.NODECOORDS_BASENUM + np.arange(n_nodes) edge_xs = self.EDGECOORDS_BASENUM + np.arange(n_edges) face_xs = self.FACECOORDS_BASENUM + np.arange(n_faces) # Record all these for re-use in tests self.n_faces = n_faces self.n_nodes = n_nodes self.face_xs = face_xs self.node_xs = node_xs self.edge_xs = edge_xs self.face_nodes_array = face_nodes_array self.edge_nodes_array = edge_nodes_array # convert source data to Dask arrays if asked. if lazy_sources: def lazify(arr): return da.from_array(arr, chunks=-1, meta=np.ndarray) node_xs = lazify(node_xs) face_xs = lazify(face_xs) edge_xs = lazify(edge_xs) face_nodes_array = lazify(face_nodes_array) edge_nodes_array = lazify(edge_nodes_array) # Build a mesh with this info stored in it. co_nodex = AuxCoord( node_xs, standard_name="longitude", long_name="node_x", units=1 ) co_facex = AuxCoord( face_xs, standard_name="longitude", long_name="face_x", units=1 ) co_edgex = AuxCoord( edge_xs, standard_name="longitude", long_name="edge_x", units=1 ) # N.B. the Mesh requires 'Y's as well. co_nodey = co_nodex.copy() co_nodey.rename("latitude") co_nodey.long_name = "node_y" co_facey = co_facex.copy() co_facey.rename("latitude") co_facey.long_name = "face_y" co_edgey = co_edgex.copy() co_edgey.rename("edge_y") co_edgey.long_name = "edge_y" face_node_conn = Connectivity( inds_start_index + ( face_nodes_array.transpose() if inds_location_axis == 1 else face_nodes_array ), cf_role="face_node_connectivity", long_name="face_nodes", start_index=inds_start_index, location_axis=inds_location_axis, ) edge_node_conn = Connectivity( inds_start_index + ( edge_nodes_array.transpose() if inds_location_axis == 1 else edge_nodes_array ), cf_role="edge_node_connectivity", long_name="edge_nodes", start_index=inds_start_index, location_axis=inds_location_axis, ) self.mesh = Mesh( topology_dimension=2, node_coords_and_axes=[(co_nodex, "x"), (co_nodey, "y")], connectivities=[face_node_conn, edge_node_conn], face_coords_and_axes=[(co_facex, "x"), (co_facey, "y")], edge_coords_and_axes=[(co_edgex, "x"), (co_edgey, "y")], ) # Construct a test meshcoord. meshcoord = MeshCoord(mesh=self.mesh, location=location, axis="x") self.meshcoord = meshcoord return meshcoord
class Test1Dim(tests.IrisTest): def setUp(self): self.lon = DimCoord( points=[0.5, 1.5, 2.5], bounds=[[0, 1], [1, 2], [2, 3]], standard_name="longitude", long_name="edge longitudes", var_name="lon", units="degrees", attributes={"test": 1}, ) # Should be fine with either a DimCoord or an AuxCoord. self.lat = AuxCoord( points=[0.5, 2.5, 1.5], bounds=[[0, 1], [2, 3], [1, 2]], standard_name="latitude", long_name="edge_latitudes", var_name="lat", units="degrees", attributes={"test": 1}, ) def create(self): return Mesh.from_coords(self.lon, self.lat) def test_dimensionality(self): mesh = self.create() self.assertEqual(1, mesh.topology_dimension) self.assertArrayEqual([0, 1, 1, 2, 2, 3], mesh.node_coords.node_x.points) self.assertArrayEqual([0, 1, 2, 3, 1, 2], mesh.node_coords.node_y.points) self.assertArrayEqual([0.5, 1.5, 2.5], mesh.edge_coords.edge_x.points) self.assertArrayEqual([0.5, 2.5, 1.5], mesh.edge_coords.edge_y.points) self.assertIsNone(getattr(mesh, "face_coords", None)) for conn_name in Connectivity.UGRID_CF_ROLES: conn = getattr(mesh, conn_name, None) if conn_name == "edge_node_connectivity": self.assertArrayEqual([[0, 1], [2, 3], [4, 5]], conn.indices) else: self.assertIsNone(conn) def test_node_metadata(self): mesh = self.create() pairs = [ (self.lon, mesh.node_coords.node_x), (self.lat, mesh.node_coords.node_y), ] for expected_coord, actual_coord in pairs: for attr in ("standard_name", "long_name", "units", "attributes"): expected = getattr(expected_coord, attr) actual = getattr(actual_coord, attr) self.assertEqual(expected, actual) self.assertIsNone(actual_coord.var_name) def test_centre_metadata(self): mesh = self.create() pairs = [ (self.lon, mesh.edge_coords.edge_x), (self.lat, mesh.edge_coords.edge_y), ] for expected_coord, actual_coord in pairs: for attr in ("standard_name", "long_name", "units", "attributes"): expected = getattr(expected_coord, attr) actual = getattr(actual_coord, attr) self.assertEqual(expected, actual) self.assertIsNone(actual_coord.var_name) def test_mesh_metadata(self): # Inappropriate to guess these values from the input coords. mesh = self.create() for attr in ( "standard_name", "long_name", "var_name", ): self.assertIsNone(getattr(mesh, attr)) self.assertTrue(mesh.units.is_unknown()) self.assertDictEqual({}, mesh.attributes) def test_lazy(self): self.lon = AuxCoord.from_coord(self.lon) self.lon = self.lon.copy(self.lon.lazy_points(), self.lon.lazy_bounds()) self.lat = self.lat.copy(self.lat.lazy_points(), self.lat.lazy_bounds()) mesh = self.create() for coord in list(mesh.all_coords): if coord is not None: self.assertTrue(coord.has_lazy_points()) for conn in list(mesh.all_connectivities): if conn is not None: self.assertTrue(conn.has_lazy_indices()) def test_coord_shape_mismatch(self): lat_orig = self.lat.copy(self.lat.points, self.lat.bounds) self.lat = lat_orig.copy(points=lat_orig.points, bounds=np.tile(lat_orig.bounds, 2)) with self.assertRaisesRegex(ValueError, "bounds shapes are not identical"): _ = self.create() self.lat = lat_orig.copy(points=lat_orig.points[-1], bounds=lat_orig.bounds[-1]) with self.assertRaisesRegex(ValueError, "points shapes are not identical"): _ = self.create() def test_reorder(self): # Swap the coords. self.lat, self.lon = self.lon, self.lat mesh = self.create() # Confirm that the coords have been swapped back to the 'correct' order. self.assertEqual("longitude", mesh.node_coords.node_x.standard_name) self.assertEqual("latitude", mesh.node_coords.node_y.standard_name) def test_non_xy(self): for coord in self.lon, self.lat: coord.standard_name = None lon_name, lat_name = [ coord.long_name for coord in (self.lon, self.lat) ] # Swap the coords. self.lat, self.lon = self.lon, self.lat with self.assertLogs(logger, "INFO", "Unable to find 'X' and 'Y'"): mesh = self.create() # Confirm that the coords have not been swapped back. self.assertEqual(lat_name, mesh.node_coords.node_x.long_name) self.assertEqual(lon_name, mesh.node_coords.node_y.long_name)