def _cube_to_GridInfo(cube, center=False, resolution=None): # This is a simplified version of an equivalent function/method in PR #26. # It is anticipated that this function will be replaced by the one in PR #26. # # Returns a GridInfo object describing the horizontal grid of the cube. # This may be inherited from code written for the rectilinear regridding scheme. lon, lat = cube.coord(axis="x"), cube.coord(axis="y") # Checks may cover units, coord systems (e.g. rotated pole), contiguous bounds. if cube.coord_system() is None: crs = None else: crs = cube.coord_system().as_cartopy_crs() londim, latdim = len(lon.shape), len(lat.shape) assert londim == latdim assert londim in (1, 2) if londim == 1: # Ensure coords come from a proper grid. assert isinstance(lon, iris.coords.DimCoord) assert isinstance(lat, iris.coords.DimCoord) circular = lon.circular # TODO: perform checks on lat/lon. elif londim == 2: assert cube.coord_dims(lon) == cube.coord_dims(lat) assert lon.is_contiguous() assert lat.is_contiguous() # 2D coords must be AuxCoords, which do not have a circular attribute. circular = False lon_bound_array = lon.contiguous_bounds() lon_bound_array = lon.units.convert(lon_bound_array, Unit("degrees")) lat_bound_array = lat.contiguous_bounds() lat_bound_array = lat.units.convert(lat_bound_array, Unit("degrees")) if resolution is None: grid_info = GridInfo( lon.points, lat.points, lon_bound_array, lat_bound_array, crs=crs, circular=circular, center=center, ) else: grid_info = RefinedGridInfo( lon_bound_array, lat_bound_array, crs=crs, resolution=resolution, ) return grid_info
def _create_cf_grid_mapping(dataset, cube, cf_var): """ Create CF-netCDF grid mapping variable and associated CF-netCDF data variable grid mapping attribute. """ cs = cube.coord_system('HorizontalCS') if cs is not None: if isinstance(cs, iris.coord_systems.LatLonCS): cf_grid_name = 'rotated_latitude_longitude' if cs.has_rotated_pole() else 'latitude_longitude' if cf_grid_name not in dataset.variables: cf_var.grid_mapping = cf_grid_name cf_var_grid = dataset.createVariable(cf_grid_name, np.int32) cf_var_grid.grid_mapping_name = cf_grid_name cf_var_grid.longitude_of_prime_meridian = 0.0 if cs.datum: cf_var_grid.semi_major_axis = cs.datum.semi_major_axis cf_var_grid.semi_minor_axis = cs.datum.semi_minor_axis if cs.has_rotated_pole(): if cs.n_pole: cf_var_grid.grid_north_pole_latitude = cs.n_pole.latitude cf_var_grid.grid_north_pole_longitude = cs.n_pole.longitude cf_var_grid.north_pole_grid_longitude = cs.reference_longitude else: # Reference previously created grid mapping cf_var.grid_mapping = cf_grid_name else: warnings.warn('Unable to represent the horizontal coordinate system. The coordinate system type %r is not yet implemented.' % type(cs))
def _map_common(draw_method_name, arg_func, mode, cube, data, *args, **kwargs): """ Draw the given cube on a map using its points or bounds. "Mode" parameter will switch functionality between POINT or BOUND plotting. """ # get the 2d x and 2d y from the CS if mode == iris.coords.POINT_MODE: x, y = cartography.get_xy_grids(cube) else: try: x, y = cartography.get_xy_contiguous_bounded_grids(cube) # Exception translation. except iris.exceptions.CoordinateMultiDimError: raise ValueError("Could not get XY grid from bounds. " "X or Y coordinate not 1D.") except ValueError: raise ValueError("Could not get XY grid from bounds. " "X or Y coordinate doesn't have 2 bounds " "per point.") # take a copy of the data so that we can make modifications to it data = data.copy() # If we are global, then append the first column of data the array to the # last (and add 360 degrees) NOTE: if it is found that this block of code # is useful in anywhere other than this plotting routine, it may be better # placed in the CS. x_coord = cube.coord(axis="X") if getattr(x_coord, 'circular', False): _, direction = iris.util.monotonic(x_coord.points, return_direction=True) y = np.append(y, y[:, 0:1], axis=1) x = np.append(x, x[:, 0:1] + 360 * direction, axis=1) data = ma.concatenate([data, data[:, 0:1]], axis=1) # Replace non-cartopy subplot/axes with a cartopy alternative. cs = cube.coord_system('CoordSystem') if cs: cartopy_proj = cs.as_cartopy_projection() else: cartopy_proj = cartopy.crs.PlateCarree() ax = _get_cartopy_axes(cartopy_proj) draw_method = getattr(ax, draw_method_name) # Set the "from transform" keyword. # NB. While cartopy doesn't support spherical contours, just use the # projection as the source CRS. assert 'transform' not in kwargs, 'Transform keyword is not allowed.' kwargs['transform'] = cartopy_proj if arg_func is not None: new_args, kwargs = arg_func(x, y, data, *args, **kwargs) else: new_args = (x, y, data) + args # Draw the contour lines/filled contours. return draw_method(*new_args, **kwargs)
def _check_both_conversions(self, cube): lats, lons = iris.analysis.cartography.get_lat_lon_grids(cube) plt.scatter(lons, lats) self.check_graphic() n_pole = cube.coord_system('LatLonCS').n_pole rlons, rlats = iris.analysis.cartography.rotate_pole(lons, lats, n_pole.longitude, n_pole.latitude) plt.scatter(rlons, rlats) self.check_graphic()
def _check_both_conversions(self, cube): rlons, rlats = iris.analysis.cartography.get_xy_grids(cube) rcs = cube.coord_system('RotatedGeogCS') x, y = iris.analysis.cartography.unrotate_pole( rlons, rlats, rcs.grid_north_pole_longitude, rcs.grid_north_pole_latitude) plt.scatter(x, y) self.check_graphic() plt.scatter(rlons, rlats) self.check_graphic()
def default_projection(cube): """ Return the primary map projection for the given cube. Using the returned projection, one can create a cartopy map with:: import matplotlib.pyplot as plt ax = plt.ax(projection=default_projection(cube)) """ # XXX logic seems flawed, but it is what map_setup did... cs = cube.coord_system("CoordSystem") projection = cs.as_cartopy_projection() if cs else None return projection
def _check_both_conversions(self, cube, index): rlons, rlats = iris.analysis.cartography.get_xy_grids(cube) rcs = cube.coord_system('RotatedGeogCS') x, y = iris.analysis.cartography.unrotate_pole( rlons, rlats, rcs.grid_north_pole_longitude, rcs.grid_north_pole_latitude) self.assertDataAlmostEqual( x, ('analysis', 'rotated_pole.{}.x.json'.format(index))) self.assertDataAlmostEqual( y, ('analysis', 'rotated_pole.{}.y.json'.format(index))) self.assertDataAlmostEqual( rlons, ('analysis', 'rotated_pole.{}.rlon.json'.format(index))) self.assertDataAlmostEqual( rlats, ('analysis', 'rotated_pole.{}.rlat.json'.format(index)))
def _check_both_conversions(self, cube, index): rlons, rlats = iris.analysis.cartography.get_xy_grids(cube) rcs = cube.coord_system('RotatedGeogCS') x, y = iris.analysis.cartography.unrotate_pole( rlons, rlats, rcs.grid_north_pole_longitude, rcs.grid_north_pole_latitude) self.assertDataAlmostEqual(x, ('analysis', 'rotated_pole.{}.x.json'.format(index))) self.assertDataAlmostEqual(y, ('analysis', 'rotated_pole.{}.y.json'.format(index))) self.assertDataAlmostEqual(rlons, ('analysis', 'rotated_pole.{}.rlon.json'.format(index))) self.assertDataAlmostEqual(rlats, ('analysis', 'rotated_pole.{}.rlat.json'.format(index)))
def _create_cf_grid_mapping(dataset, cube, cf_var): """ Create CF-netCDF grid mapping variable and associated CF-netCDF data variable grid mapping attribute. """ # TODO: What if there's more than one CoordSystem? cs = cube.coord_system('CoordSystem') if cs is not None: # Grid var not yet created? if cs.grid_mapping_name not in dataset.variables: cf_var_grid = dataset.createVariable(cs.grid_mapping_name, np.int32) cf_var_grid.grid_mapping_name = cs.grid_mapping_name # latlon if isinstance(cs, iris.coord_systems.GeogCS): cf_var_grid.longitude_of_prime_meridian = cs.longitude_of_prime_meridian cf_var_grid.semi_major_axis = cs.semi_major_axis cf_var_grid.semi_minor_axis = cs.semi_minor_axis # rotated latlon elif isinstance(cs, iris.coord_systems.RotatedGeogCS): if cs.ellipsoid: cf_var_grid.longitude_of_prime_meridian = cs.ellipsoid.longitude_of_prime_meridian cf_var_grid.semi_major_axis = cs.ellipsoid.semi_major_axis cf_var_grid.semi_minor_axis = cs.ellipsoid.semi_minor_axis cf_var_grid.grid_north_pole_latitude = cs.grid_north_pole_latitude cf_var_grid.grid_north_pole_longitude = cs.grid_north_pole_longitude cf_var_grid.north_pole_grid_longitude = cs.north_pole_grid_longitude # tmerc elif isinstance(cs, iris.coord_systems.TransverseMercator): warnings.warn('TransverseMercator coordinate system not yet handled') # osgb (a specific tmerc) elif isinstance(cs, iris.coord_systems.OSGB): warnings.warn('OSGB coordinate system not yet handled') # other else: warnings.warn('Unable to represent the horizontal coordinate system. The coordinate system type %r is not yet implemented.' % type(cs)) # Refer to grid var cf_var.grid_mapping = cs.grid_mapping_name
def _create_cf_grid_mapping(self, cube, cf_var_cube): """ Create CF-netCDF grid mapping variable and associated CF-netCDF data variable grid mapping attribute. Args: * cube (:class:`iris.cube.Cube`) or cubelist (:class:`iris.cube.CubeList`): A :class:`iris.cube.Cube`, :class:`iris.cube.CubeList` or list of cubes to be saved to a netCDF file. * cf_var_cube (:class:`netcdf.netcdf_variable`): cf variable cube representation. Returns: None """ cs = cube.coord_system('CoordSystem') if cs is not None: # Grid var not yet created? if cs not in self._coord_systems: while cs.grid_mapping_name in self._dataset.variables: cs.grid_mapping_name = ( self._increment_name(cs.grid_mapping_name)) cf_var_grid = self._dataset.createVariable( cs.grid_mapping_name, np.int32) cf_var_grid.grid_mapping_name = cs.grid_mapping_name # latlon if isinstance(cs, iris.coord_systems.GeogCS): cf_var_grid.longitude_of_prime_meridian = ( cs.longitude_of_prime_meridian) cf_var_grid.semi_major_axis = cs.semi_major_axis cf_var_grid.semi_minor_axis = cs.semi_minor_axis # rotated latlon elif isinstance(cs, iris.coord_systems.RotatedGeogCS): if cs.ellipsoid: cf_var_grid.longitude_of_prime_meridian = ( cs.ellipsoid.longitude_of_prime_meridian) cf_var_grid.semi_major_axis = ( cs.ellipsoid.semi_major_axis) cf_var_grid.semi_minor_axis = ( cs.ellipsoid.semi_minor_axis) cf_var_grid.grid_north_pole_latitude = ( cs.grid_north_pole_latitude) cf_var_grid.grid_north_pole_longitude = ( cs.grid_north_pole_longitude) cf_var_grid.north_pole_grid_longitude = ( cs.north_pole_grid_longitude) # tmerc elif isinstance(cs, iris.coord_systems.TransverseMercator): warnings.warn('TransverseMercator coordinate system not ' 'yet handled') # osgb (a specific tmerc) elif isinstance(cs, iris.coord_systems.OSGB): warnings.warn('OSGB coordinate system not yet handled') # other else: warnings.warn('Unable to represent the horizontal ' 'coordinate system. The coordinate system ' 'type %r is not yet implemented.' % type(cs)) self._coord_systems.append(cs) # Refer to grid var cf_var_cube.grid_mapping = cs.grid_mapping_name