def _add_iris_coord(cube, name, points, dim, calendar=None): """ Add a Coord to a Cube from a Pandas index or columns array. If no calendar is specified for a time series, Gregorian is assumed. """ units = Unit("unknown") if calendar is None: calendar = cf_units.CALENDAR_GREGORIAN # Convert pandas datetime objects to python datetime obejcts. if isinstance(points, DatetimeIndex): points = np.array([i.to_datetime() for i in points]) # Convert datetime objects to Iris' current datetime representation. if points.dtype == object: dt_types = (datetime.datetime, netcdftime.datetime) if all([isinstance(i, dt_types) for i in points]): units = Unit("hours since epoch", calendar=calendar) points = units.date2num(points) points = np.array(points) if (np.issubdtype(points.dtype, np.number) and iris.util.monotonic(points, strict=True)): coord = DimCoord(points, units=units) coord.rename(name) cube.add_dim_coord(coord, dim) else: coord = AuxCoord(points, units=units) coord.rename(name) cube.add_aux_coord(coord, dim)
def _add_iris_coord(cube, name, points, dim, calendar=None): """ Add a Coord to a Cube from a Pandas index or columns array. If no calendar is specified for a time series, Gregorian is assumed. """ units = Unit("unknown") if calendar is None: calendar = cf_units.CALENDAR_GREGORIAN # Convert pandas datetime objects to python datetime obejcts. if isinstance(points, DatetimeIndex): points = np.array([i.to_pydatetime() for i in points]) # Convert datetime objects to Iris' current datetime representation. if points.dtype == object: dt_types = (datetime.datetime, cftime.datetime) if all([isinstance(i, dt_types) for i in points]): units = Unit("hours since epoch", calendar=calendar) points = units.date2num(points) points = np.array(points) if (np.issubdtype(points.dtype, np.number) and iris.util.monotonic(points, strict=True)): coord = DimCoord(points, units=units) coord.rename(name) cube.add_dim_coord(coord, dim) else: coord = AuxCoord(points, units=units) coord.rename(name) cube.add_aux_coord(coord, dim)
def _get_coords(ctl): """Get correct coordinates for cube.""" # Time time_units = Unit('days since 1950-1-1 00:00:00', calendar='standard') time_start = datetime.strptime(ctl['t_start'], '%d%b%Y') times = [ _add_months(time_start, d) + timedelta(days=14) for d in int(ctl['t_delta'][0]) * np.arange(ctl['t_size']) ] times = [time_units.date2num(time) for time in times] time_coord = iris.coords.DimCoord(times, standard_name='time', long_name='time', var_name='time', units=time_units) # Latitude lats = float( ctl['y_start']) + (float(ctl['y_delta']) * np.arange(ctl['y_size'])) lat_coord = iris.coords.DimCoord(lats, standard_name='latitude', long_name='latitude', var_name='lat', units='degrees_north') # Longitude lons = float( ctl['x_start']) + (float(ctl['x_delta']) * np.arange(ctl['x_size'])) lon_coord = iris.coords.DimCoord(lons, standard_name='longitude', long_name='longitude', var_name='lon', units='degrees_east') return [(time_coord, 0), (lat_coord, 1), (lon_coord, 2)]
def _create_frt_type_coord( cube: Cube, point: datetime, name: str = "forecast_reference_time" ) -> DimCoord: """Create a new auxiliary coordinate based on forecast reference time Args: cube: Input cube with scalar forecast reference time coordinate points Single datetime point for output coord name Name of aux coord to be returned Returns: New auxiliary coordinate """ frt_coord_name = "forecast_reference_time" coord_type_spec = TIME_COORDS[frt_coord_name] coord_units = Unit(coord_type_spec.units) new_points = round_close([coord_units.date2num(point)], dtype=coord_type_spec.dtype) try: new_coord = DimCoord(new_points, standard_name=name, units=coord_units) except ValueError: new_coord = DimCoord(new_points, long_name=name, units=coord_units) return new_coord
def _get_coords(year, filename, cfg): """Get correct coordinates for cube.""" filename = os.path.basename(filename) time_units = Unit('days since 1950-1-1 00:00:00', calendar='standard') # Extract date from filename time_str = filename.replace(cfg['binary_prefix'], '') month = MONTHS[time_str[4:7]] day = DAYS[time_str[7:8]] date = datetime(year, month, day) # Build time coordinate time_data = [time_units.date2num(date)] time_coord = iris.coords.DimCoord(time_data, standard_name='time', long_name='time', var_name='time', units=time_units) # Build latitude/Longitude coordinates latitude_data = np.linspace(UPPER_LEFT_LAT, LOWER_RIGHT_LAT, N_LAT) longitude_data = np.linspace(UPPER_LEFT_LON, LOWER_RIGHT_LON, N_LON) lat_coord = iris.coords.DimCoord(latitude_data, standard_name='latitude', long_name='latitude', var_name='lat', units='degrees') lon_coord = iris.coords.DimCoord(longitude_data, standard_name='longitude', long_name='longitude', var_name='lon', units='degrees') return [(time_coord, 0), (lat_coord, 1), (lon_coord, 2)]
def _fix_time_coord(cube): """Set time points to central day of month.""" time_coord = cube.coord('time') new_unit = Unit('days since 1850-01-01 00:00:00', calendar='standard') time_coord.convert_units(new_unit) old_time = new_unit.num2date(time_coord.points) new_time = [d.replace(day=15) for d in old_time] time_coord.points = new_unit.date2num(new_time)
def _convert_datetime_to_coord_unit(coord, dt): """Converts a datetime to be in the unit of a specified Coord. """ if isinstance(coord, iris.coords.Coord): # The unit class is then cf_units.Unit. iris_unit = coord.units else: iris_unit = Unit(coord.units) return iris_unit.date2num(dt)
def unify_forecast_reference_time(cubes, cycletime): """Function to unify the forecast_reference_time across the input cubes provided. The cycletime specified is used as the forecast_reference_time. This function is intended for use in grid blending, where the models being blended may not have been run at the same cycle time, but should be given the same forecast period weightings. Args: cubes (iris.cube.CubeList or iris.cube.Cube): Cubes that will have their forecast_reference_time unified. If a single cube is provided the forecast_reference_time will be updated. Any bounds on the forecast_reference_time coord will be discarded. cycletime (datetime.datetime): Datetime for the cycletime that will be used to replace the forecast_reference_time on the individual cubes. Returns: result_cubes (iris.cube.CubeList): Cubes that have had their forecast_reference_time unified. Raises: ValueError: if forecast_reference_time is a dimension coordinate """ if isinstance(cubes, iris.cube.Cube): cubes = iris.cube.CubeList([cubes]) result_cubes = iris.cube.CubeList([]) for cube in cubes: frt_units = cube.coord('forecast_reference_time').units frt_type = cube.coord('forecast_reference_time').dtype new_frt_units = Unit('seconds since 1970-01-01 00:00:00') frt_points = np.round([new_frt_units.date2num(cycletime) ]).astype(frt_type) frt_coord = build_coordinate( frt_points, standard_name="forecast_reference_time", bounds=None, template_coord=cube.coord('forecast_reference_time'), units=new_frt_units) frt_coord.convert_units(frt_units) frt_coord.points = frt_coord.points.astype(frt_type) cube.remove_coord("forecast_reference_time") cube.add_aux_coord(frt_coord, data_dims=None) # If a forecast period coordinate already exists on a cube, replace # this coordinate, otherwise create a new coordinate. fp_units = "seconds" if cube.coords("forecast_period"): fp_units = cube.coord("forecast_period").units cube.remove_coord("forecast_period") fp_coord = forecast_period_coord(cube, force_lead_time_calculation=True, result_units=fp_units) cube.add_aux_coord(fp_coord, data_dims=cube.coord_dims("time")) result_cubes.append(cube) return result_cubes
def _unify_time_coord(cube): """Unify time coordinate of cube.""" if not cube.coords('time', dim_coords=True): return time_coord = cube.coord('time') dates_points = time_coord.units.num2date(time_coord.points) dates_bounds = time_coord.units.num2date(time_coord.bounds) new_units = Unit('days since 1850-01-01 00:00:00') new_time_coord = iris.coords.DimCoord( new_units.date2num(dates_points), bounds=new_units.date2num(dates_bounds), var_name='time', standard_name='time', long_name='time', units=new_units, ) coord_dims = cube.coord_dims('time') cube.remove_coord('time') cube.add_dim_coord(new_time_coord, coord_dims)
def _get_time_coord(year, month): """Get time coordinate.""" point = datetime(year=year, month=month, day=15) bound_low = datetime(year=year, month=month, day=1) if month == 12: month_bound_up = 1 year_bound_up = year + 1 else: month_bound_up = month + 1 year_bound_up = year bound_up = datetime(year=year_bound_up, month=month_bound_up, day=1) time_units = Unit('days since 1950-01-01 00:00:00', calendar='standard') time_coord = iris.coords.DimCoord( time_units.date2num(point), bounds=time_units.date2num([bound_low, bound_up]), var_name='time', standard_name='time', long_name='time', units=time_units, ) return time_coord
def unify_cycletime(cubes, cycletime): """ Function to unify the forecast_reference_time and update forecast_period. The cycletime specified is used as the forecast_reference_time, and the forecast_period is recalculated using the time coordinate and updated forecast_reference_time. Args: cubes (iris.cube.CubeList or list of iris.cube.Cube): Cubes that will have their forecast_reference_time and forecast_period updated. Any bounds on the forecast_reference_time coordinate will be discarded. cycletime (datetime.datetime): Datetime for the cycletime that will be used to replace the forecast_reference_time on the individual cubes. Returns: iris.cube.CubeList: Updated cubes Raises: ValueError: if forecast_reference_time is a dimension coordinate """ result_cubes = iris.cube.CubeList([]) for cube in cubes: cube = cube.copy() frt_units = cube.coord('forecast_reference_time').units frt_type = cube.coord('forecast_reference_time').dtype new_frt_units = Unit(TIME_REFERENCE_UNIT) frt_points = np.round([new_frt_units.date2num(cycletime) ]).astype(frt_type) frt_coord = build_coordinate( frt_points, standard_name="forecast_reference_time", bounds=None, template_coord=cube.coord('forecast_reference_time'), units=new_frt_units) frt_coord.convert_units(frt_units) frt_coord.points = frt_coord.points.astype(frt_type) cube.remove_coord("forecast_reference_time") cube.add_aux_coord(frt_coord, data_dims=None) # Update the forecast period for consistency within each cube if cube.coords("forecast_period"): cube.remove_coord("forecast_period") fp_coord = forecast_period_coord(cube, force_lead_time_calculation=True) cube.add_aux_coord(fp_coord, data_dims=cube.coord_dims("time")) result_cubes.append(cube) return result_cubes
def test_unify_time_coordinates(self): """Test set common calenar.""" cube1 = self.cube1 time1 = cube1.coord('time') t_unit1 = time1.units dates = t_unit1.num2date(time1.points) t_unit2 = Unit('days since 1850-01-01', calendar='gregorian') time2 = t_unit2.date2num(dates) cube2 = self.cube1.copy() cube2.coord('time').points = time2 cube2.coord('time').units = t_unit2 _unify_time_coordinates([cube1, cube2]) self.assertEqual(cube1.coord('time'), cube2.coord('time'))
class Test(tests.IrisGribTest): def setUp(self): self.section = { 'year': 2007, 'month': 1, 'day': 15, 'hour': 0, 'minute': 3, 'second': 0 } self.unit = Unit('hours since epoch', calendar=CALENDAR_GREGORIAN) dt = datetime(self.section['year'], self.section['month'], self.section['day'], self.section['hour'], self.section['minute'], self.section['second']) self.point = self.unit.date2num(dt) def _check(self, section, standard_name=None): expected = DimCoord(self.point, standard_name=standard_name, units=self.unit) # The call being tested. coord = reference_time_coord(section) self.assertEqual(coord, expected) def test_start_of_forecast__0(self): section = deepcopy(self.section) section['significanceOfReferenceTime'] = 0 self._check(section, 'forecast_reference_time') def test_start_of_forecast__1(self): section = deepcopy(self.section) section['significanceOfReferenceTime'] = 1 self._check(section, 'forecast_reference_time') def test_observation_time(self): section = deepcopy(self.section) section['significanceOfReferenceTime'] = 3 self._check(section, 'time') def test_unknown_significance(self): section = deepcopy(self.section) section['significanceOfReferenceTime'] = 5 emsg = 'unsupported significance' with self.assertRaisesRegex(TranslationError, emsg): self._check(section)
def unify_cycletime(cubes, cycletime): """ Function to unify the forecast_reference_time and update forecast_period. The cycletime specified is used as the forecast_reference_time, and the forecast_period is recalculated using the time coordinate and updated forecast_reference_time. Args: cubes (iris.cube.CubeList or list of iris.cube.Cube): Cubes that will have their forecast_reference_time and forecast_period updated. Any bounds on the forecast_reference_time coordinate will be discarded. cycletime (datetime.datetime): Datetime for the cycletime that will be used to replace the forecast_reference_time on the individual cubes. Returns: iris.cube.CubeList: Updated cubes Raises: ValueError: if forecast_reference_time is a dimension coordinate """ result_cubes = iris.cube.CubeList([]) for cube in cubes: cube = cube.copy() frt_coord_name = "forecast_reference_time" coord_type_spec = TIME_COORDS[frt_coord_name] coord_units = Unit(coord_type_spec.units) frt_points = round_close([coord_units.date2num(cycletime)], dtype=coord_type_spec.dtype) frt_coord = cube.coord(frt_coord_name).copy(points=frt_points) cube.remove_coord(frt_coord_name) cube.add_aux_coord(frt_coord, data_dims=None) # Update the forecast period for consistency within each cube if cube.coords("forecast_period"): cube.remove_coord("forecast_period") fp_coord = forecast_period_coord(cube, force_lead_time_calculation=True) cube.add_aux_coord(fp_coord, data_dims=cube.coord_dims("time")) result_cubes.append(cube) return result_cubes
class Test(tests.IrisTest): def setUp(self): self.section = {'year': 2007, 'month': 1, 'day': 15, 'hour': 0, 'minute': 3, 'second': 0} self.unit = Unit('hours since epoch', calendar=CALENDAR_GREGORIAN) dt = datetime(self.section['year'], self.section['month'], self.section['day'], self.section['hour'], self.section['minute'], self.section['second']) self.point = self.unit.date2num(dt) def _check(self, section, standard_name=None): expected = DimCoord(self.point, standard_name=standard_name, units=self.unit) # The call being tested. coord = reference_time_coord(section) self.assertEqual(coord, expected) def test_start_of_forecast_0(self): section = deepcopy(self.section) section['significanceOfReferenceTime'] = 0 self._check(section, 'forecast_reference_time') def test_start_of_forecast_1(self): section = deepcopy(self.section) section['significanceOfReferenceTime'] = 1 self._check(section, 'forecast_reference_time') def test_observation_time(self): section = deepcopy(self.section) section['significanceOfReferenceTime'] = 3 self._check(section, 'time') def test_unknown_significance(self): section = deepcopy(self.section) section['significanceOfReferenceTime'] = 5 emsg = 'unsupported significance' with self.assertRaisesRegexp(TranslationError, emsg): self._check(section)
def timecoord(frequency, calendar='gregorian', offset='days since 1850-01-01', num=3): """Return a time coordinate with the given time points and calendar.""" time_points = range(1, num + 1) if frequency == 'hourly': dates = [datetime(1850, 1, 1, i, 0, 0) for i in time_points] if frequency == 'daily': dates = [datetime(1850, 1, i, 0, 0, 0) for i in time_points] elif frequency == 'monthly': dates = [datetime(1850, i, 15, 0, 0, 0) for i in time_points] elif frequency == 'yearly': dates = [datetime(1850, 7, i, 0, 0, 0) for i in time_points] unit = Unit(offset, calendar=calendar) points = unit.date2num(dates) return iris.coords.DimCoord(points, standard_name='time', units=unit)
def generate_cube_from_dates( dates, calendar='gregorian', offset='days since 1850-01-01', fill_val=1, len_data=3, var_name=None, ): """Generate test cube from list of dates / frequency specification. Parameters ---------- calendar : str or list Date frequency: 'hourly' / 'daily' / 'monthly' / 'yearly' or list of datetimes. offset : str Offset to use fill_val : int Value to fill the data with len_data : int Number of data / time points var_name : str Name of the data variable Returns ------- iris.cube.Cube """ if isinstance(dates, str): time = timecoord(dates, calendar, offset=offset, num=len_data) else: unit = Unit(offset, calendar=calendar) time = iris.coords.DimCoord(unit.date2num(dates), standard_name='time', units=unit) return Cube((fill_val, ) * len_data, dim_coords_and_dims=[(time, 0)], var_name=var_name)
def _get_coords(data_table): """Extract coordinates.""" time_units = Unit('days since 1850-01-01 00:00:00') times = [datetime(year=year, month=6, day=15) for year in data_table.index] time_dim = iris.coords.DimCoord(time_units.date2num(times), var_name='time', standard_name='time', long_name='time', units=time_units) time_dim.guess_bounds() lat_dim = iris.coords.DimCoord([0.0], bounds=[[-90.0, 90.0]], var_name='lat', standard_name='latitude', long_name='latitude', units=Unit('degrees_north')) lon_dim = iris.coords.DimCoord([180.0], bounds=[[0.0, 360.0]], var_name='lon', standard_name='longitude', long_name='longitude', units=Unit('degrees_east')) return [(time_dim, 0), (lat_dim, 1), (lon_dim, 2)]
def test_3d_spot_cube_for_time(self): """Test output with two extra dimensions, one of which is time with forecast_period as an auxiliary coordinate""" data = np.ones((3, 2, 4), dtype=np.float32) time_spec = TIME_COORDS["time"] time_units = Unit(time_spec.units) time_as_dt = [ datetime(2021, 12, 25, 12, 0), datetime(2021, 12, 25, 12, 1) ] time_points = round_close( np.array([time_units.date2num(t) for t in time_as_dt]), dtype=time_spec.dtype, ) time_coord = DimCoord(time_points, units=time_units, standard_name="time") fp_spec = TIME_COORDS["forecast_period"] fp_units = Unit(fp_spec.units) fp_points = np.array([0, 3600], dtype=fp_spec.dtype) fp_coord = AuxCoord(fp_points, units=fp_units, standard_name="forecast_period") result = build_spotdata_cube( data, *self.args, grid_attributes=self.grid_attributes, additional_dims=[time_coord], additional_dims_aux=[[fp_coord]], ) self.assertArrayAlmostEqual(result.data, data) self.assertEqual(result.coord_dims("grid_attributes")[0], 0) self.assertEqual(result.coord_dims("time")[0], 1) self.assertEqual(result.coord_dims("forecast_period")[0], 1)
class Test(tests.IrisTest): def setUp(self): self.section = {"year": 2007, "month": 1, "day": 15, "hour": 0, "minute": 3, "second": 0} self.unit = Unit("hours since epoch", calendar=CALENDAR_GREGORIAN) dt = datetime( self.section["year"], self.section["month"], self.section["day"], self.section["hour"], self.section["minute"], self.section["second"], ) self.point = self.unit.date2num(dt) def _check(self, section, standard_name=None): expected = DimCoord(self.point, standard_name=standard_name, units=self.unit) # The call being tested. coord = reference_time_coord(section) self.assertEqual(coord, expected) def test_start_of_forecast(self): section = deepcopy(self.section) section["significanceOfReferenceTime"] = 1 self._check(section, "forecast_reference_time") def test_observation_time(self): section = deepcopy(self.section) section["significanceOfReferenceTime"] = 3 self._check(section, "time") def test_unknown_significance(self): section = deepcopy(self.section) section["significanceOfReferenceTime"] = 0 emsg = "unsupported significance" with self.assertRaisesRegexp(TranslationError, emsg): self._check(section)
def NAME_to_cube(filenames, callback): """ Returns a generator of cubes given a list of filenames and a callback. """ for filename in filenames: header, column_headings, data_arrays = load_NAME_III(filename) for i, data_array in enumerate(data_arrays): # turn the dictionary of column headers with a list of header # information for each field into a dictionary of headers for just # this field. Ignore the first 4 columns of grid position (data was # located with the data array). field_headings = dict((k, v[i + 4]) for k, v in column_headings.items()) # make an cube cube = iris.cube.Cube(data_array) # define the name and unit name = ('%s %s' % (field_headings['species'], field_headings['quantity'])) name = name.upper().replace(' ', '_') cube.rename(name) # Some units are badly encoded in the file, fix this by putting a # space in between. (if gs is not found, then the string will be # returned unchanged) cube.units = field_headings['unit'].replace('gs', 'g s') # define and add the singular coordinates of the field (flight # level, time etc.) cube.add_aux_coord(icoords.AuxCoord(field_headings['z_level'], long_name='flight_level', units='1')) # define the time unit and use it to serialise the datetime for the # time coordinate time_unit = Unit('hours since epoch', calendar=CALENDAR_GREGORIAN) time_coord = icoords.AuxCoord( time_unit.date2num(field_headings['time']), standard_name='time', units=time_unit) cube.add_aux_coord(time_coord) # build a coordinate system which can be referenced by latitude and # longitude coordinates lat_lon_coord_system = icoord_systems.GeogCS(6371229) # build regular latitude and longitude coordinates which have # bounds start = header['X grid origin'] + header['X grid resolution'] step = header['X grid resolution'] count = header['X grid size'] pts = start + np.arange(count, dtype=np.float32) * step lon_coord = icoords.DimCoord(pts, standard_name='longitude', units='degrees', coord_system=lat_lon_coord_system) lon_coord.guess_bounds() start = header['Y grid origin'] + header['Y grid resolution'] step = header['Y grid resolution'] count = header['Y grid size'] pts = start + np.arange(count, dtype=np.float32) * step lat_coord = icoords.DimCoord(pts, standard_name='latitude', units='degrees', coord_system=lat_lon_coord_system) lat_coord.guess_bounds() # add the latitude and longitude coordinates to the cube, with # mappings to data dimensions cube.add_dim_coord(lat_coord, 0) cube.add_dim_coord(lon_coord, 1) # implement standard iris callback capability. Although callbacks # are not used in this example, the standard mechanism for a custom # loader to implement a callback is shown: cube = iris.io.run_callback(callback, cube, [header, field_headings, data_array], filename) # yield the cube created (the loop will continue when the next() # element is requested) yield cube
class TestCategoriseCoordFunctionForTime: def __init__(self): self.u = Unit('days since 1600-01-01 00:00:00', calendar=CALENDAR_STANDARD) self.points = np.arange(1, 5, 1) self.coord = iris.coords.DimCoord(self.points, units=self.u) self.start = datetime.datetime(2000, 1, 1) self.end = datetime.datetime(2003, 4, 24) self.start = self.u.date2num(self.start) self.end = self.u.date2num(self.end) def setup_func(self): self.__init__() @with_setup(setup_func) def test_categorise_coord_function_time_year_only(self): delta = date_delta_creator(1) result_function = categorise_coord_function(self.start, self.end, delta, True) expected = np.array([self.u.date2num(datetime.datetime(2000, 7, 1, 0, 0, 0)), self.u.date2num(datetime.datetime(2001, 7, 1, 0, 0, 0)), self.u.date2num(datetime.datetime(2002, 7, 1, 0, 0, 0))]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2000, 1, 1, 0, 0, 0))), expected[0]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2001, 3, 3, 0, 0, 0))), expected[1]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2002, 5, 8, 0, 0, 0))), expected[2]) @with_setup(setup_func) def test_categorise_coord_function_time_year_month(self): delta = date_delta_creator(1, 1) result_function = categorise_coord_function(self.start, self.end, delta, True) expected = np.array([self.u.date2num(datetime.datetime(2000, 7, 15, 0, 0, 0)), self.u.date2num(datetime.datetime(2001, 8, 15, 0, 0, 0)), self.u.date2num(datetime.datetime(2002, 9, 15, 0, 0, 0))]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2000, 1, 1, 0, 0, 0))), expected[0]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2001, 3, 3, 0, 0, 0))), expected[1]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2002, 5, 8, 0, 0, 0))), expected[2]) @with_setup(setup_func) def test_categorise_coord_function_with_month_going_past_december(self): start = datetime.datetime(2000, 11, 3) start = self.u.date2num(start) end = datetime.datetime(2004, 11, 3) end = self.u.date2num(end) delta = date_delta_creator(1, 2) result_function = categorise_coord_function(start, end, delta, True) expected = np.array([self.u.date2num(datetime.datetime(2001, 6, 3, 0, 0, 0)), self.u.date2num(datetime.datetime(2002, 8, 3, 0, 0, 0)), self.u.date2num(datetime.datetime(2003, 10, 3, 0, 0, 0))]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(1999, 1, 1, 0, 0, 0))), expected[0]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2001, 3, 3, 0, 0, 0))), expected[0]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2002, 3, 3, 0, 0, 0))), expected[1]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2005, 5, 8, 0, 0, 0))), expected[2]) @with_setup(setup_func) def test_categorise_coord_function_time_year_month_day_hour_minute_second(self): delta = date_delta_creator(1, 3, 2, 4, 5, 6) result_function = categorise_coord_function(self.start, self.end, delta, True) expected = np.array([self.u.date2num(datetime.datetime(2000, 8, 16, 2, 2, 33)), self.u.date2num(datetime.datetime(2001, 11, 18, 6, 7, 39)), self.u.date2num(datetime.datetime(2003, 2, 20, 10, 12, 45))]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2000, 1, 1, 0, 0, 0))), expected[0]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2001, 7, 3, 0, 0, 0))), expected[1]) assert_equal(result_function(self.coord, self.u.date2num(datetime.datetime(2002, 9, 8, 0, 0, 0))), expected[2])
def NAME_to_cube(filenames, callback): """ Returns a generator of cubes given a list of filenames and a callback. """ for filename in filenames: header, column_headings, data_arrays = load_NAME_III(filename) for i, data_array in enumerate(data_arrays): # turn the dictionary of column headers with a list of header # information for each field into a dictionary of headers for just # this field. Ignore the first 4 columns of grid position (data was # located with the data array). field_headings = dict( (k, v[i + 4]) for k, v in column_headings.items()) # make an cube cube = iris.cube.Cube(data_array) # define the name and unit name = "%s %s" % ( field_headings["species"], field_headings["quantity"], ) name = name.upper().replace(" ", "_") cube.rename(name) # Some units are badly encoded in the file, fix this by putting a # space in between. (if gs is not found, then the string will be # returned unchanged) cube.units = field_headings["unit"].replace("gs", "g s") # define and add the singular coordinates of the field (flight # level, time etc.) cube.add_aux_coord( icoords.AuxCoord( field_headings["z_level"], long_name="flight_level", units="1", )) # define the time unit and use it to serialise the datetime for the # time coordinate time_unit = Unit("hours since epoch", calendar=CALENDAR_GREGORIAN) time_coord = icoords.AuxCoord( time_unit.date2num(field_headings["time"]), standard_name="time", units=time_unit, ) cube.add_aux_coord(time_coord) # build a coordinate system which can be referenced by latitude and # longitude coordinates lat_lon_coord_system = icoord_systems.GeogCS(6371229) # build regular latitude and longitude coordinates which have # bounds start = header["X grid origin"] + header["X grid resolution"] step = header["X grid resolution"] count = header["X grid size"] pts = start + np.arange(count, dtype=np.float32) * step lon_coord = icoords.DimCoord( pts, standard_name="longitude", units="degrees", coord_system=lat_lon_coord_system, ) lon_coord.guess_bounds() start = header["Y grid origin"] + header["Y grid resolution"] step = header["Y grid resolution"] count = header["Y grid size"] pts = start + np.arange(count, dtype=np.float32) * step lat_coord = icoords.DimCoord( pts, standard_name="latitude", units="degrees", coord_system=lat_lon_coord_system, ) lat_coord.guess_bounds() # add the latitude and longitude coordinates to the cube, with # mappings to data dimensions cube.add_dim_coord(lat_coord, 0) cube.add_dim_coord(lon_coord, 1) # implement standard iris callback capability. Although callbacks # are not used in this example, the standard mechanism for a custom # loader to implement a callback is shown: cube = iris.io.run_callback(callback, cube, [header, field_headings, data_array], filename) # yield the cube created (the loop will continue when the next() # element is requested) yield cube