def write_cross_reference_module(module_path, xrefs): gen_helpers.prep_module_file(module_path) with open(module_path, "a") as module_file: module_file.write(HEADER) module_file.write(CODE_PREAMBLE) module_file.write("STASH_TRANS = {\n") for xref in xrefs: stash = xref.get("stash") try: STASH.from_msi(stash.replace('"', "")) except ValueError: msg = "stash code is not of a recognised" '"m??s??i???" form: {}'.format(stash) print msg grid = xref.get("grid") if grid is not None: try: int(grid) except ValueError: msg = "grid code retrieved from STASH lookup" "is not an interger: {}".format(grid) print msg else: grid = 0 lbfc = xref.get("lbfcn") try: int(lbfc) except (ValueError, TypeError): lbfc = 0 module_file.write(' "{}": Stash({}, {}),\n'.format(stash, grid, lbfc)) module_file.write("}\n")
def write_cross_reference_module(module_path, xrefs): gen_helpers.prep_module_file(module_path) with open(module_path, 'a') as module_file: module_file.write(HEADER) module_file.write(CODE_PREAMBLE) module_file.write('STASH_TRANS = {\n') for xref in xrefs: stash = xref.get('stash') try: STASH.from_msi(stash.replace('"', '')) except ValueError: msg = ('stash code is not of a recognised' '"m??s??i???" form: {}'.format(stash)) print(msg) grid = xref.get('grid') if grid is not None: try: int(grid) except ValueError: msg = ('grid code retrieved from STASH lookup' 'is not an interger: {}'.format(grid)) print(msg) else: grid = 0 lbfc = xref.get('lbfcn') try: int(lbfc) except (ValueError, TypeError): lbfc = 0 module_file.write( ' "{}": Stash({}, {}),\n'.format(stash, grid, lbfc)) module_file.write('}\n')
def write_cross_reference_module(module_path, xrefs): gen_helpers.prep_module_file(module_path) with open(module_path, 'a') as module_file: module_file.write(HEADER) module_file.write(CODE_PREAMBLE) module_file.write('STASH_TRANS = {\n') for xref in xrefs: stash = xref.get('stash') try: STASH.from_msi(stash.replace('"', '')) except ValueError: msg = ('stash code is not of a recognised' '"m??s??i???" form: {}'.format(stash)) print(msg) grid = xref.get('grid') if grid is not None: try: int(grid) except ValueError: msg = ('grid code retrieved from STASH lookup' 'is not an integer: {}'.format(grid)) print(msg) else: grid = 0 lbfc = _value_from_xref(xref, 'lbfcn') pseudT = _value_from_xref(xref, 'pseudT') module_file.write(' "{}": Stash({}, {}, {}),\n'.format( stash, grid, lbfc, pseudT)) module_file.write('}\n')
def test_double_stash(self): stcube236 = mock.Mock(stash=STASH.from_msi('m01s03i236')) stcube4 = mock.Mock(stash=STASH.from_msi('m01s00i004')) stcube7 = mock.Mock(stash=STASH.from_msi('m01s00i007')) constraints = [iris.AttributeConstraint(STASH='m01s03i236'), iris.AttributeConstraint(STASH='m01s00i004')] pp_filter = _convert_constraints(constraints) self.assertTrue(pp_filter(stcube236)) self.assertTrue(pp_filter(stcube4)) self.assertFalse(pp_filter(stcube7))
def test_callable_stash(self): stcube236 = mock.Mock(stash=STASH.from_msi('m01s03i236')) stcube4 = mock.Mock(stash=STASH.from_msi('m01s00i004')) stcube7 = mock.Mock(stash=STASH.from_msi('m01s00i007')) con1 = iris.AttributeConstraint(STASH=lambda s: s.endswith("004")) con2 = iris.AttributeConstraint(STASH=lambda s: s == "m01s00i007") constraints = [con1, con2] pp_filter = _convert_constraints(constraints) self.assertFalse(pp_filter(stcube236)) self.assertTrue(pp_filter(stcube4)) self.assertTrue(pp_filter(stcube7))
def test_summary_stash(self): self.cubes[0].attributes["STASH"] = STASH.from_msi("m01s00i004") expected = ( "0: m01s00i004 / (unknown) " " (latitude: 3; longitude: 4)" ) self.assertEqual(str(self.cubes), expected)
def _check_potm(self, lbcode, expect_match=True): lbvc = 19 blev = 130.6 stash = STASH(1, 1, 1) lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \ None, None, None, None, None, None coords_and_dims, factories = _convert_scalar_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev) if expect_match: expect_result = [ (DimCoord([blev], standard_name='air_potential_temperature', units='K', attributes={'positive': 'up'}), None) ] else: expect_result = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def _check_pressure(self, lbcode, expect_match=True): lbvc = 8 blev = 250.3 stash = STASH(1, 1, 1) lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \ None, None, None, None, None, None coords_and_dims, factories = _convert_scalar_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev) if expect_match: expect_result = [(DimCoord([blev], long_name='pressure', units='hPa'), None)] else: expect_result = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def _check_soil_depth(self, lbcode, expect_match=True): lbvc = 6 blev = 0.05 brsvd1, brlev = 0, 0.1 stash = STASH(1, 1, 1) lblev, bhlev, bhrlev, brsvd2 = None, None, None, None coords_and_dims, factories = _convert_scalar_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev) if expect_match: expect_result = [(DimCoord([blev], standard_name='depth', units='m', bounds=[[brsvd1, brlev]], attributes={'positive': 'down'}), None)] else: expect_result = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def _check_soil_level(self, lbcode, expect_match=True): lbvc = 6 lblev = 12.3 brsvd1, brlev = 0, 0 stash = STASH(1, 1, 1) blev, bhlev, bhrlev, brsvd2 = None, None, None, None coords_and_dims, factories = _convert_scalar_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev) if expect_match: expect_result = [(DimCoord([lblev], long_name='soil_model_level_number', attributes={'positive': 'down'}), None)] else: expect_result = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def _check_soil_depth(self, lbcode, blev=0.05, brsvd1=0, brlev=0.1, expect_match=True, dim=None): lbvc = 6 stash = STASH(1, 1, 1) lblev, bhlev, bhrlev, brsvd2 = None, None, None, None coords_and_dims, factories = _convert_vertical_coords(lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev, dim=dim) expect_result = [] if expect_match: coord = DimCoord(blev, standard_name='depth', bounds=np.vstack((brsvd1, brlev)).T, units='m', attributes={'positive': 'down'}) expect_result = [(coord, dim)] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def _check(self, lblev=37.0, blev=9596.3, brlev=9500.0, brsvd1=9800.0, bhlev=0.35, bhrlev=0.31, brsvd2=0.39, dim=None): lbvc = 65 lbcode = _lbcode(0) # unused stash = STASH(1, 1, 1) # unused coords_and_dims, factories = _convert_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev, dim=dim) expect_coords_and_dims = [ (DimCoord(lblev, standard_name='model_level_number', attributes={'positive': 'up'}), dim)] brlev = np.atleast_1d(brlev) brsvd1 = np.atleast_1d(brsvd1) expect_coords_and_dims.append( (DimCoord(blev, long_name='level_height', units='m', bounds=np.vstack((brlev, brsvd1)).T, attributes={'positive': 'up'}), dim)) bhrlev = np.atleast_1d(bhrlev) brsvd2 = np.atleast_1d(brsvd2) expect_coords_and_dims.append( (AuxCoord(bhlev, long_name='sigma', bounds=np.vstack((bhrlev, brsvd2)).T), dim)) expect_factories = [(HybridHeightFactory, [{'long_name': 'level_height'}, {'long_name': 'sigma'}, Reference('orography')])] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_coords_and_dims) self.assertEqual(factories, expect_factories)
def test_implied_height_1m5(self): self._check_height( blev=75.2, stash=STASH(1, 3, 236), expect_normal=False, expect_fixed_height=1.5, )
def test_unknown_lbvc(self): lbvc = 999 blev, lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = ( None, None, None, None, None, None, None, ) lbcode = _lbcode(0) # unused stash = STASH(1, 1, 1) # unused coords_and_dims, factories = _convert_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev, ) self.assertEqual(coords_and_dims, []) self.assertEqual(factories, [])
def _check_soil_level(self, lbcode, lblev=12.3, expect_match=True, dim=None): lbvc = 6 stash = STASH(1, 1, 1) brsvd1, brlev = 0, 0 if hasattr(lblev, "__iter__"): brsvd1 = [0] * len(lblev) brlev = [0] * len(lblev) blev, bhlev, bhrlev, brsvd2 = None, None, None, None coords_and_dims, factories = _convert_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev, dim=dim, ) expect_result = [] if expect_match: coord = DimCoord( lblev, long_name="soil_model_level_number", attributes={"positive": "down"}, ) expect_result = [(coord, dim)] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def test_normal_height__absent_mixed_vector(self): data = [-1, 12.3, -1, 123.4] dim = 2 for blev in [data, np.asarray(data)]: for dim_i in [dim, (dim,)]: self._check_height(blev=blev, stash=STASH(1, 1, 1), expect_normal=False, dim=dim_i)
def _check_pressure(self, lbcode, blev=250.3, expect_match=True, dim=None): lbvc = 8 stash = STASH(1, 1, 1) lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = ( None, None, None, None, None, None, ) coords_and_dims, factories = _convert_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev, dim=dim, ) if expect_match: expect_result = [(DimCoord(blev, long_name="pressure", units="hPa"), dim)] else: expect_result = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def test_implied_height_10m(self): self._check_height( blev=75.2, stash=STASH(1, 3, 225), expect_normal=False, expect_fixed_height=10.0, )
def test_implied_height_1m5__vector(self): data = [1, 2, 3, 4] dim = 3 for blev in [data, np.asarray(data)]: for dim_i in [dim, (dim,)]: self._check_height(blev=blev, stash=STASH(1, 3, 236), expect_normal=False, expect_fixed_height=1.5, dim=dim_i)
def test_implied_height_10m__vector(self): data = list(range(10)) dim = 4 for blev in [data, np.asarray(data)]: for dim_i in [dim, (dim,)]: self._check_height(blev=blev, stash=STASH(1, 3, 225), expect_normal=False, expect_fixed_height=10.0, dim=dim_i)
def test_no_std_name(self): lbuser = [1, 0, 0, 0, 0, 0, 0] lbfc = 0 stash = STASH(lbuser[6], lbuser[3] // 1000, lbuser[3] % 1000) field = _mock_field(lbuser=lbuser, lbfc=lbfc, stash=stash) (factories, references, standard_name, long_name, units, attributes, cell_methods, dim_coords_and_dims, aux_coords_and_dims) = convert(field) self.assertIsNone(standard_name) self.assertIsNone(units)
def test_fc_cf_air_temp(self): lbuser = [1, 0, 0, 0, 0, 0, 0] lbfc = 16 stash = STASH(lbuser[6], lbuser[3] // 1000, lbuser[3] % 1000) field = _mock_field(lbuser=lbuser, lbfc=lbfc, stash=stash) (factories, references, standard_name, long_name, units, attributes, cell_methods, dim_coords_and_dims, aux_coords_and_dims) = convert(field) self.assertEqual(standard_name, 'air_temperature') self.assertEqual(units, 'K')
def write_cross_reference_module(module_path, xrefs): gen_helpers.prep_module_file(module_path) with open(module_path, 'a') as module_file: module_file.write(HEADER) module_file.write('STASH_GRID = {\n') for xref in xrefs: stash = xref.get('stash') try: STASH.from_msi(stash) except ValueError: msg = ('stash code is not of a recognised' '"m??s??i???" form: {}'.format(stash)) grid = xref.get('grid') try: int(grid) except ValueError: msg = ('grid code retrieved from STASH lookup' 'is not an interger: {}'.format(grid)) module_file.write(" {}: {},\n".format(stash, grid)) module_file.write('}\n')
def _check_depth(self, lbcode, lblev=23.0, blev=123.4, brlev=0.0, brsvd1=0.0, expect_bounds=True, expect_match=True, expect_mixed=False, dim=None): lbvc = 2 stash = STASH(1, 1, 1) bhlev, bhrlev, brsvd2 = None, None, None coords_and_dims, factories = _convert_vertical_coords(lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev, dim=dim) if expect_match: expect_result = [(DimCoord(lblev, standard_name='model_level_number', attributes={'positive': 'down'}), dim)] if expect_bounds: brsvd1 = np.atleast_1d(brsvd1) brlev = np.atleast_1d(brlev) if expect_mixed: lower = np.where(brsvd1 == brlev, blev, brsvd1) upper = np.where(brsvd1 == brlev, blev, brlev) else: lower, upper = brsvd1, brlev bounds = np.vstack((lower, upper)).T expect_result.append((DimCoord(blev, standard_name='depth', units='m', bounds=bounds, attributes={'positive': 'down'}), dim)) else: expect_result.append((DimCoord(blev, standard_name='depth', units='m', attributes={'positive': 'down'}), dim)) else: expect_result = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def _check(self, lblev=37.0, bhlev=850.1, bhrlev=810.0, brsvd2=875.0, blev=0.15, brlev=0.11, brsvd1=0.19, expect_match=True, dim=None): lbvc = 9 lbcode = _lbcode(0) # unused stash = STASH(1, 1, 1) # unused coords_and_dims, factories = _convert_vertical_coords(lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev, dim=dim) expect_coords_and_dims = [(DimCoord(lblev, standard_name='model_level_number', attributes={'positive': 'up'}), dim)] bhrlev = np.atleast_1d(bhrlev) brsvd2 = np.atleast_1d(brsvd2) expect_coords_and_dims.append((DimCoord(bhlev, long_name='level_pressure', units='Pa', bounds=np.vstack( (bhrlev, brsvd2)).T), dim)) brlev = np.atleast_1d(brlev) brsvd1 = np.atleast_1d(brsvd1) expect_coords_and_dims.append((AuxCoord(blev, long_name='sigma', bounds=np.vstack( (brlev, brsvd1)).T), dim)) expect_factories = [(HybridPressureFactory, [{ 'long_name': 'level_pressure' }, { 'long_name': 'sigma' }, Reference('surface_air_pressure')])] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_coords_and_dims) self.assertEqual(factories, expect_factories)
def callback_HadCM2_ts_SAT_ann_18602100_b_pp(cube, field, filename): def reset_pole(coord_name): coord = cube.coord(coord_name) coord.rename(coord.name().replace("grid_", "")) coord.coord_system = coord.coord_system.ellipsoid reset_pole("grid_latitude") reset_pole("grid_longitude") cube.standard_name = "air_temperature" cube.units = "Celsius" cube.attributes["STASH"] = STASH(1, 3, 236) # Force the height to 1.5m if cube.coords("height"): cube.remove_coord("height") height_coord = iris.coords.DimCoord(1.5, standard_name="height", units="m") cube.add_aux_coord(height_coord)
def callback_HadCM2_ts_SAT_ann_18602100_b_pp(cube, field, filename): def reset_pole(coord_name): coord = cube.coord(coord_name) coord.rename(coord.name().replace('grid_', '')) coord.coord_system = coord.coord_system.ellipsoid reset_pole('grid_latitude') reset_pole('grid_longitude') cube.standard_name = 'air_temperature' cube.units = 'Celsius' cube.attributes['STASH'] = STASH(1, 3, 236) # Force the height to 1.5m if cube.coords("height"): cube.remove_coord("height") height_coord = iris.coords.DimCoord(1.5, standard_name='height', units='m') cube.add_aux_coord(height_coord)
def test_valid(self, expect_match=True): lbvc = 65 lblev = 37.0 bhlev = 0.35 # sigma bhrlev, brsvd2 = 0.31, 0.39 # sigma bounds blev = 9596.3 # level_height brlev, brsvd1 = 9500.0, 9800.0 # level_height bounds lbcode = _lbcode(0) # unused stash = STASH(1, 1, 1) # unused coords_and_dims, factories = _convert_scalar_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev) if expect_match: expect_coords_and_dims = [ (DimCoord([37.0], standard_name='model_level_number', attributes={'positive': 'up'}), None), (DimCoord([9596.3], long_name='level_height', units='m', bounds=[brlev, brsvd1], attributes={'positive': 'up'}), None), (AuxCoord([0.35], long_name='sigma', bounds=[bhrlev, brsvd2]), None) ] expect_factories = [(HybridHeightFactory, [{ 'long_name': 'level_height' }, { 'long_name': 'sigma' }, Reference('orography')]) ] else: expect_coords_and_dims = [] expect_factories = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_coords_and_dims) self.assertEqual(factories, expect_factories)
def test_valid(self, expect_match=True): lbvc = 9 lblev = 37.0 bhlev = 850.1 # pressure bhrlev, brsvd2 = 810.0, 875.0 # pressure bounds blev = 0.15 # sigma brlev, brsvd1 = 0.11, 0.19 # sigma bounds lbcode = _lbcode(0) # unused stash = STASH(1, 1, 1) # unused coords_and_dims, factories = _convert_scalar_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev) if expect_match: expect_coords_and_dims = [ (DimCoord([37.0], standard_name='model_level_number', attributes={'positive': 'up'}), None), (DimCoord([850.1], long_name='level_pressure', units='Pa', bounds=[810.0, 875.0]), None), (AuxCoord([0.15], long_name='sigma', bounds=[brlev, brsvd1]), None) ] expect_factories = [(HybridPressureFactory, [{ 'long_name': 'level_pressure' }, { 'long_name': 'sigma' }, Reference('surface_air_pressure')])] else: expect_coords_and_dims = [] expect_factories = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_coords_and_dims) self.assertEqual(factories, expect_factories)
def _check_depth(self, lbcode, lblev, brlev=0.0, brsvd1=0.0, expect_bounds=True, expect_match=True): lbvc = 2 lblev = 23.0 blev = 123.4 stash = STASH(1, 1, 1) bhlev, bhrlev, brsvd2 = None, None, None coords_and_dims, factories = _convert_scalar_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev) if expect_match: expect_result = [(DimCoord([lblev], standard_name='model_level_number', attributes={'positive': 'down'}), None)] if expect_bounds: expect_result.append((DimCoord(blev, standard_name='depth', units='m', bounds=[brsvd1, brlev], attributes={'positive': 'down'}), None)) else: expect_result.append((DimCoord(blev, standard_name='depth', units='m', attributes={'positive': 'down'}), None)) else: expect_result = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def _check_potm(self, lbcode, blev=130.6, expect_match=True, dim=None): lbvc = 19 stash = STASH(1, 1, 1) lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = ( None, None, None, None, None, None, ) coords_and_dims, factories = _convert_vertical_coords( lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash, bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2, brlev=brlev, dim=dim, ) if expect_match: expect_result = [ ( DimCoord( blev, standard_name="air_potential_temperature", units="K", attributes={"positive": "up"}, ), dim, ) ] else: expect_result = [] self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result) self.assertEqual(factories, [])
def callback_model_b_pp(cube, field, filename): cube.standard_name = 'air_temperature' cube.units = 'K' cube.attributes['STASH'] = STASH(1, 16, 203)
def test_summary_stash(self): self.cubes[0].attributes['STASH'] = STASH.from_msi('m01s00i004') expected = ('0: m01s00i004 / (unknown) ' ' (latitude: 3; longitude: 4)') self.assertEqual(str(self.cubes), expected)
def fields(self, c_t=None, cft=None, ctp=None, c_h=None, c_p=None, phn=0, mmm=None, pse=None): # Return a list of 2d cubes representing raw PPFields, from args # specifying sequences of (scalar) coordinate values. # TODO? : add bounds somehow ? # # Arguments 'c<xx>' are either a single int value, making a scalar # coord, or a string of characters : '0'-'9' (index) or '-' (missing). # The indexes select point values from fixed list of possibles. # # Argument 'c_h' and 'c_p' represent height or pressure values, so # ought to be mutually exclusive -- these control LBVC. # # Argument 'phn' indexes phenomenon types. # # Argument 'mmm' denotes existence (or not) of a cell method of type # 'average' or 'min' or 'max' (values '012' respectively), applying to # the time values -- ultimately, this controls LBTIM. # # Argument 'pse' denotes pseudo-level numbers. # These translate into 'LBUSER5' values. # Get the number of result cubes, defined by the 'longest' arg. def arglen(arg): # Get the 'length' of a control argument. if arg is None: result = 0 elif isinstance(arg, six.string_types): result = len(arg) else: result = 1 return result n_flds = max(arglen(x) for x in (c_t, cft, ctp, c_h, c_p, mmm)) # Make basic anonymous test cubes. ny, nx = 3, 5 data = np.arange(n_flds * ny * nx, dtype=np.float32) data = data.reshape((n_flds, ny, nx)) cubes = [Cube(data[i]) for i in range(n_flds)] # Define test point values for making coordinates. time_unit = 'hours since 1970-01-01' period_unit = 'hours' height_unit = 'm' pressure_unit = 'hPa' time_values = 24.0 * np.arange(10) height_values = 100.0 * np.arange(1, 11) pressure_values = [100.0, 150.0, 200.0, 250.0, 300.0, 500.0, 850.0, 1000.0] pseudolevel_values = range(1, 11) # A valid value is >= 1. # Test phenomenon details. # NOTE: in order to write/readback as identical, these also contain a # canonical unit and matching STASH attribute. # Those could in principle be looked up, but it's a bit awkward. phenomenon_values = [ ('air_temperature', 'K', 'm01s01i004'), ('x_wind', 'm s-1', 'm01s00i002'), ('y_wind', 'm s-1', 'm01s00i003'), ('specific_humidity', 'kg kg-1', 'm01s00i010'), ] # Test cell-methods. # NOTE: if you add an *interval* to any of these cell-methods, it is # not saved into the PP file (?? or maybe not loaded back again ??). # This could be a PP save/load bug, or maybe just because no bounds ? cell_method_values = [ CellMethod('mean', 'time'), CellMethod('maximum', 'time'), CellMethod('minimum', 'time'), ] # Define helper to decode an argument as a list of test values. def arg_vals(arg, vals): # Decode an argument to a list of 'n_flds' coordinate point values. # (or 'None' where missing) # First get a list of value indices from the argument. # Can be: a single index value; a list of indices; or a string. if (isinstance(arg, Iterable) and not isinstance(arg, six.string_types)): # Can also just pass a simple iterable of values. inds = [int(val) for val in arg] else: n_vals = arglen(arg) if n_vals == 0: inds = [None] * n_flds elif n_vals == 1: inds = [int(arg)] * n_flds else: assert isinstance(arg, six.string_types) inds = [None if char == '-' else int(char) for char in arg] # Convert indices to selected point values. values = [None if ind is None else vals[int(ind)] for ind in inds] return values # Apply phenomenon_values definitions. phenomena = arg_vals(phn, phenomenon_values) for cube, (name, units, stash) in zip(cubes, phenomena): cube.rename(name) # NOTE: in order to get a cube that will write+readback the same, # the units must be the canonical one. cube.units = units # NOTE: in order to get a cube that will write+readback the same, # we must include a STASH attribute. cube.attributes['STASH'] = STASH.from_msi(stash) # Add x and y coords. cs = GeogCS(EARTH_RADIUS) xvals = np.linspace(0.0, 180.0, nx) co_x = DimCoord(np.array(xvals, dtype=np.float32), standard_name='longitude', units='degrees', coord_system=cs) yvals = np.linspace(-45.0, 45.0, ny) co_y = DimCoord(np.array(yvals, dtype=np.float32), standard_name='latitude', units='degrees', coord_system=cs) for cube in cubes: cube.add_dim_coord(co_y, 0) cube.add_dim_coord(co_x, 1) # Add multiple scalar coordinates as defined by the arguments. def arg_coords(arg, name, unit, vals=None): # Decode an argument to a list of scalar coordinates. if vals is None: vals = np.arange(n_flds + 2) # Note allowance vals = arg_vals(arg, vals) coords = [None if val is None else DimCoord([val], units=unit) for val in vals] # Apply names separately, as 'pressure' is not a standard name. for coord in coords: if coord: coord.rename(name) # Also fix heights to match what comes from a PP file. if name == 'height': coord.attributes['positive'] = 'up' return coords def add_arg_coords(arg, name, unit, vals=None): # Add scalar coordinates to each cube, for one argument. coords = arg_coords(arg, name, unit, vals) for cube, coord in zip(cubes, coords): if coord: cube.add_aux_coord(coord) add_arg_coords(c_t, 'time', time_unit, time_values) add_arg_coords(cft, 'forecast_reference_time', time_unit) add_arg_coords(ctp, 'forecast_period', period_unit, time_values) add_arg_coords(c_h, 'height', height_unit, height_values) add_arg_coords(c_p, 'pressure', pressure_unit, pressure_values) add_arg_coords(pse, 'pseudo_level', '1', pseudolevel_values) # Add cell methods as required. methods = arg_vals(mmm, cell_method_values) for cube, method in zip(cubes, methods): if method: cube.add_cell_method(method) return cubes
def test_stash_object(self): constraint = iris.AttributeConstraint( STASH=STASH.from_msi('m01s03i236')) pp_filter = _convert_constraints(constraint) stcube = mock.Mock(stash=STASH.from_msi('m01s03i236')) self.assertTrue(pp_filter(stcube))
def test_single_stash(self): pp_filter = self._single_stash() stcube = mock.Mock(stash=STASH.from_msi('m01s03i236')) self.assertTrue(pp_filter(stcube))
def test_surface_altitude(self): # Ensure that surface altitude fields are not filtered. pp_filter = self._single_stash() orography_cube = mock.Mock(stash=STASH.from_msi('m01s00i033')) self.assertTrue(pp_filter(orography_cube))
def test_surface_pressure(self): # Ensure that surface pressure fields are not filtered. pp_filter = self._single_stash() pressure_cube = mock.Mock(stash=STASH.from_msi('m01s00i001')) self.assertTrue(pp_filter(pressure_cube))