예제 #1
0
파일: raster.py 프로젝트: aleaf/gis-utils
def get_transform(xul, yul, dx, dy=None, rotation=0.):
    """Returns an affine.Affine instance that can be
    used to locate raster grids in space. See
    https://www.perrygeo.com/python-affine-transforms.html
    https://rasterio.readthedocs.io/en/stable/topics/migrating-to-v1.html

    Parameters
    ----------
    xul : float
        x-coorindate of upper left corner of raster grid
    yul : float
        y-coorindate of upper left corner of raster grid
    dx : float
        cell spacing in the x-direction
    dy : float
        cell spacing in the y-direction
    rotation :
        rotation of the raster grid in degrees, clockwise
    Returns
    -------
    affine.Affine instance
    """
    if not rasterio:
        raise ModuleNotFoundError(
            'This function requires rasterio. Please conda install rasterio.')
    if dy is None:
        dy = -dx
    return Affine(dx, 0., xul,
                  0., dy, yul) * \
           Affine.rotation(rotation)
예제 #2
0
 def defineSquare(self, x, y, alpha, length):
     transform0 = rasterio.open(self.imgdir + self.imgWithCoords(x, y),
                                'r').transform
     x_ras, y_ras = np.round((~transform0) * (x, y))
     transform1 = transform0 * A.translation(x_ras,
                                             y_ras) * A.rotation(alpha)
     corners = [
         transform1 * (0, 0), transform1 * (length, 0),
         transform1 * (length, length), transform1 * (0, length)
     ]
     return corners
예제 #3
0
 def transform(self):
     """Rasterio-style affine transform object.
     https://www.perrygeo.com/python-affine-transforms.html
     """
     if self.uniform:
         for param in ['dx', 'rotation', 'xul', 'dy', 'yul']:
             if self.__dict__[param] is None:
                 print('This method requires a uniform grid and '
                       'specification of xul, yul, dx, dy, and rotation.')
                 return
         return Affine(self.dx, 0., self.xul,
                       0., -self.dy, self.yul) * Affine.rotation(self.rotation)
예제 #4
0
def test_get_transform():
    dx = 5.
    height = 2
    xll, yll = 0., 0.
    rotation = 30.
    xul = _xll_to_xul(xll, height * dx, rotation)
    yul = _yll_to_yul(yll, height * dx, rotation)
    transform = get_transform(xul=xul,
                              yul=yul,
                              dx=dx,
                              dy=-dx,
                              rotation=rotation)
    transform2 = Affine(dx, 0., xul,
                        0., -dx, yul) * \
                 Affine.rotation(rotation)
    assert transform == transform2
예제 #5
0
    def newImage(self, x, y, alpha, length):
        square = self.defineSquare(x, y, alpha, length)
        imgs = self.imagesFromSquare(square)
        if len(imgs) < 1:
            return 0
        datasets = []
        road_datasets = []
        for filename in imgs:
            datasets.append(rasterio.open(self.imgdir + filename, 'r'))
            road_datasets.append(
                rasterio.open(self.roaddir + self.roadName(filename), 'r'))

        if len(datasets) > 1:
            mergedImages, src_transform = rasterio.merge.merge(datasets)
            mergedRoads = rasterio.merge.merge(road_datasets)[0]
        else:
            mergedImages = datasets[0].read()
            mergedRoads = road_datasets[0].read()
            src_transform = datasets[0].transform

        #define destination transform from the upper left corner of the square
        translationVector = ~src_transform * square[0]
        dst_transform = src_transform * A.translation(
            *translationVector) * A.rotation(alpha)

        dest = np.zeros((mergedImages.shape[0], length, length),
                        mergedImages.dtype)
        road_dest = np.zeros((length, length), mergedRoads.dtype)

        reproject(mergedImages,
                  dest,
                  src_transform=src_transform,
                  src_crs=datasets[0].crs,
                  dst_transform=dst_transform,
                  dst_crs=datasets[0].crs,
                  resampling=Resampling.nearest)

        reproject(mergedRoads,
                  road_dest,
                  src_transform=src_transform,
                  src_crs=datasets[0].crs,
                  dst_transform=dst_transform,
                  dst_crs=datasets[0].crs,
                  resampling=Resampling.nearest)

        return [dest, road_dest, dst_transform]
