def __init__(self, directory, filename, constraints=None, callback=None, tmp_directory=None): self.directory = directory self.filename = filename self.tmp_directory = tmp_directory or os.path.join(directory, 'tmp') # try to create the temporary directory # if there are other problems (e.g. permissions) except that it already # exists an exception will be raised try: os.makedirs(self.tmp_directory) except OSError: if not os.path.isdir(self.tmp_directory): raise self.cube_list = iris.load(os.path.join(directory, filename), constraints=constraints, callback=callback) self._orig_standard_name = self.cube_list[0].standard_name self._orig_var_name = self.cube_list[0].var_name self._orig_long_name = self.cube_list[0].long_name self.calendar = self.cube_list[0].coord('time').units.calendar self._orig_units = self.cube_list[0].units for ndim, coord in enumerate(self.cube_list[0].dim_coords): if coord.units.is_time_reference(): self._timeaxis = ndim break # save the period of the entire dataset self._orig_period = ( self.cube_list[0].dim_coords[self._timeaxis].units.num2date( self.cube_list[0].dim_coords[self._timeaxis].points[0]), self.cube_list[-1].dim_coords[self._timeaxis].units.num2date( self.cube_list[-1].dim_coords[self._timeaxis].points[-1]) ) # save the geographical extent x = self.cube_list[0].coord(axis="X", dim_coords=True) y = self.cube_list[0].coord(axis="Y", dim_coords=True) # save the coordinate system self._coord_system = x.coord_system.as_cartopy_crs() if not x.has_bounds(): x.guess_bounds() y.guess_bounds() x_edges = np.concatenate((x.bounds[:,0], np.array([x.bounds[-1,-1]]*y.shape[0]), x.bounds[:,-1], np.array([x.bounds[0,0]]*y.shape[0]))) y_edges = np.concatenate((np.array([y.bounds[0,0]]*x.shape[0]), y.bounds[:,0], np.array([y.bounds[-1,-1]]*x.shape[0]), y.bounds[:,-1])) ll_crs = Geodetic() lon_lat_edges = ll_crs.transform_points( x.coord_system.as_cartopy_crs(), x_edges, y_edges)[:,:-1] east, west = max(lon_lat_edges[:,0]), min(lon_lat_edges[:,0]) north, south = max(lon_lat_edges[:,1]), min(lon_lat_edges[:,1]) self._orig_extent = (north, east, south, west) x.bounds = None y.bounds = None
def _extent_constraint(self): """ if Dataset has an extent set return the geographical constraint with at least one extra line/row at the north/south- and west/east-edge, respectively to guarantee a sufficient large extent for interpolating on a smaller grid. Returns: :class:`iris.Constraint` over the x and y axis """ north, east, south, west = self.extent from matplotlib.path import Path poly = Path([[west, south], [east, south], [east, north], [west, north], [west, south]], closed=True) ll_crs = Geodetic() x = self.cube_list[0].coord(axis='X', dim_coords=True) y = self.cube_list[0].coord(axis='Y', dim_coords=True) dx = x.points[1] - x.points[0] dy = y.points[1] - y.points[0] # get the order of the spatial dimensions xdim = 1 ydim = 0 if self.cube_list[0].coord_dims(x) < self.cube_list[0].coord_dims(y): xdim = 0 ydim = 1 xgrid, ygrid = np.meshgrid(x.points, y.points) ll_field = ll_crs.transform_points(self._coord_system, xgrid, ygrid)[:, :, :2] ll_flat = ll_field.reshape((-1, 2)) mask = poly.contains_points(ll_flat).reshape(xgrid.shape) inside_indices = np.where(mask) minx, maxx = inside_indices[xdim].min(), inside_indices[xdim].max() miny, maxy = inside_indices[ydim].min(), inside_indices[ydim].max() west_bound, east_bound = x.points[minx] - dx, x.points[maxx] + dx south_bound, north_bound = y.points[miny] - dy, y.points[maxy] + dy return iris.Constraint( coord_values={ x.standard_name: lambda cell: west_bound <= cell.point <= east_bound, y.standard_name: lambda cell: south_bound <= cell.point <= north_bound })
def _extent_constraint(self): """ if Dataset has an extent set return the geographical constraint with at least one extra line/row at the north/south- and west/east-edge, respectively to guarantee a sufficient large extent for interpolating on a smaller grid. Returns: iris.Constraint over the x and y axis """ north, east, south, west = self.extent from matplotlib.path import Path poly = Path([[west, south], [east, south], [east, north], [west, north], [west,south]], closed=True) ll_crs = Geodetic() x = self.cube_list[0].coord(axis='X', dim_coords=True) y = self.cube_list[0].coord(axis='Y', dim_coords=True) dx = x.points[1] - x.points[0] dy = y.points[1] - y.points[0] # get the order of the spatial dimensions xdim = 1 ydim = 0 if self.cube_list[0].coord_dims(x) < self.cube_list[0].coord_dims(y): xdim = 0 ydim = 1 xgrid, ygrid = np.meshgrid(x.points, y.points) ll_field = ll_crs.transform_points(self._coord_system, xgrid, ygrid)[:,:,:2] ll_flat = ll_field.reshape((-1,2)) mask = poly.contains_points(ll_flat).reshape(xgrid.shape) inside_indices = np.where(mask) minx, maxx = inside_indices[xdim].min(), inside_indices[xdim].max() miny, maxy = inside_indices[ydim].min(), inside_indices[ydim].max() west_bound, east_bound = x.points[minx]-dx, x.points[maxx]+dx south_bound, north_bound = y.points[miny]-dy, y.points[maxy]+dy return iris.Constraint(coord_values={ x.standard_name: lambda cell: west_bound <= cell.point <= east_bound, y.standard_name: lambda cell: south_bound <= cell.point <= north_bound })
def __init__(self, directory, filename, constraints=None, callback=None): """ Args: * directory (str): path to the data * filename (str): glob pattern of data files Kwargs: * constraints (:class:`iris.Constraint`): any valid constraint on the data * callback (callable): a function to add metadata to the cube | *function signature*: (cube, field, filename) """ from cartopy.crs import Geodetic self.directory = directory self.filename = filename self.cube_list = iris.load(os.path.join(directory, filename), constraints=constraints, callback=callback) self._orig_standard_name = self.cube_list[0].standard_name self._orig_var_name = self.cube_list[0].var_name self._orig_long_name = self.cube_list[0].long_name self.calendar = self.cube_list[0].coord('time').units.calendar self._orig_units = self.cube_list[0].units for ndim, coord in enumerate(self.cube_list[0].dim_coords): if coord.units.is_time_reference(): self._timeaxis = ndim break # save the period of the entire dataset self._orig_period = ( self.cube_list[0].dim_coords[self._timeaxis].units.num2date( self.cube_list[0].dim_coords[self._timeaxis].points[0]), self.cube_list[-1].dim_coords[self._timeaxis].units.num2date( self.cube_list[-1].dim_coords[self._timeaxis].points[-1] + np.diff(self.cube_list[-1].dim_coords[ self._timeaxis].points)[-1])) # save the geographical extent x = self.cube_list[0].coord(axis="X", dim_coords=True) y = self.cube_list[0].coord(axis="Y", dim_coords=True) # save the coordinate system self._coord_system = x.coord_system.as_cartopy_crs() # make a bounding box in lon/lat # if the dataset consists only of one cell/row/column draw a large # box around it remove_bounds = False if not x.has_bounds(): remove_bounds = True try: x.guess_bounds() except ValueError: x.bounds = np.repeat(x.points, 2) + np.array([-1, 1]) * 30000 try: y.guess_bounds() except ValueError: y.bounds = np.repeat(y.points, 2) + np.array([-1, 1]) * 30000 x_edges = np.concatenate( (x.bounds[:, 0], np.array([x.bounds[-1, -1]] * y.shape[0]), x.bounds[:, -1], np.array([x.bounds[0, 0]] * y.shape[0]))) y_edges = np.concatenate( (np.array([y.bounds[0, 0]] * x.shape[0]), y.bounds[:, 0], np.array([y.bounds[-1, -1]] * x.shape[0]), y.bounds[:, -1])) ll_crs = Geodetic() lon_lat_edges = ll_crs.transform_points( x.coord_system.as_cartopy_crs(), x_edges, y_edges)[:, :-1] east, west = max(lon_lat_edges[:, 0]), min(lon_lat_edges[:, 0]) north, south = max(lon_lat_edges[:, 1]), min(lon_lat_edges[:, 1]) self._orig_extent = (north, east, south, west) if remove_bounds: x.bounds = None y.bounds = None # set the initial temporal and spatial extent self.period = self._orig_period self.extent = self._orig_extent
def __init__(self, directory, filename, constraints=None, callback=None, tmp_directory=None): """ Args: * directory (str): path to the data * filename (str): glob pattern of data files Kwargs: * constraints (:class:`iris.Constraint`): any valid constraint on the data * callback (callable): a function to add metadata to the cube | *function signature*: (cube, field, filename) * tmp_directory (str): path to a write-able directory where intermediate data can be saved defaults to directory/tmp """ from cartopy.crs import Geodetic self.directory = directory self.filename = filename self.tmp_directory = tmp_directory or os.path.join(directory, 'tmp') # try to create the temporary directory # if there are other problems (e.g. permissions) except that it already # exists an exception will be raised try: os.makedirs(self.tmp_directory) except OSError: if not os.path.isdir(self.tmp_directory): raise self.cube_list = iris.load(os.path.join(directory, filename), constraints=constraints, callback=callback) self._orig_standard_name = self.cube_list[0].standard_name self._orig_var_name = self.cube_list[0].var_name self._orig_long_name = self.cube_list[0].long_name self.calendar = self.cube_list[0].coord('time').units.calendar self._orig_units = self.cube_list[0].units for ndim, coord in enumerate(self.cube_list[0].dim_coords): if coord.units.is_time_reference(): self._timeaxis = ndim break # save the period of the entire dataset self._orig_period = ( self.cube_list[0].dim_coords[self._timeaxis].units.num2date( self.cube_list[0].dim_coords[self._timeaxis].points[0]), self.cube_list[-1].dim_coords[self._timeaxis].units.num2date( self.cube_list[-1].dim_coords[self._timeaxis].points[-1] + np.diff( self.cube_list[-1].dim_coords[self._timeaxis].points)[-1] ) ) # save the geographical extent x = self.cube_list[0].coord(axis="X", dim_coords=True) y = self.cube_list[0].coord(axis="Y", dim_coords=True) # Determine source coordinate system if x.coord_system is None: # Assume WGS84 latlon if unspecified warnings.warn('Coordinate system of latitude and longitude ' 'coordinates is not specified. Assuming WGS84 Geodetic.') self._coord_system = iris.coord_systems.GeogCS(semi_major_axis=6378137.0, inverse_flattening=298.257223563).as_cartopy_crs() else: # save the coordinate system self._coord_system = x.coord_system.as_cartopy_crs() remove_bounds = False if not x.has_bounds(): x.guess_bounds() y.guess_bounds() remove_bounds = True x_edges = np.concatenate( (x.bounds[:, 0], np.array([x.bounds[-1, -1]] * y.shape[0]), x.bounds[:, -1], np.array([x.bounds[0, 0]] * y.shape[0]))) y_edges = np.concatenate( (np.array([y.bounds[0, 0]] * x.shape[0]), y.bounds[:, 0], np.array([y.bounds[-1, -1]] * x.shape[0]), y.bounds[:, -1])) ll_crs = Geodetic() lon_lat_edges = ll_crs.transform_points( # x.coord_system.as_cartopy_crs(), x_edges, y_edges)[:, :-1] self._coord_system, x_edges, y_edges)[:, :-1] east, west = max(lon_lat_edges[:, 0]), min(lon_lat_edges[:, 0]) north, south = max(lon_lat_edges[:, 1]), min(lon_lat_edges[:, 1]) self._orig_extent = (north, east, south, west) if remove_bounds: x.bounds = None y.bounds = None