def _make_src_affine(src_data_array):
    src_bounds = _get_bounds(src_data_array)
    src_left, src_bottom, src_right, src_top = src_bounds
    src_resolution_x, src_resolution_y = _get_resolution(src_data_array,
                                                         as_tuple=True)
    return Affine.translation(src_left, src_top) * Affine.scale(
        src_resolution_x, src_resolution_y)
示例#2
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)
示例#3
0
def areagrid(outraster, c = 0.083333001, r = 6371007.2, minx = -180, miny = -90, w = 360, h = 180):
    """
    Generates a global grid in geograpic coordinates
    with the area of each gridcell as the value of the cell
    
    Parameters:
        outraster = path to output raster file
        c = cellsize in decimal degrees
        r = radius of earth in desired units (e.g. 6371007.2m for sq. meters)
        minx, miny = the south west coordinate of the raster in degrees
        w, h = the width and height of the raster in degrees
        
    Returns:
        None
    """
    c = float(c)
    r = float(r)

    # make a vector of ones [1,1,1, ... 1] of length equal to the number of cells from west to east.
    X = np.ones(round(w/c))
    # make a vector counting from 0 to the number of cells from south to north. e.g. [0,1,2,...,179] for 1 deg cells.
    Y = np.arange(round(h/c))
    
    # multiply all the numbers in the Y vector by the cell size, 
    # so it extends from 0 to <180 (if the cell size is different than 1 deg)
    # then add the southernmost coordinate (-90deg). This makes a vector of -90 to +90 degrees North
    degN = Y*c + miny
    # convert degrees vector to radians
    radN = degN*np.pi/180.0
    # convert the cell size to radians
    radc = c * np.pi/180.0
    
    # calculate the area of the cell
    # there's some implicit geometry that's been done here already'
    # but basically it averages the width of the top of a cell and the bottom of a cell
    # and mutiplies it by the height of the cell (which is constant no matter how far or south north you are)
    # then by the square of the radius
    # since the angles are in radians it works out area correctly
    # you end up with a vector of cell area from south to north
    A = (np.sin(radN+radc/2)-np.sin(radN-radc/2)) * radc * r**2
    
    # the outer product of any vector and a vector of ones just duplicates the first vector into columns in a matrix
    # basically we just copy the latitude vector across from east to west
    M = np.outer(A,X)
    
    cols = round(w/c)
    rows = round(h/c)
    
    # save the matrix as a raster
    with rasterio.open(outraster,'w',
                       'GTiff',
                       width=cols,
                       height=rows,
                       dtype=M.dtype,
                       crs={'init': 'EPSG:4326'},
                       transform=Affine.translation(-cols*c/2, rows*c/2) * Affine.scale(c, -c),
                       count=1) as dst:
        dst.write_band(1,M)
def data_arrays_resampling_demo():
    """init demo data arrays (2d) and meta data for resampling"""
    data_arrays = list()
    # demo pop:
    data_arrays.append(np.array([[0, 1, 2], [3, 4, 5]], dtype='float32'))
    data_arrays.append(np.array([[0, 1, 2], [3, 4, 5]], dtype='float32'))
    # array([[0, 1, 2],
    #       [3, 4, 5]])
    # demo nightlight:
    data_arrays.append(
        np.array([[2, 10, 0, 0, 0, 0], [10, 2, 10, 0, 0, 0],
                  [0, 0, 0, 0, 1, 1], [1, 0, 0, 0, 1, 1]],
                 dtype='float32'))
    # array([[ 2., 10.,  0.,  0.,  0.,  0.],
    #        [10.,  2., 10.,  0.,  0.,  0.],
    #        [ 0.,  0.,  0.,  0.,  1.,  1.],
    #        [ 1.,  0.,  0.,  0.,  1.,  1.]], dtype=float32)]

    meta_list = [
        {
            'driver': 'GTiff',
            'dtype': 'float32',
            'nodata': -3.4028230607370965e+38,
            'width': 3,
            'height': 2,
            'count': 1,
            'crs': CRS.from_epsg(4326),
            #'crs': CRS.from_epsg(4326),
            'transform': Affine(1, 0.0, -10, 0.0, -1, 40),
        },
        {
            'driver': 'GTiff',
            'dtype': 'float32',
            'nodata': -3.4028230607370965e+38,
            'width': 3,
            'height': 2,
            'count': 1,
            'crs': CRS.from_epsg(4326),
            #'crs': CRS.from_epsg(4326),
            'transform':
            Affine(1, 0.0, -10, 0.0, -1,
                   41),  # shifted by 1 degree latitude to the north
        },
        {
            'driver': 'GTiff',
            'dtype': 'float32',
            'nodata': None,
            'width': 6,
            'height': 4,
            'count': 1,
            'crs': CRS.from_epsg(4326),
            # 'crs': CRS.from_epsg(32662),
            'transform': Affine(.5, 0.0, -10, 0.0, -.5,
                                40),  # higher resolution
        }
    ]
    return data_arrays, meta_list