예제 #6
0
def export_array(modelgrid, filename, a, nodata=-9999,
                 fieldname='value',
                 **kwargs):
    """
    Write a numpy array to Arc Ascii grid or shapefile with the model
    reference.

    Parameters
    ----------
    filename : str
        Path of output file. Export format is determined by
        file extention.
        '.asc'  Arc Ascii grid
        '.tif'  GeoTIFF (requries rasterio package)
        '.shp'  Shapefile
    a : 2D numpy.ndarray
        Array to export
    nodata : scalar
        Value to assign to np.nan entries (default -9999)
    fieldname : str
        Attribute field name for array values (shapefile export only).
        (default 'values')
    kwargs:
        keyword arguments to np.savetxt (ascii)
        rasterio.open (GeoTIFF)
        or flopy.export.shapefile_utils.write_grid_shapefile2

    Notes
    -----
    Rotated grids will be either be unrotated prior to export,
    using scipy.ndimage.rotate (Arc Ascii format) or rotation will be
    included in their transform property (GeoTiff format). In either case
    the pixels will be displayed in the (unrotated) projected geographic
    coordinate system, so the pixels will no longer align exactly with the
    model grid (as displayed from a shapefile, for example). A key difference
    between Arc Ascii and GeoTiff (besides disk usage) is that the
    unrotated Arc Ascii will have a different grid size, whereas the GeoTiff
    will have the same number of rows and pixels as the original.

    """

    if filename.lower().endswith(".asc"):
        if len(np.unique(modelgrid.delr)) != len(np.unique(modelgrid.delc)) != 1 \
                or modelgrid.delr[0] != modelgrid.delc[0]:
            raise ValueError('Arc ascii arrays require a uniform grid.')

        xoffset, yoffset = modelgrid.xoffset, modelgrid.yoffset
        cellsize = modelgrid.delr[0] # * self.length_multiplier
        fmt = kwargs.get('fmt', '%.18e')
        a = a.copy()
        a[np.isnan(a)] = nodata
        if modelgrid.angrot != 0:
            try:
                from scipy.ndimage import rotate
                a = rotate(a, modelgrid.angrot, cval=nodata)
                height_rot, width_rot = a.shape
                xmin, ymin, xmax, ymax = modelgrid.extent
                dx = (xmax - xmin) / width_rot
                dy = (ymax - ymin) / height_rot
                cellsize = np.max((dx, dy))
                xoffset, yoffset = xmin, ymin
            except ImportError:
                print('scipy package required to export rotated grid.')

        filename = '.'.join(
            filename.split('.')[:-1]) + '.asc'  # enforce .asc ending
        nrow, ncol = a.shape
        a[np.isnan(a)] = nodata
        txt = 'ncols  {:d}\n'.format(ncol)
        txt += 'nrows  {:d}\n'.format(nrow)
        txt += 'xllcorner  {:f}\n'.format(xoffset)
        txt += 'yllcorner  {:f}\n'.format(yoffset)
        txt += 'cellsize  {}\n'.format(cellsize)
        # ensure that nodata fmt consistent w values
        txt += 'NODATA_value  {}\n'.format(fmt) % (nodata)
        with open(filename, 'w') as output:
            output.write(txt)
        with open(filename, 'ab') as output:
            np.savetxt(output, a, **kwargs)
        print('wrote {}'.format(filename))

    elif filename.lower().endswith(".tif"):
        if len(np.unique(modelgrid.delr)) != len(np.unique(modelgrid.delc)) != 1 \
                or modelgrid.delr[0] != modelgrid.delc[0]:
            raise ValueError('GeoTIFF export require a uniform grid.')
        try:
            import rasterio
            from rasterio import Affine
        except ImportError:
            print('GeoTIFF export requires the rasterio package.')
            return
        dxdy = modelgrid.delc[0] # * self.length_multiplier
        trans = Affine.translation(modelgrid.xoffset, modelgrid.yoffset) * \
                Affine.rotation(modelgrid.angrot) * \
                Affine.scale(dxdy, -dxdy)

        # third dimension is the number of bands
        a = a.copy()
        if len(a.shape) == 2:
            a = np.reshape(a, (1, a.shape[0], a.shape[1]))
        if a.dtype.name == 'int64':
            a = a.astype('int32')
            dtype = rasterio.int32
        elif a.dtype.name == 'int32':
            dtype = rasterio.int32
        elif a.dtype.name == 'float64':
            dtype = rasterio.float64
        elif a.dtype.name == 'float32':
            dtype = rasterio.float32
        else:
            msg = 'ERROR: invalid dtype "{}"'.format(a.dtype.name)
            raise TypeError(msg)

        meta = {'count': a.shape[0],
                'width': a.shape[2],
                'height': a.shape[1],
                'nodata': nodata,
                'dtype': dtype,
                'driver': 'GTiff',
                'crs': modelgrid.proj4,
                'transform': trans
                }
        meta.update(kwargs)
        with rasterio.open(filename, 'w', **meta) as dst:
            dst.write(a)
        print('wrote {}'.format(filename))

    elif filename.lower().endswith(".shp"):
        from ..export.shapefile_utils import write_grid_shapefile2
        epsg = kwargs.get('epsg', None)
        prj = kwargs.get('prj', None)
        if epsg is None and prj is None:
            epsg = modelgrid.epsg
        write_grid_shapefile2(filename, modelgrid, array_dict={fieldname: a},
                              nan_val=nodata,
                              epsg=epsg, prj=prj)
