Example #1
0
    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
Example #2
0
    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
            })
Example #3
0
    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
        })
Example #4
0
    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
Example #5
0
    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