示例#5
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
示例#6
0
    def _get_affine_transform(self, bounding_box):
        lng1, lng2 = bounding_box.west, bounding_box.east
        lat1, lat2 = bounding_box.south, bounding_box.north
        x_scale = self.google_static_maps.image_w / (lng2 - lng1)
        y_scale = -self.google_static_maps.image_h / (lat2 - lat1)

        affine_translate = Affine.translation(-lng1, -lat2)
        affine_scale = Affine.scale(x_scale, y_scale)
        # affine_mirror = Affine(1, 0, 0, 0, -1, image_h)
        affine_transform = affine_scale * affine_translate
        return affine_transform
示例#7
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)
    def from_dataset(cls, dataset, map_crs='epsg:4326'):
        transform = dataset.transform
        image_crs = None if dataset.crs is None else dataset.crs.wkt

        no_crs_tf = (image_crs is None) or (image_crs == map_crs)
        no_affine_tf = (transform is None) or (transform == Affine.identity())
        if no_crs_tf and no_affine_tf:
            return IdentityCRSTransformer()

        if transform is None:
            transform = Affine.identity()

        return cls(transform, image_crs, map_crs)
示例#9
0
def resample_meta(solar_zenith, solar_azimuth,meta_name, index):
    """
    Resamples Solar Zenith and solar azimuth angle from 5x5 km
    to 10 m Grid (nearest neighbor) and writes into GeoTIFF

    Parameters
    ----------
    solar_zenith: np.array float64
        data in 5km x 5 km grid
    solar_azimuth: np.array float64
        data in 5 km x 5 km grid
    meta_name: str
        Name of .xml file containing metadata
    index: int
        number of current tile (just used for naming convention)


    Returns
    -------
    None
    """
    reference_tile = glob.glob(os.path.join(meta_name[:-10],'IMG_DATA','*_B02.jp2'))[0]

    # Open 10 m resolution tile to read size and dimension of final tile:
    with rasterio.open(reference_tile) as src:
        
        out_meta = src.meta.copy()
        newarr = src.read()
        newarr = np.squeeze(newarr)
        newarr = newarr.astype(float)

        new_transform = src.transform
        old_transform = Affine(new_transform.a * 500, new_transform.b,
                               new_transform.c, new_transform.d,
                               new_transform.e * 500, new_transform.f)
        out_meta['dtype'] = 'float64'
        out_meta['driver'] = "GTiff"

    angles = [solar_zenith, solar_azimuth]
    angles_str = ["solar_zenith.tif", "solar_azimuth.tif"]
    id = 0
    if not os.path.exists(os.path.join(cfg.PATHS['working_dir'], 'cache',
                                       str(cfg.PARAMS['date'][0]), 'meta')):
        os.makedirs(os.path.join(cfg.PATHS['working_dir'], 'cache',
                                 str(cfg.PARAMS['date'][0]), 'meta'))

    for angle in angles:
        with rasterio.open(os.path.join(cfg.PATHS['working_dir'], 'cache',
                                         str(cfg.PARAMS['date'][0]), 'meta',
                                         str(index)+angles_str[id]), "w", **out_meta) \
             as dest:
            reproject(
                     source=angle, destination=newarr,
                     src_transform=old_transform,
                     dst_transform=src.transform,
                     src_crs=src.crs,
                     dst_crs=src.crs,
                     resampling=Resampling.nearest)
            dest.write(newarr, indexes=1)
        id = id + 1
示例#10
0
def main():
    samplefile = r'bxk1-d-ck.idf'
    tiffile = samplefile.replace('.idf', '.geotiff')
    dtype = rasterio.float64
    driver = 'AAIGrid'
    crs = CRS.from_epsg(28992)

    # read data from idf file
    idffile = idfpy.IdfFile(filepath=samplefile, mode='rb')
    geotransform = idffile.geotransform
    height = idffile.header['nrow']
    width = idffile.header['ncol']
    nodata = idffile.header['nodata']
    transform = Affine.from_gdal(*geotransform)

    # write data from idf file to geotiff with rasterio
    profile = {
        'width': width,
        'height': height,
        'count': 1,
        'dtype': dtype,
        'driver': driver,
        'crs': crs,
        'transform': transform,
        'nodata': nodata,
    }

    # the default profile would be sufficient for the example, however the profile dict shows how to make the export
    # profile
    idffile.to_raster(tiffile, **profile)
示例#11
0
def make_affine(height, width, ul, lr):
    """
    Create an affine for a tile of a given size
    """
    xCell = (ul[0] - lr[0]) / width
    yCell = (ul[1] - lr[1]) / height
    return Affine(-xCell, 0.0, ul[0], 0.0, -yCell, ul[1])
