Beispiel #1
0
    def init_xy(self, lon_min, lat_min, lon_max, lat_max,
                target_cellsize_meters):
        """Create & initialize x/y dimensions/coordinate vars.
        
        Args:
            lon_min: Minimum longitude of domain.
            lat_min: Minimum latitude of domain.
            lon_max: Maximum longitude of domain.
            lat_max: Maximum latitude of domain.
            target_cellsize_meters: Target cell size, in meters. Actual
                calculated cell sizes will be approximations of this.
        """
        # Calculate actual x/y cell sizes
        cellsize_x, cellsize_y = RegularGrid.calc_cellsizes(
            lon_min, lat_min, lon_max, lat_max, target_cellsize_meters)

        # Build a regular grid using calculated cell sizes and given extent
        reg_grid = RegularGrid(lon_min, lat_min, lon_max, lat_max, cellsize_x,
                               cellsize_y)

        # Create NetCDF dimensions & coordinate variables using dimension sizes
        # from regular grid
        self.create_dims_coord_vars(len(reg_grid.y_coords),
                                    len(reg_grid.x_coords))

        # Populate NetCDF coordinate variables using regular grid coordinates
        self.var_x[:] = reg_grid.x_coords[:]
        self.var_y[:] = reg_grid.y_coords[:]
        self.nc_file.gridSpacingLongitude = cellsize_x
        self.nc_file.gridSpacingLatitude = cellsize_y

        return reg_grid
def test_calc_gridpoints(reg_grid_values):
    """Test grid point calculation"""
    reg_grid = RegularGrid(reg_grid_values.lon_min, reg_grid_values.lat_min,
                           reg_grid_values.lon_max, reg_grid_values.lat_max,
                           reg_grid_values.expected_cellsize_x,
                           reg_grid_values.expected_cellsize_y)
    print(f"Calculated x_coords: {reg_grid.x_coords}")
    print(f"Calculated y_coords: {reg_grid.y_coords}")
    assert numpy.allclose(reg_grid.x_coords, reg_grid_values.expected_x_coords)
    assert numpy.allclose(reg_grid.x_coords, reg_grid_values.expected_x_coords)
def test_calc_cellsizes(reg_grid_values):
    """Test cell size calculation"""
    cellsize_x, cellsize_y = RegularGrid.calc_cellsizes(
        reg_grid_values.lon_min, reg_grid_values.lat_min,
        reg_grid_values.lon_max, reg_grid_values.lat_max,
        reg_grid_values.target_cellsize_meters)
    print(f"Calculated cellsize_x: {cellsize_x}")
    print(f"Calculated cellsize_y: {cellsize_y}")

    assert_approx_equal(cellsize_x, reg_grid_values.expected_cellsize_x)
    assert_approx_equal(cellsize_y, reg_grid_values.expected_cellsize_y)
