def _regrid_variable(self, var_cube: Cube, unit: str) -> Cube: """ Sorts spatial coordinates in ascending order, regrids the input variable onto the topography grid and converts to the required units. This function does not modify the input variable cube. Args: var_cube: Cube containing input variable data unit: Required unit for this variable Returns: Cube containing regridded variable data """ for axis in ["x", "y"]: var_cube = sort_coord_in_cube(var_cube, var_cube.coord(axis=axis)) enforce_coordinate_ordering( var_cube, [var_cube.coord(axis="y").name(), var_cube.coord(axis="x").name()]) regridder = iris.analysis.Linear() out_cube = var_cube.regrid(self.topography, regridder) out_cube.data = out_cube.data.astype(np.float32) out_cube.convert_units(unit) return out_cube
def process(self, cube: Cube, input_land: Cube, output_land: Cube) -> Cube: """ Update cube.data so that output_land and sea points match an input_land or sea point respectively so long as one is present within the specified vicinity radius. Note that before calling this plugin the input land mask MUST be checked against the source grid, to ensure the grids match. Args: cube: Cube of data to be updated (on same grid as output_land). input_land: Cube of land_binary_mask data on the grid from which "cube" has been reprojected (it is expected that the iris.analysis.Nearest method would have been used). Land points should be set to one and sea points set to zero. This is used to determine where the input model data is representing land and sea points. output_land: Cube of land_binary_mask data on target grid. Returns: Cube of regridding results. """ # Check cube and output_land are on the same grid: if not spatial_coords_match([cube, output_land]): raise ValueError("X and Y coordinates do not match for cubes {}" "and {}".format(repr(cube), repr(output_land))) self.output_land = output_land # Regrid input_land to output_land grid. self.input_land = input_land.regrid(self.output_land, self.regridder) # Slice over x-y grids for multi-realization data. result = iris.cube.CubeList() # Reset cache as input_land and output_land have changed self._get_matches.cache_clear() for xyslice in cube.slices( [cube.coord(axis="y"), cube.coord(axis="x")]): # Store and copy cube ready for the output data self.nearest_cube = xyslice self.output_cube = self.nearest_cube.copy() # Update sea points that were incorrectly sourced from land points self.correct_where_input_true(0) # Update land points that were incorrectly sourced from sea points self.correct_where_input_true(1) result.append(self.output_cube) result = result.merge_cube() return result
def _regrid_to_target(self, cube: Cube, target_grid: Cube, regridded_title: Optional[str]) -> Cube: """ Regrid cube to target_grid, inherit grid attributes and update title Args: cube: Cube to be regridded target_grid: Data on the target grid. If regridding with mask, this cube should contain land-sea mask data to be used in adjusting land and sea points after regridding. regridded_title: New value for the "title" attribute to be used after regridding. If not set, a default value is used. Returns: Regridded cube with updated attributes """ regridder = Linear(extrapolation_mode=self.extrapolation_mode) if "nearest" in self.regrid_mode: regridder = Nearest(extrapolation_mode=self.extrapolation_mode) cube = cube.regrid(target_grid, regridder) if self.REGRID_REQUIRES_LANDMASK[self.regrid_mode]: cube = self._adjust_landsea(cube, target_grid) # identify grid-describing attributes on source cube that need updating required_grid_attributes = [ attr for attr in cube.attributes if attr in MOSG_GRID_ATTRIBUTES ] # update attributes if available on target grid, otherwise remove for key in required_grid_attributes: if key in target_grid.attributes: cube.attributes[key] = target_grid.attributes[key] else: cube.attributes.pop(key) cube.attributes["title"] = (MANDATORY_ATTRIBUTE_DEFAULTS["title"] if regridded_title is None else regridded_title) return cube
def test(self): # Test that Cube.regrid() just defers to the regridder of the # given scheme. # Define a fake scheme and its associated regridder which just # capture their arguments and return them in place of the # regridded cube. class FakeRegridder(object): def __init__(self, *args): self.args = args def __call__(self, cube): return self.args + (cube,) class FakeScheme(object): def regridder(self, src, target): return FakeRegridder(self, src, target) cube = Cube(0) scheme = FakeScheme() result = cube.regrid(mock.sentinel.TARGET, scheme) self.assertEqual(result, (scheme, cube, mock.sentinel.TARGET, cube))
def _regrid_to_target( self, cube: Cube, target_grid: Cube, regridded_title: Optional[str], regrid_mode: str, ) -> Cube: """ Regrid cube to target_grid, inherit grid attributes and update title Args: cube: Cube to be regridded target_grid: Data on the target grid. If regridding with mask, this cube should contain land-sea mask data to be used in adjusting land and sea points after regridding. regridded_title: New value for the "title" attribute to be used after regridding. If not set, a default value is used. regrid_mode: "bilinear","nearest","nearest-with-mask", "nearest-2","nearest-with-mask-2","bilinear-2","bilinear-with-mask-2" Returns: Regridded cube with updated attributes. """ if regrid_mode in ( "nearest-with-mask", "nearest-with-mask-2", "bilinear-with-mask-2", ): if self.landmask_name not in self.landmask_source_grid.name(): msg = "Expected {} in input_landmask cube but found {}".format( self.landmask_name, repr(self.landmask_source_grid)) warnings.warn(msg) if self.landmask_name not in target_grid.name(): msg = "Expected {} in target_grid cube but found {}".format( self.landmask_name, repr(target_grid)) warnings.warn(msg) # basic categories (1) Iris-based (2) new nearest based (3) new bilinear-based if regrid_mode in ("bilinear", "nearest", "nearest-with-mask"): if "nearest" in regrid_mode: regridder = Nearest(extrapolation_mode=self.extrapolation_mode) else: regridder = Linear(extrapolation_mode=self.extrapolation_mode) cube = cube.regrid(target_grid, regridder) # Iris regridding is used, and then adjust if land_sea mask is considered if self.REGRID_REQUIRES_LANDMASK[regrid_mode]: cube = AdjustLandSeaPoints( vicinity_radius=self.landmask_vicinity, extrapolation_mode=self.extrapolation_mode, )(cube, self.landmask_source_grid, target_grid) # new version of nearest/bilinear option with/without land-sea mask elif regrid_mode in ( "nearest-2", "nearest-with-mask-2", "bilinear-2", "bilinear-with-mask-2", ): cube = RegridWithLandSeaMask( regrid_mode=regrid_mode, vicinity_radius=self.landmask_vicinity)( cube, self.landmask_source_grid, target_grid) # identify grid-describing attributes on source cube that need updating required_grid_attributes = [ attr for attr in cube.attributes if attr in MOSG_GRID_ATTRIBUTES ] # update attributes if available on target grid, otherwise remove for key in required_grid_attributes: if key in target_grid.attributes: cube.attributes[key] = target_grid.attributes[key] else: cube.attributes.pop(key) cube.attributes["title"] = (MANDATORY_ATTRIBUTE_DEFAULTS["title"] if regridded_title is None else regridded_title) return cube
regridded_data_emission = cube2.interpolate([('latitude', lat01), ('longitude', lon01)], iris.analysis.Linear()) print(regridded_data_emission.shape, 'regrid_emission_shape') sum_regridded_emission = np.nansum(np.nansum(np.nansum( regridded_data_emission.data, axis=2), axis=1), axis=0) print(sum_regridded_emission, 'sum_regridded_emission') regridded_data_emission.coord('longitude').guess_bounds() regridded_data_emission.coord('latitude').guess_bounds() scheme = iris.analysis.AreaWeighted(mdtol=1) regridded_data_emission2 = cube2.regrid(regridded_data_emission, scheme) sum_regridded_emission2 = np.nansum(np.nansum(np.nansum( regridded_data_emission2.data, axis=2), axis=1), axis=0) print(sum_regridded_emission2, 'sum_regridded_emission2') lat_n = regridded_data_emission.coord('latitude') #print(lat_n.shape) lat_n = lat_n.points[:] lon_n = regridded_data_emission.coord('longitude') #print(lon_n.shape) lon_n = lon_n.points[:] lat_n_min, lon_n_min = np.nanmin(lat_n), np.nanmin(lon_n)