示例#12
0
def makeTesting(output, size, windowsize, bands):
    kwargs = {
        'count':
        bands,
        'crs': {
            'init': u'epsg:3857'
        },
        'dtype':
        'uint8',
        'driver':
        u'GTiff',
        'transform':
        Affine(4.595839562240513, 0.0, -13550756.3744, 0.0, -4.595839562240513,
               6315533.02503),
        'height':
        size,
        'width':
        size,
        'compress':
        'lzw',
        'blockxsize':
        windowsize,
        'blockysize':
        windowsize,
        'tiled':
        True
    }

    randArr = np.array([(np.random.rand(size, size) * 255).astype(np.uint8)
                        for i in range(bands)])

    with rasterio.open(output, 'w', **kwargs) as dst:
        dst.write(randArr)
示例#13
0
def resample_raster_dataset(raster, scale):
    t = raster.transform

    # rescale the metadata
    transform = Affine(t.a / scale, t.b, t.c, t.d, t.e / scale, t.f)
    height = int(raster.height * scale)
    width = int(raster.width * scale)

    profile = raster.profile
    profile.update(transform=transform,
                   driver='GTiff',
                   height=height,
                   width=width)

    data = raster.read(  # Note changed order of indexes, arrays are band, row, col order not row, col, band
        out_shape=(raster.count, height, width),
        resampling=Resampling.bilinear,
    )

    with MemoryFile() as memfile:
        with memfile.open(**profile) as dataset:  # Open as DatasetWriter
            dataset.write(data)

        with memfile.open() as dataset:  # Reopen as DatasetReader
            return data, dataset
示例#14
0
def ShapeToArray(inputgeodf, cellsize, valfield=None, fillval=0):
    """Transform vector data into numpy arrays. Locations that vector data presents are valued to 1, otherwise 0.

    :param GeoDataFrame inputgeodf: input GeoDataFrame
    :param int cellsize: cell size used to transform the vector data
    :param string valfield: the field contains values for each cell in the output array
    :param int fillval: fill value for all areas not covered by the input geometries
    :return: numpy array, affine object, and extent of the original vector data
    """
    extent = inputgeodf.total_bounds
    outshape = (int(round((extent[3] - extent[1]) / cellsize)),
                int(round((extent[2] - extent[0]) / cellsize)))
    trans = Affine(cellsize, 0, extent[0], 0, -cellsize, extent[3])
    if valfield is None:
        arr = features.rasterize(inputgeodf[inputgeodf.geometry.name],
                                 out_shape=outshape,
                                 fill=fillval,
                                 transform=trans)
    else:
        arr = features.rasterize(tuple(
            zip(inputgeodf[inputgeodf.geometry.name], inputgeodf[valfield])),
                                 out_shape=outshape,
                                 fill=fillval,
                                 transform=trans)
    return arr, trans, extent
示例#15
0
def _yield_downsampled_raster(raster):
    # https://gis.stackexchange.com/questions/329434/creating-an-in-memory-rasterio-dataset-from-numpy-array/329439#329439
    max_n = np.product(MAX_LOAD_SHAPE)
    n = raster.height * raster.width
    scale = 1.0
    if n > max_n:
        scale = max_n / n

    if scale == 1.0:
        yield raster
        return

    t = raster.transform
    # rescale the metadata
    transform = Affine(t.a / scale, t.b, t.c, t.d, t.e / scale, t.f)
    height = int(raster.height * scale)
    width = int(raster.width * scale)

    profile = raster.profile
    profile.update(transform=transform, height=height, width=width)

    data = raster.read(
        out_shape=(raster.count, height, width),
        resampling=Resampling.bilinear,
    )

    with MemoryFile() as memfile:
        with memfile.open(**profile) as dataset:
            dataset.write(data)
            del data

        with memfile.open() as dataset:  # Reopen as DatasetReader
            yield dataset  # Note yield not return
示例#16
0
 def append(self, centr):
     """ Append raster or points. Raster needs to have the same resolution """
     if self.meta and centr.meta:
         LOGGER.debug('Appending raster')
         if centr.meta['crs'] != self.meta['crs']:
             LOGGER.error('Different CRS not accepted.')
             raise ValueError
         if self.meta['transform'][0] != centr.meta['transform'][0] or \
         self.meta['transform'][4] != centr.meta['transform'][4]:
             LOGGER.error('Different raster resolutions.')
             raise ValueError
         left = min(self.total_bounds[0], centr.total_bounds[0])
         bottom = min(self.total_bounds[1], centr.total_bounds[1])
         right = max(self.total_bounds[2], centr.total_bounds[2])
         top = max(self.total_bounds[3], centr.total_bounds[3])
         crs = self.meta['crs']
         width = (right - left) / self.meta['transform'][0]
         height = (bottom - top) / self.meta['transform'][4]
         self.meta = {'dtype':'float32', 'width':width, 'height':height,
                      'crs':crs, 'transform':Affine(self.meta['transform'][0], \
                      0.0, left, 0.0, self.meta['transform'][4], top)}
     else:
         LOGGER.debug('Appending points')
         if not equal_crs(centr.geometry.crs, self.geometry.crs):
             LOGGER.error('Different CRS not accepted.')
             raise ValueError
         lat = np.append(self.lat, centr.lat)
         lon = np.append(self.lon, centr.lon)
         crs = self.geometry.crs
         self.__init__()
         self.set_lat_lon(lat, lon, crs)