Beispiel #4
0
    def init_xy_with_subsets(self,
                             lon_min,
                             lat_min,
                             lon_max,
                             lat_max,
                             target_cellsize_meters,
                             subset_grid_shp,
                             subset_grid_field_name=None):
        """Create & initialize x/y dimensions/coordinate vars and subset vars.

        Args:
            lon_min: Minimum longitude of domain.
            lat_min: Minimum latitude of domain.
            lon_max: Maximum longitude of domain.
            lat_max: Maximum latitude of domain.
            target_cellsize_meters: Target cell size, in meters. Actual
                calculated cell sizes will be approximations of this.
            subset_grid_shp: Path to subset grid polygon shapefile used to
                define subgrid domains.
            subset_grid_field_name: Optional, default None) Shapefile
                field name to be stored in the index file.

        Raises: Exception when given subset grid shapefile does not exist or
            does not include any grid polygons intersecting with given extent.

        Returns:
            Instance of `RegularGrid` representing the extended generated
            grid whose extent matches the union of all intersecting subset grid
            polygons.
        """
        shp = ogr.Open(subset_grid_shp)
        layer = shp.GetLayer()

        # Create OGR Geometry from ocean model grid extent
        ring = ogr.Geometry(ogr.wkbLinearRing)
        ring.AddPoint(lon_min, lat_max)
        ring.AddPoint(lon_min, lat_min)
        ring.AddPoint(lon_max, lat_min)
        ring.AddPoint(lon_max, lat_max)
        ring.AddPoint(lon_min, lat_max)
        # Create polygon
        ofs_poly = ogr.Geometry(ogr.wkbPolygon)
        ofs_poly.AddGeometry(ring)

        # Get the EPSG value from the import shapefile and transform to WGS84
        spatial_ref = layer.GetSpatialRef()
        shp_srs = spatial_ref.GetAttrValue('AUTHORITY', 1)
        source = osr.SpatialReference()
        source.ImportFromEPSG(int(shp_srs))
        target = osr.SpatialReference()
        target.ImportFromEPSG(4326)
        transform = osr.CoordinateTransformation(source, target)
        ofs_poly.Transform(transform)

        # Find the intersection between grid polygon and ocean model grid extent
        subset_polys = {}
        fids = []
        fields = {}
        fid = 0
        for feature in layer:
            geom = feature.GetGeometryRef()
            if ofs_poly.Intersects(geom):
                subset_polys[fid] = geom.ExportToJson()
                if subset_grid_field_name is not None:
                    field_name = feature.GetField(str(subset_grid_field_name))
                    fields.update({fid: field_name})
                    fids.append(fid)
                else:
                    fids.append(fid)
            fid += 1

        if len(fids) == 0:
            raise Exception(
                'Given subset grid shapefile contains no polygons that intersect with model domain; cannot proceed.'
            )

        # Use a single subset polygon to calculate x/y cell sizes. This ensures
        # that cells do not fall on the border between two grid polygons.
        single_polygon = ogr.Geometry(ogr.wkbMultiPolygon)
        single_polygon.AddGeometry(
            ogr.CreateGeometryFromJson(subset_polys[fids[0]]))
        sp_x_min, sp_x_max, sp_y_min, sp_y_max = single_polygon.GetEnvelope()

        cellsize_x, cellsize_y = RegularGrid.calc_cellsizes(
            sp_x_min, sp_y_min, sp_x_max, sp_y_max, target_cellsize_meters)

        # Combine identified subset grid polygons into single multipolygon to
        # calculate full extent of all combined subset grids
        multipolygon = ogr.Geometry(ogr.wkbMultiPolygon)
        for fid in fids:
            multipolygon.AddGeometry(
                ogr.CreateGeometryFromJson(subset_polys[fid]))

        (x_min, x_max, y_min, y_max) = multipolygon.GetEnvelope()
        full_reg_grid = RegularGrid(x_min, y_min, x_max, y_max, cellsize_x,
                                    cellsize_y)

        # Create NetCDF dimensions & coordinate variables using dimension sizes
        # from regular grid
        self.create_dims_coord_vars(len(full_reg_grid.y_coords),
                                    len(full_reg_grid.x_coords))
        # Populate NetCDF coordinate variables using regular grid coordinates
        self.var_x[:] = full_reg_grid.x_coords[:]
        self.var_y[:] = full_reg_grid.y_coords[:]
        self.nc_file.gridSpacingLongitude = full_reg_grid.cellsize_x
        self.nc_file.gridSpacingLatitude = full_reg_grid.cellsize_y

        # Create subgrid dimension/variables
        self.create_subgrid_dims_vars(len(subset_polys),
                                      subset_grid_field_name)
        # Calculate subgrid mask ranges, populate subgrid ID
        for subgrid_index, fid in enumerate(fids):
            self.var_subgrid_id[subgrid_index] = fid
            if subset_grid_field_name is not None:
                self.var_subgrid_name[subgrid_index] = fields[fid]

            # Convert OGR geometry to shapely geometry
            subset_poly_shape = shape(json.loads(subset_polys[fid]))
            min_x_coord = subset_poly_shape.bounds[0]
            max_x_coord = subset_poly_shape.bounds[2]
            min_y_coord = subset_poly_shape.bounds[1]
            max_y_coord = subset_poly_shape.bounds[3]

            subgrid_x_min = None
            subgrid_x_max = None
            subgrid_y_min = None
            subgrid_y_max = None

            for i, x in enumerate(self.var_x):
                if x >= min_x_coord:
                    subgrid_x_min = i
                    break
            count_x = round(
                ((max_x_coord - min_x_coord) / full_reg_grid.cellsize_x))

            for i, y in enumerate(self.var_y):
                if y >= min_y_coord:
                    subgrid_y_min = i
                    break
            count_y = round(
                ((max_y_coord - min_y_coord) / full_reg_grid.cellsize_y))

            subgrid_x_max = subgrid_x_min + count_x - 1
            subgrid_y_max = subgrid_y_min + count_y - 1

            self.var_subgrid_x_min[subgrid_index] = subgrid_x_min
            self.var_subgrid_x_max[subgrid_index] = subgrid_x_max
            self.var_subgrid_y_min[subgrid_index] = subgrid_y_min
            self.var_subgrid_y_max[subgrid_index] = subgrid_y_max

        return full_reg_grid