예제 #7
0
 def transform(self):
     """Rasterio Affine object (same as transform attribute of rasters).
     """
     return Affine(self.delr[0], 0., self.xul,
                   0., -self.delc[0], self.yul) * \
            Affine.rotation(angle=-self.angrot)
예제 #8
0
def get_nearest_point_on_grid(x,
                              y,
                              transform=None,
                              xul=None,
                              yul=None,
                              dx=None,
                              dy=None,
                              rotation=0.,
                              offset='center',
                              op=None):
    """

    Parameters
    ----------
    x : float
        x-coordinate of point
    y : float
        y-coordinate of point
    transform : Affine instance, optional
        Affine object instance describing grid
    xul : float
        x-coordinate of upper left corner of the grid
    yul : float
        y-coordinate of upper left corner of the grid
    dx : float
        grid spacing in the x-direction (along rows)
    dy : float
        grid spacing in the y-direction (along columns)
    rotation : float
        grid rotation about the upper left corner, in degrees clockwise from the x-axis
    offset : str, {'center', 'edge'}
        Whether the point on the grid represents a cell center or corner (edge). This
        argument is only used if xul, yul, dx, dy and rotation are supplied. If
        an Affine transform instance is supplied, it is assumed to already incorporate
        the offset.
    op : function, optional
        Function to convert fractional pixels to whole numbers (np.round, np.floor, np.ceiling).
        Defaults to np.round if offset == 'center'; otherwise defaults to np.floor.



    Returns
    -------
    x_nearest, y_nearest : float
        Coordinates of nearest grid cell center.

    """
    # get the closet (fractional) grid cell location
    # (in case the grid is rotated)
    if transform is None:
        transform = Affine(dx, 0., xul,
                           0., dy, yul) * \
                    Affine.rotation(rotation)
        if offset == 'center':
            transform *= Affine.translation(0.5, 0.5)
    x_raster, y_raster = ~transform * (x, y)

    if offset == 'center':
        op = np.round
    elif op is None:
        op = np.floor

    j = int(op(x_raster))
    i = int(op(y_raster))

    x_nearest, y_nearest = transform * (j, i)
    return x_nearest, y_nearest