示例#17
0
    def resample(self, dst_res=None, dst_shape=None, interpolation='nearest'):

        transform = self.transform if dst_res is None else Affine(
            dst_res[1], self.transform.b, self.transform.c, self.transform.d,
            -dst_res[0], self.transform.f)

        if dst_res is not None and dst_shape is None:
            target_height = int(self.height * self.res[0] / dst_res[0])
            target_width = int(self.width * self.res[1] / dst_res[1])
        elif dst_shape is not None:
            target_height = dst_shape[1]
            target_width = dst_shape[2]
        else:
            target_height = self.height
            target_width = self.width

        new_raster = np.empty(shape=(1, target_height, target_width),
                              dtype=self.dtype)

        reproject(self._raster,
                  new_raster,
                  src_transform=self.transform,
                  dst_transform=transform,
                  src_crs=self.crs,
                  dst_crs=self.crs,
                  resampling=getattr(Resampling, interpolation))

        return BandSample(self._name, new_raster, self.crs, transform,
                          self.nodata)
示例#18
0
def increase_resolution(raster_file_path: str, factor_increase: int):
    """
    References:
    * mapbox.github.io/rasterio/topics/resampling.html#use-decimated-reads

    :param raster_file_path:
    :param factor_increase:
    :return:
    """
    # this method need a integer factor resolution
    res = int(factor_increase)  # alias
    with rasterio.open(raster_file_path) as src:
        image = src.read()

        image_new = np.empty(
            shape=(
                image.shape[0],  # same number of bands
                round(image.shape[1] * res),  # n times resolution
                round(image.shape[2] * res)),  # n times resolution
            dtype=image.dtype)

        image = src.read(out=image_new).copy()
        meta = dict(src.profile)

    aff = copy(meta['affine'])
    meta['transform'] = Affine(aff.a / res, aff.b, aff.c, aff.d, aff.e / res,
                               aff.f)
    meta['affine'] = meta['transform']
    meta['width'] *= res
    meta['height'] *= res

    with rasterio.open(raster_file_path, "w", **meta) as dst:
        dst.write(image)
示例#19
0
    def set_raster_from_pix_bounds(self,
                                   xf_lat,
                                   xo_lon,
                                   d_lat,
                                   d_lon,
                                   n_lat,
                                   n_lon,
                                   crs=DEF_CRS):
        """ Set raster metadata (meta attribute) from pixel border data

        Parameters:
            xf_lat (float): upper latitude (top)
            xo_lon (float): left longitude
            d_lat (float): latitude step
            d_lon (float): longitude step
            n_lat (int): number of latitude points
            n_lon (int): number of longitude points
            crs (dict() or rasterio.crs.CRS, optional): CRS. Default: DEF_CRS
        """
        self.__init__()
        self.meta = {
            'dtype': 'float32',
            'width': n_lon,
            'height': n_lat,
            'crs': crs,
            'transform': Affine(d_lon, 0.0, xo_lon, 0.0, d_lat, xf_lat)
        }
示例#20
0
def rio_resample(srcpath,  outpath, res_factor = 15):


    with rio.open(srcpath) as src:

        arr = src.read()
        newarr = np.empty(shape=(arr.shape[0], int(arr.shape[1] * res_factor), int(arr.shape[2] * res_factor)))

        # adjust the new affine transform to the 150% smaller cell size
        aff = src.transform
        newaff = Affine(aff.a / res_factor, aff.b, aff.c, aff.d, aff.e /res_factor, aff.f)

        kwargs = src.meta.copy()
        #kwargs['transform'] = newaff
        #kwargs['affine'] = newaff
        kwargs.update({
            'crs': src.crs,
            'transform': newaff,
            'affine': newaff,
            'width': int(arr.shape[2] * res_factor),
            'height': int(arr.shape[1] * res_factor)
        })


        with rio.open(outpath, 'w', **kwargs) as dst:

            reproject(
                arr, newarr,
                src_transform = aff,
                dst_transform = newaff,
                src_crs = src.crs,
                dst_crs = src.crs,
                resample = Resampling.bilinear)

            dst.write(newarr[0].astype(rio.float32), indexes=1)
