def test_create_from_gribcode(self): gribcode1 = GRIBCode((4, 3, 2, 1)) gribcode2 = GRIBCode(gribcode1) self.assertEqual(gribcode1, gribcode2) # NOTE: *not* passthrough : it creates a copy # (though maybe not too significant, as it is immutable anyway?) self.assertIsNot(gribcode1, gribcode2)
def test_create_from_own_string(self): # Check that GRIBCode string reprs are valid as create arguments. gribcode = GRIBCode( edition_or_string=2, discipline=17, category=94, number=231) grib_param_string = str(gribcode) newcode = GRIBCode(grib_param_string) self.assertEqual(newcode, gribcode)
def test_create_from_keys(self): gribcode = GRIBCode( edition_or_string=5, discipline=7, category=4, number=199) self.assertEqual(gribcode.edition, 5) self.assertEqual(gribcode.discipline, 7) self.assertEqual(gribcode.category, 4) self.assertEqual(gribcode.number, 199)
def test_no_phenomenon(self): self.phenom_lookup_patch.return_value = None expected_metadata = self.metadata.copy() translate_phenomenon(self.metadata, discipline=7, parameterCategory=77, parameterNumber=777, typeOfFirstFixedSurface=None, scaledValueOfFirstFixedSurface=None, typeOfSecondFixedSurface=None, probability=self.probability) expected_metadata['attributes']['GRIB_PARAM'] = \ GRIBCode(2, 7, 77, 777) self.assertEqual(self.metadata, expected_metadata)
def test_save_load(self): cube = stock.lat_lon_cube() cube.rename("atmosphere_mole_content_of_ozone") cube.units = Unit("Dobson") tcoord = DimCoord(23, "time", units=Unit("days since epoch", calendar="standard")) fpcoord = DimCoord(24, "forecast_period", units=Unit("hours")) cube.add_aux_coord(tcoord) cube.add_aux_coord(fpcoord) cube.attributes["WMO_constituent_type"] = 0 cube.attributes["GRIB_PARAM"] = GRIBCode("GRIB2:d000c014n000") with self.temp_filename("test_grib_pdt40.grib2") as temp_file_path: save(cube, temp_file_path) loaded = load_cube(temp_file_path) self.assertEqual(loaded.attributes, cube.attributes)
def test_basic(self): translate_phenomenon(self.metadata, 7, 8, 9, None, None, None, probability=self.probability) # Check metadata. thresh_coord = DimCoord([22.0], standard_name='air_temperature', long_name='', units='K') self.assertEqual( self.metadata, { 'standard_name': None, 'long_name': 'probability_of_air_temperature_<prob_type>', 'units': Unit(1), 'aux_coords_and_dims': [(thresh_coord, None)], 'attributes': { 'GRIB_PARAM': GRIBCode(2, 7, 8, 9) } })
def test_create_string_more_than_4_nums(self): # Note: does not error, just discards the extra. gribcode = GRIBCode('1,2,3,4,5,6,7,8') self.assertEqual(gribcode, GRIBCode(1, 2, 3, 4))
def test__str__(self): result = str(GRIBCode(2, 17, 3, 123)) self.assertEqual(result, 'GRIB2:d017c003n123')
def test_create_bad_single_arg_less_than_4_nums(self): with self.assertRaisesRegex( ValueError, 'Invalid argument for GRIBCode creation'): GRIBCode('1,2,3')
def test_create_bad_single_arg_single_numeric(self): with self.assertRaisesRegex( ValueError, 'Invalid argument for GRIBCode creation'): GRIBCode('44')
def test_create_bad_single_arg_empty_string(self): with self.assertRaisesRegex( ValueError, 'Invalid argument for GRIBCode creation'): GRIBCode('')
def test_create_bad_single_arg_nonums(self): with self.assertRaisesRegex( ValueError, 'Invalid argument for GRIBCode creation'): GRIBCode('saas- dsa- ')
def test_create_bad_nargs(self): # Between 1 and 4 args is not invalid call syntax, but it should fail. with self.assertRaisesRegex( ValueError, 'Cannot create GRIBCode from 2 arguments'): GRIBCode(1, 2)
def test_create_bad_single_arg_None(self): with self.assertRaisesRegex( ValueError, 'Cannot create GRIBCode from 0 arguments'): GRIBCode(None)
def test_gribcode_attribute_object(self): cube = self.mock_cube cube.attributes = {'GRIB_PARAM': GRIBCode(2, 7, 12, 99)} self._check_coding(cube, 7, 12, 99)
def test_gribcode_attribute_not_edition_2(self): cube = self.mock_cube cube.attributes = {'GRIB_PARAM': GRIBCode(1, 7, 12, 99)} self._check_coding(cube, 255, 255, 255)
def test_create_from_string(self): gribcode = GRIBCode('xxx12xs-34 -5,678qqqq') # NOTE: args 2 and 3 are *not* negative. self.assertEqual(gribcode, GRIBCode(12, 34, 5, 678))
def test_create_from_args(self): gribcode = GRIBCode(7, 3, 12, 99) self.assertEqual(gribcode.edition, 7) self.assertEqual(gribcode.discipline, 3) self.assertEqual(gribcode.category, 12) self.assertEqual(gribcode.number, 99)
def test_create_is_copy(self): gribcode1 = GRIBCode(7, 3, 12, 99) gribcode2 = GRIBCode(7, 3, 12, 99) self.assertEqual(gribcode1, gribcode2) self.assertIsNot(gribcode1, gribcode2)
def test_save_load(self): # Load sample UKV data (variable-resolution rotated grid). path = tests.get_data_path(("PP", "ukV1", "ukVpmslont.pp")) cube = load_cube(path) # Extract a single 2D field, for simplicity. self.assertEqual(cube.ndim, 3) self.assertEqual(cube.coord_dims("time"), (0, )) cube = cube[0] # FOR NOW: **also** fix the data so that it is square, i.e. nx=ny. # This is needed because of a bug in the gribapi. # See : https://software.ecmwf.int/issues/browse/SUP-1096 ny, nx = cube.shape nn = min(nx, ny) cube = cube[:nn, :nn] # Check that it has a rotated-pole variable-spaced grid, as expected. x_coord = cube.coord(axis="x") self.assertIsInstance(x_coord.coord_system, RotatedGeogCS) self.assertFalse(is_regular(x_coord)) # Write to temporary file, check that key contents are in the file, # then load back in. with self.temp_filename("ukv_sample.grib2") as temp_file_path: save(cube, temp_file_path) # Check that various aspects of the saved file are as expected. expect_values = ( (0, "editionNumber", 2), (3, "gridDefinitionTemplateNumber", 5), (3, "Ni", cube.shape[-1]), (3, "Nj", cube.shape[-2]), (3, "shapeOfTheEarth", 1), ( 3, "scaledValueOfRadiusOfSphericalEarth", int(UM_DEFAULT_EARTH_RADIUS), ), (3, "resolutionAndComponentFlags", 0), (3, "latitudeOfSouthernPole", -37500000), (3, "longitudeOfSouthernPole", 357500000), (3, "angleOfRotation", 0), ) self.assertGribMessageContents(temp_file_path, expect_values) # Load the Grib file back into a new cube. cube_loaded_from_saved = load_cube(temp_file_path) # Also load data, before the temporary file gets deleted. cube_loaded_from_saved.data # The re-loaded result will not match the original in every respect: # * cube attributes are discarded # * horizontal coordinates are rounded to an integer representation # * bounds on horizontal coords are lost # Thus the following "equivalence tests" are rather piecemeal.. # Check those re-loaded properties which should match the original. for test_cube in (cube, cube_loaded_from_saved): self.assertEqual(test_cube.standard_name, "air_pressure_at_sea_level") self.assertEqual(test_cube.units, "Pa") self.assertEqual(test_cube.shape, (744, 744)) self.assertEqual(test_cube.cell_methods, ()) # Check only the GRIB_PARAM attribute exists on the re-loaded cube. # Note: this does *not* match the original, but is as expected. self.assertEqual( cube_loaded_from_saved.attributes, {"GRIB_PARAM": GRIBCode("GRIB2:d000c003n001")}, ) # Now remaining to check: coordinates + data... # Check they have all the same coordinates. co_names = [coord.name() for coord in cube.coords()] co_names_reload = [ coord.name() for coord in cube_loaded_from_saved.coords() ] self.assertEqual(sorted(co_names_reload), sorted(co_names)) # Check all the coordinates. for coord_name in co_names: try: co_orig = cube.coord(coord_name) co_load = cube_loaded_from_saved.coord(coord_name) # Check shape. self.assertEqual( co_load.shape, co_orig.shape, 'Shape of re-loaded "{}" coord is {} ' "instead of {}".format(coord_name, co_load.shape, co_orig.shape), ) # Check coordinate points equal, within a tolerance. self.assertArrayAllClose(co_load.points, co_orig.points, rtol=1.0e-6) # Check all coords are unbounded. # (NOTE: this is not so for the original X and Y coordinates, # but Grib does not store those bounds). self.assertIsNone(co_load.bounds) except AssertionError as err: self.assertTrue( False, 'Failed on coordinate "{}" : {}'.format( coord_name, str(err)), ) # Check that main data array also matches. self.assertArrayAllClose(cube.data, cube_loaded_from_saved.data)
def test_create_from_tuple(self): gribcode = GRIBCode((4, 3, 2, 1)) self.assertEqual(gribcode, GRIBCode(4, 3, 2, 1))