예제 #9
0
파일: utils.py 프로젝트: modflowpy/flopy
def export_array(modelgrid, filename, a, nodata=-9999,
                 fieldname='value',
                 **kwargs):
    """Write a numpy array to Arc Ascii grid
    or shapefile with the model reference.
    Parameters
    ----------
    filename : str
        Path of output file. Export format is determined by
        file extention.
        '.asc'  Arc Ascii grid
        '.tif'  GeoTIFF (requries rasterio package)
        '.shp'  Shapefile
    a : 2D numpy.ndarray
        Array to export
    nodata : scalar
        Value to assign to np.nan entries (default -9999)
    fieldname : str
        Attribute field name for array values (shapefile export only).
        (default 'values')
    kwargs:
        keyword arguments to np.savetxt (ascii)
        rasterio.open (GeoTIFF)
        or flopy.export.shapefile_utils.write_grid_shapefile2

    Notes
    -----
    Rotated grids will be either be unrotated prior to export,
    using scipy.ndimage.rotate (Arc Ascii format) or rotation will be
    included in their transform property (GeoTiff format). In either case
    the pixels will be displayed in the (unrotated) projected geographic coordinate system,
    so the pixels will no longer align exactly with the model grid
    (as displayed from a shapefile, for example). A key difference between
    Arc Ascii and GeoTiff (besides disk usage) is that the
    unrotated Arc Ascii will have a different grid size, whereas the GeoTiff
    will have the same number of rows and pixels as the original.
    """

    if filename.lower().endswith(".asc"):
        if len(np.unique(modelgrid.delr)) != len(np.unique(modelgrid.delc)) != 1 \
                or modelgrid.delr[0] != modelgrid.delc[0]:
            raise ValueError('Arc ascii arrays require a uniform grid.')

        xoffset, yoffset = modelgrid.xoffset, modelgrid.yoffset
        cellsize = modelgrid.delr[0] # * self.length_multiplier
        fmt = kwargs.get('fmt', '%.18e')
        a = a.copy()
        a[np.isnan(a)] = nodata
        if modelgrid.angrot != 0:
            try:
                from scipy.ndimage import rotate
                a = rotate(a, modelgrid.angrot, cval=nodata)
                height_rot, width_rot = a.shape
                xmin, ymin, xmax, ymax = modelgrid.extent
                dx = (xmax - xmin) / width_rot
                dy = (ymax - ymin) / height_rot
                cellsize = np.max((dx, dy))
                # cellsize = np.cos(np.radians(self.rotation)) * cellsize
                xoffset, yoffset = xmin, ymin
            except ImportError:
                print('scipy package required to export rotated grid.')
                pass

        filename = '.'.join(
            filename.split('.')[:-1]) + '.asc'  # enforce .asc ending
        nrow, ncol = a.shape
        a[np.isnan(a)] = nodata
        txt = 'ncols  {:d}\n'.format(ncol)
        txt += 'nrows  {:d}\n'.format(nrow)
        txt += 'xllcorner  {:f}\n'.format(xoffset)
        txt += 'yllcorner  {:f}\n'.format(yoffset)
        txt += 'cellsize  {}\n'.format(cellsize)
        # ensure that nodata fmt consistent w values
        txt += 'NODATA_value  {}\n'.format(fmt) % (nodata)
        with open(filename, 'w') as output:
            output.write(txt)
        with open(filename, 'ab') as output:
            np.savetxt(output, a, **kwargs)
        print('wrote {}'.format(filename))

    elif filename.lower().endswith(".tif"):
        if len(np.unique(modelgrid.delr)) != len(np.unique(modelgrid.delc)) != 1 \
                or modelgrid.delr[0] != modelgrid.delc[0]:
            raise ValueError('GeoTIFF export require a uniform grid.')
        try:
            import rasterio
            from rasterio import Affine
        except:
            print('GeoTIFF export requires the rasterio package.')
            return
        dxdy = modelgrid.delc[0] # * self.length_multiplier
        trans = Affine.translation(modelgrid.xoffset, modelgrid.yoffset) * \
                Affine.rotation(modelgrid.angrot) * \
                Affine.scale(dxdy, -dxdy)

        # third dimension is the number of bands
        a = a.copy()
        if len(a.shape) == 2:
            a = np.reshape(a, (1, a.shape[0], a.shape[1]))
        if a.dtype.name == 'int64':
            a = a.astype('int32')
            dtype = rasterio.int32
        elif a.dtype.name == 'int32':
            dtype = rasterio.int32
        elif a.dtype.name == 'float64':
            dtype = rasterio.float64
        elif a.dtype.name == 'float32':
            dtype = rasterio.float32
        else:
            msg = 'ERROR: invalid dtype "{}"'.format(a.dtype.name)
            raise TypeError(msg)

        meta = {'count': a.shape[0],
                'width': a.shape[2],
                'height': a.shape[1],
                'nodata': nodata,
                'dtype': dtype,
                'driver': 'GTiff',
                'crs': modelgrid.proj4,
                'transform': trans
                }
        meta.update(kwargs)
        with rasterio.open(filename, 'w', **meta) as dst:
            dst.write(a)
        print('wrote {}'.format(filename))

    elif filename.lower().endswith(".shp"):
        from ..export.shapefile_utils import write_grid_shapefile2
        epsg = kwargs.get('epsg', None)
        prj = kwargs.get('prj', None)
        if epsg is None and prj is None:
            epsg = modelgrid.epsg
        write_grid_shapefile2(filename, modelgrid, array_dict={fieldname: a},
                              nan_val=nodata,
                              epsg=epsg, prj=prj)