示例#21
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
示例#22
0
def array2coords(array, array_transform, nodata):
    '''
    

    Parameters
    ----------
    array : numpy.ndarray
        2D Numpy array to be converted
    array_transform : affine.Affine
        The affine transformation needed. Can be derived from a rasterio.profile
    nodata : float
        Value to be ignored from output dataset

    Returns
    -------
    pandas.DataFrame

    '''

    T1 = array_transform * Affine.translation(
        0.5, 0.5)  # reference the pixel centre
    rc2xy = lambda r, c: (c, r) * T1
    row, col = np.where(array != nodata)
    z = np.extract(array != nodata, array)

    df_coords = pd.DataFrame({'col': col, 'row': row, 'z': z})
    df_coords['x'] = df_coords.apply(lambda row: rc2xy(row.row, row.col)[0],
                                     axis=1)
    df_coords['y'] = df_coords.apply(lambda row: rc2xy(row.row, row.col)[1],
                                     axis=1)

    return df_coords
示例#23
0
    def test_transform_raster_pass(self):
        meta, inten_ras = read_raster(HAZ_DEMO_FL,
                                      transform=Affine(0.009000000000000341,
                                                       0.0, -69.33714959699981,
                                                       0.0,
                                                       -0.009000000000000341,
                                                       10.42822096697894),
                                      height=500,
                                      width=501)

        left = meta['transform'].xoff
        top = meta['transform'].yoff
        bottom = top + meta['transform'][4] * meta['height']
        right = left + meta['transform'][0] * meta['width']

        self.assertAlmostEqual(left, -69.33714959699981)
        self.assertAlmostEqual(bottom, 5.928220966978939)
        self.assertAlmostEqual(right, -64.82814959699981)
        self.assertAlmostEqual(top, 10.42822096697894)
        self.assertEqual(meta['width'], 501)
        self.assertEqual(meta['height'], 500)
        self.assertEqual(meta['crs'].to_epsg(), 4326)
        self.assertEqual(inten_ras.shape, (1, 500 * 501))

        meta, inten_all = read_raster(HAZ_DEMO_FL,
                                      window=Window(0, 0, 501, 500))
        self.assertTrue(np.array_equal(inten_all, inten_ras))
示例#24
0
    def sample(self, y, x, height, width, **kwargs):
        """ Read sample of the Band to memory.

        The sample is defined by its size and position in the raster, without respect to the georeference.
        In case if the sample coordinates spread out of the image boundaries, the image is padded with nodata value.

        Args:
            x: pixel horizontal coordinate of left top corner of the sample
            y: pixel vertical coordinate of left top corner of the sample
            width: spatial dimension of sample in pixels
            height: spatial dimension of sample in pixels

        Returns:
             a new :obj:`BandSample` containing the specified spatial subset of the band
        """

        coord_x = self.transform.c + x * self.transform.a
        coord_y = self.transform.f + y * self.transform.e

        dst_crs = self.crs
        dst_name = os.path.basename(self.name)
        dst_nodata = self.nodata if self.nodata is not None else 0
        dst_transform = Affine(self.transform.a, self.transform.b, coord_x,
                               self.transform.d, self.transform.e, coord_y)

        dst_raster = self._band.read(window=((y, y + height), (x, x + width)),
                                     boundless=True, fill_value=dst_nodata)

        sample = BandSample(dst_name, dst_raster, dst_crs, dst_transform, dst_nodata)

        return sample
示例#25
0
def rescale_transform(src_transform, src_width, src_height, scale):
    """Calculate the transform corresponding to a pixel size multiplied
    by a given scale factor.

    Parameters
    ----------
    src_transform : Affine
        Source affine transform.
    src_width : int
        Source raster width.
    src_height : int
        Source raster height.
    scale : float
        Scale factor (e.g. 0.5 to reduce pixel size by half).

    Returns
    -------
    dst_transform : Affine
        New affine transform.
    dst_width : int
        New raster width.
    dst_height : int
        New raster height.
    """
    dst_transform = Affine(src_transform.a * scale, src_transform.b,
                           src_transform.c, src_transform.d,
                           src_transform.e * scale, src_transform.f)
    dst_width = int(src_width / scale)
    dst_height = int(src_height / scale)
    return dst_transform, dst_width, dst_height
示例#26
0
def pix_to_coord(
    transform_array: Union[List, np.ndarray],
    row: Union[int, np.ndarray],
    col: Union[List, np.ndarray],
) -> Tuple[np.ndarray, np.ndarray]:
    """
    Transform pixels to coordinates

    :param transform_array: Transform
    :type transform_array: List or np.ndarray
    :param row: row
    :type row: int or np.ndarray
    :param col: column
    :type col: List or np.ndarray
    :return: x,y
    :rtype: np.ndarray, np.ndarray
    """
    transform = Affine.from_gdal(
        transform_array[0],
        transform_array[1],
        transform_array[2],
        transform_array[3],
        transform_array[4],
        transform_array[5],
    )
    # Set the offset to ul (upper left)
    x, y = rasterio.transform.xy(transform, row, col, offset="ul")

    if not isinstance(x, int):
        x = np.array(x)
        y = np.array(y)

    return x, y
示例#27
0
    def setUp(self):
        self.arr = np.array([[4, 4, 3, 2], [4, 4, 1, 1], [1, 4, 0, 2]],
                            dtype='uint8').reshape(3, 4, 1)

        self.masked_filled = np.array(
            [[4, 4, 0, 0], [4, 4, 0, 0], [0, 4, 0, 0]],
            dtype='uint8').reshape(3, 4, 1)

        self.arr4ch = np.array([[[4, 4, 3, 2], [4, 4, 1, 1], [1, 4, 0, 2]],
                                [[4, 4, 3, 2], [4, 4, 1, 1], [1, 4, 0, 2]]],
                               dtype='uint8')

        self.masked_filled4ch = np.array(
            [[[4, 4, 0, 0], [4, 4, 0, 0], [0, 4, 0, 0]],
             [[4, 4, 0, 0], [4, 4, 0, 0], [0, 4, 0, 0]]],
            dtype='uint8')

        self.meta = {
            'driver': 'GTiff',
            'dtype': 'uint8',
            'nodata': None,
            'width': 4,
            'height': 3,
            'count': 1,
            'crs': CRS.from_epsg(32737),
            'transform': Affine(10.0, 0.0, 199980.0, 0.0, -10.0, 9300040.0)
        }
示例#28
0
def test_file_writer():
    test_data = np.zeros((3, 256, 256), dtype=np.uint8)

    test_opts = {
        'driver': 'PNG',
        'dtype': 'uint8',
        'height': 512,
        'width': 512,
        'count': 3,
        'crs': 'EPSG:3857'
    }

    test_affine = Affine(1, 0, 0, 0, -1, 0)

    test_bytearray = _encode_as_png(test_data, test_opts, test_affine)

    assert len(test_bytearray) == 842

    test_complex_data = test_data.copy()

    test_complex_data[0] += (np.random.rand(256, 256) * 255).astype(np.uint8)
    test_complex_data[1] += 10

    test_bytearray_complex = _encode_as_png(test_complex_data, test_opts, test_affine)

    assert len(test_bytearray) < len(test_bytearray_complex)
示例#29
0
    def read_hdf5(self, file_data):
        """Read centroids attributes from hdf5.

        Parameters:
            file_data (str or h5): if string, path to read data. if h5 object,
                the datasets will be read from there
        """
        if isinstance(file_data, str):
            LOGGER.info('Reading %s', file_data)
            data = h5py.File(file_data, 'r')
        else:
            data = file_data
        self.clear()
        crs = DEF_CRS
        if data.get('crs'):
            crs = ast.literal_eval(data.get('crs')[0])
        if data.get('lat') and data.get('lat').size:
            self.set_lat_lon(np.array(data.get('lat')), np.array(data.get('lon')), crs)
        elif data.get('latitude') and data.get('latitude').size:
            self.set_lat_lon(np.array(data.get('latitude')), np.array(data.get('longitude')), crs)
        else:
            centr_meta = data.get('meta')
            self.meta['crs'] = crs
            for key, value in centr_meta.items():
                if key != 'transform':
                    self.meta[key] = value[0]
                else:
                    self.meta[key] = Affine(*value)
        for centr_name in data.keys():
            if centr_name not in ('crs', 'lat', 'lon', 'meta'):
                setattr(self, centr_name, np.array(data.get(centr_name)))
        if isinstance(file_data, str):
            data.close()
示例#30
0
class Img(object):
    def __enter__(self):
        return self

    def __exit__(self, type, value, tb):
        pass

    @staticmethod
    def read_masks(band: int = 0,
                   window: Optional[Window] = None) -> np.ndarray:
        return np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]])

    @staticmethod
    def block_windows(idx: int):
        for i in range(0, 2):
            yield (0, i), Window(i, 0, 1, 1)

    profile: Dict[str, Any] = {
        "transform": Affine(0, 2, 0, 0, -2, 0),
        "width": 3,
        "height": 3,
        "crs": CRS.from_epsg(4326),
        "blockxsize": 16,
        "blockysize": 16,
        "dtype": np.dtype("uint"),
    }
    bounds: box = box(1, 1, 0, 0)
示例#31
0
def __mask_to_polygons(mask):
    """[summary]

    Args:
        mask ([type]): [description]

    Returns:
        [type]: [description]
    """
    # XXX: maybe this should be merged with __mask_to_polys() defined above
    import numpy as np
    from rasterio import features, Affine
    from shapely import geometry

    all_polygons = []
    for shape, value in features.shapes(mask.astype(np.int16),
                                        mask=(mask > 0),
                                        transform=Affine(1.0, 0, 0, 0, 1.0,
                                                         0)):
        all_polygons.append(geometry.shape(shape))

    all_polygons = geometry.MultiPolygon(all_polygons)
    if not all_polygons.is_valid:
        all_polygons = all_polygons.buffer(0)
        # Sometimes buffer() converts a simple Multipolygon to just a Polygon,
        # need to keep it a Multi throughout
        if all_polygons.type == 'Polygon':
            all_polygons = geometry.MultiPolygon([all_polygons])
    return all_polygons
def example_reproject():
    import idfpy

    from matplotlib import pyplot as plt
    from rasterio import Affine
    from rasterio.crs import CRS
    from rasterio.warp import reproject, Resampling
    import numpy as np

    with idfpy.open('bxk1-d-ck.idf') as src:
        a = src.read(masked=True)
        nr, nc = src.header['nrow'], src.header['ncol']
        dx, dy = src.header['dx'], src.header['dy']
        src_transform = Affine.from_gdal(*src.geotransform)

    # define new grid transform (same extent, 10 times resolution)
    dst_transform = Affine.translation(src_transform.c, src_transform.f)
    dst_transform *= Affine.scale(dx / 10., -dy / 10.)

    # define coordinate system (here RD New)
    src_crs = CRS.from_epsg(28992)

    # initialize new data array
    b = np.empty((10*nr, 10*nc))

    # reproject using Rasterio
    reproject(
        source=a,
        destination=b,
        src_transform=src_transform,
        dst_transform=dst_transform,
        src_crs=src_crs,
        dst_crs=src_crs,
        resampling=Resampling.bilinear,
        )

    # result as masked array
    b = np.ma.masked_equal(b, a.fill_value)

    # plot images
    fig, axes = plt.subplots(nrows=2, ncols=1)
    axes[0].imshow(a.filled(np.nan))
    axes[0].set_title('bxk1 original')
    axes[1].imshow(b.filled(np.nan))
    axes[1].set_title('bxk1 resampled')
    plt.show()
示例#33
0
def main():
    
    for i in range(2):
        dat = nc.Dataset(innc[i])
        print dat
        
        #sum monthly values for 2010
        dat2010 = dat.variables[varname[i]][600:611,:,:].sum(0)
        cols = 720
        rows = 360
        d = 1/2.0
    
        with rasterio.open(outras[i],'w',
                       'GTiff',
                       width=cols,
                       height=rows,
                       dtype=dat2010.dtype,
                       crs={'init': 'EPSG:4326'},
                       transform=A.translation(-cols*d/2, rows*d/2) * A.scale(d, -d),
                       count=1) as dst:
            dst.write_band(1,dat2010)
    def coordinates(fn=None, meta=None, numpy_array=None, input_crs=None, to_latlong=False):
        """
		take a raster file as input and return the centroid coords for each 
		of the grid cells as a pair of numpy 2d arrays (longitude, latitude)
		"""
        import rasterio
        import numpy as np
        from affine import Affine
        from pyproj import Proj, transform

        if fn:
            # Read raster
            with rasterio.open(fn) as r:
                T0 = r.affine  # upper-left pixel corner affine transform
                p1 = Proj(r.crs)
                A = r.read(1)  # pixel values

        elif (meta is not None) & (numpy_array is not None):
            A = numpy_array
            if input_crs != None:
                p1 = Proj(input_crs)
                T0 = meta["affine"]
            else:
                p1 = None
                T0 = meta["affine"]
        else:
            BaseException("check inputs")

            # All rows and columns
        cols, rows = np.meshgrid(np.arange(A.shape[1]), np.arange(A.shape[0]))
        # Get affine transform for pixel centres
        T1 = T0 * Affine.translation(0.5, 0.5)
        # Function to convert pixel row/column index (from 0) to easting/northing at centre
        rc2en = lambda r, c: (c, r) * T1
        # All eastings and northings (there is probably a faster way to do this)
        eastings, northings = np.vectorize(rc2en, otypes=[np.float, np.float])(rows, cols)

        if to_latlong == False:
            return eastings, northings
        elif (to_latlong == True) & (input_crs != None):
            # Project all longitudes, latitudes
            longs, lats = transform(p1, p1.to_latlong(), eastings, northings)
            return longs, lats
        else:
            BaseException("cant reproject to latlong without an input_crs")
示例#35
0
    def to_raster(self, fp=None, epsg=28992, driver='AAIGrid'):
        """export Idf to a geotiff"""
        self.check_read()

        if fp is None:
            fp = self.filepath.replace('.idf', '.geotiff')
            logging.warning('no filepath was given, exported to {fp}'.format(fp=fp))

        # set profile
        profile = {
            'width': self.header['ncol'],
            'height': self.header['nrow'],
            'transform': Affine.from_gdal(*self.geotransform),
            'nodata': self.header['nodata'],
            'count': 1,
            'dtype': rasterio.float64,
            'driver': driver,
            'crs': CRS.from_epsg(epsg),
        }

        logging.info('writing to {f:}'.format(f=fp))
        with rasterio.open(fp, 'w', **profile) as dst:
            dst.write(self.masked_data.astype(profile['dtype']), 1)
示例#36
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)
示例#37
0
def _make_src_affine(src_data_array):
    src_bounds = _get_bounds(src_data_array)
    src_left, src_bottom, src_right, src_top = src_bounds
    src_resolution_x, src_resolution_y = _get_resolution(src_data_array, as_tuple=True)
    return Affine.translation(src_left, src_top) * Affine.scale(src_resolution_x, src_resolution_y)
示例#38
0
def main():
    # load and average netcdfs
    arr = None
    for f in NETCDFS:
        ds = nc.Dataset(f,'r')
        if arr is None:
            print ds.variables.keys()
            arr = np.asarray(ds.variables['lwe_thickness']) / len(NETCDFS)
        else:
            arr += np.asarray(ds.variables['lwe_thickness']) / len(NETCDFS)

    # multiply by scale factor
    ds = nc.Dataset(SCALER,'r')
    print ds.variables.keys()
    scaler = np.asarray(ds.variables['SCALE_FACTOR'])
    print scaler.shape
    arr = arr*scaler

    # extract error grids
    m_err = np.asarray(ds.variables['MEASUREMENT_ERROR'])
    l_err = np.asarray(ds.variables['LEAKAGE_ERROR'])
    t_err = np.sqrt(m_err*m_err + l_err*l_err)

    # compute slopes, coefficients
    print arr.shape
    slope_arr = np.zeros(arr.shape[1:])
    r2_arr = np.zeros(arr.shape[1:])
    p_arr = np.zeros(arr.shape[1:])
    print slope_arr.shape
    time = np.arange(arr.shape[0])
    print time.shape
    for i in range(arr.shape[1]):
        for j in range(arr.shape[2]):
            b1, b0, r2, p, sd = stats.linregress(arr[:,i,j], time)
            slope_arr[i,j]=b1
            r2_arr[i,j]=r2
            p_arr[i,j]=p

    # dump to csv
    np.savetxt(SLOPE,slope_arr,delimiter=',')
    np.savetxt(R2,r2_arr,delimiter=',')
    np.savetxt(P,p_arr,delimiter=',')
    np.savetxt(ERR,t_err,delimiter=',')

    # rescale to WGS84 and dump to tif bands
    rows = arr.shape[1]
    cols = arr.shape[2]
    d = 1
    transform = A.translation(-cols*d/2,-rows*d/2) * A.scale(d,d)
    print transform
    slope_arr = np.roll(slope_arr.astype(rio.float64),180)
    r2_arr = np.roll(r2_arr.astype(rio.float64),180)
    p_arr = np.roll(p_arr.astype(rio.float64),180)
    t_err = np.roll(t_err.astype(rio.float64),180)

    with rio.open(OUT, 'w',
                  'GTiff',
                  width=cols,
                  height=rows,
                  dtype=rio.float64,
                  crs={'init': 'EPSG:4326'},
                  transform=transform,
                  count=4) as out:
        out.write_band(1, slope_arr)
        out.write_band(2, r2_arr)
        out.write_band(3, p_arr)
        out.write_band(4, t_err)
示例#39
0
import rasterio
from rasterio import Affine as A
from rasterio.warp import reproject, RESAMPLING

tempdir = '/tmp'
tiffname = os.path.join(tempdir, 'example.tif')

with rasterio.drivers():

    # Consider a 512 x 512 raster centered on 0 degrees E and 0 degrees N
    # with each pixel covering 15".
    rows, cols = src_shape = (512, 512)
    dpp = 1.0/240 # decimal degrees per pixel
    # The following is equivalent to 
    # A(dpp, 0, -cols*dpp/2, 0, -dpp, rows*dpp/2).
    src_transform = A.translation(-cols*dpp/2, rows*dpp/2) * A.scale(dpp, -dpp)
    src_crs = {'init': 'EPSG:4326'}
    source = numpy.ones(src_shape, numpy.uint8)*255

    # Prepare to reproject this rasters to a 1024 x 1024 dataset in
    # Web Mercator (EPSG:3857) with origin at -8928592, 2999585.
    dst_shape = (1024, 1024)
    dst_transform = A.from_gdal(-237481.5, 425.0, 0.0, 237536.4, 0.0, -425.0)
    dst_transform = dst_transform.to_gdal()
    dst_crs = {'init': 'EPSG:3857'}
    destination = numpy.zeros(dst_shape, numpy.uint8)

    reproject(
        source, 
        destination, 
        src_transform=src_transform,