Ejemplo n.º 1
0
def _resample_raster(raster, out_file, factor):
    """ Resample raster

    Parameters
    ----------
    raster: RasterBase
        raster to resample
    out_file: str
        output file to which to write new raster
    factor: int or float
        Resampling factor
    """
    geo_transform = (raster.x_origin, raster.resolution[0] / factor, 0,
                     raster.y_origin, 0, -raster.resolution[1] / factor)
    out_ds = _gdal_temp_dataset(out_file, raster._gdal_driver,
                                raster._gdal_dataset.GetProjection(),
                                raster.x_size * factor, raster.y_size * factor,
                                raster.nb_band, geo_transform,
                                raster.data_type, raster.no_data)

    for band in range(1, raster.nb_band + 1):
        gdal.RegenerateOverview(raster._gdal_dataset.GetRasterBand(band),
                                out_ds.GetRasterBand(band), 'mode')

    # Close dataset
    out_ds = None
Ejemplo n.º 2
0
def _rasterize(raster_class, geodataframe, burn_values, attribute,
               gdal_driver, projection, x_size, y_size, nb_band,
               geo_transform, data_type, no_data, all_touched):
    """ Rasterize geographic layer

    Parameters
    ----------
    raster_class: RasterBase
        Raster class to return
    geodataframe: geopandas.GeoDataFrame or gistools.layer.GeoLayer
        Geographic layer to be rasterized
    burn_values: None or list[float] or list[int]
        list of values to burn in each band, excusive with attribute
    attribute: str
        attribute in layer from which burn value must be retrieved
    gdal_driver
    projection
    x_size: int
    y_size: int
    nb_band: int
    geo_transform: tuple
    data_type
    no_data
    all_touched: bool

    Returns
    -------

    """

    with ShapeTempFile() as shp_file, \
            RasterTempFile(gdal_driver.GetMetadata()['DMD_EXTENSION']) as out_file:

        geodataframe.to_file(shp_file.path, driver=ESRI_DRIVER)

        out_ds = _gdal_temp_dataset(out_file.path,
                                    gdal_driver,
                                    projection,
                                    x_size,
                                    y_size,
                                    nb_band,
                                    geo_transform,
                                    data_type,
                                    no_data)

        gdal.Rasterize(out_ds,
                       shp_file.path,
                       bands=[bd + 1 for bd in range(nb_band)],
                       burnValues=burn_values,
                       attribute=attribute,
                       allTouched=all_touched)

    out_ds = None

    # Be careful with the temp file, make a pointer to be sure
    # the Python garbage collector does not destroy it !
    raster = raster_class(out_file.path)
    raster._temp_file = out_file

    return raster
Ejemplo n.º 3
0
def _array_to_raster(raster_class, array, crs, bounds, gdal_driver, no_data):
    """ Convert array to (north up) raster

    Parameters
    ----------
    array: numpy.ndarray
    crs: pyproj.CRS
    bounds: tuple
        Image boundaries as (xmin, ymin, xmax, ymax)
    gdal_driver: osgeo.gdal.Driver
    no_data

    Returns
    -------

    """
    if array.ndim == 2:
        nb_band = 1
        x_size = array.shape[1]
        y_size = array.shape[0]
    else:
        nb_band = array.shape[0]
        x_size = array.shape[2]
        y_size = array.shape[1]

    xmin, ymin, xmax, ymax = bounds
    geo_transform = (xmin, (xmax - xmin) / x_size, 0, ymax, 0,
                     -(ymax - ymin) / y_size)

    with RasterTempFile(
            gdal_driver.GetMetadata()['DMD_EXTENSION']) as out_file:

        out_ds = _gdal_temp_dataset(
            out_file.path, gdal_driver, crs.to_wkt(), x_size, y_size,
            nb_band, geo_transform,
            gdal_array.NumericTypeCodeToGDALTypeCode(array.dtype), no_data)

        if nb_band == 1:
            out_ds.GetRasterBand(nb_band).WriteArray(array)
        else:
            for band in range(nb_band):
                out_ds.GetRasterBand(band + 1).WriteArray(array[band, :, :])

    # Close dataset
    out_ds = None

    raster = raster_class(out_file.path)
    raster._temp_file = out_file

    return raster
Ejemplo n.º 4
0
def _align_raster(in_raster, out_file, on_raster):
    """ Align raster on other raster

    """
    out_ds = _gdal_temp_dataset(out_file, in_raster._gdal_driver,
                                on_raster._gdal_dataset.GetProjection(),
                                on_raster.x_size, on_raster.y_size,
                                in_raster.nb_band, on_raster.geo_transform,
                                in_raster.data_type, in_raster.no_data)

    gdal.Warp(out_ds, in_raster._gdal_dataset)

    # Close dataset
    out_ds = None
Ejemplo n.º 5
0
def _windowing(raster, out_file, function, band, window_size,
               method, data_type, no_data, chunk_size, nb_processes):
    """ Apply function in each moving or block window in raster

    Description
    -----------

    Parameters
    ----------

    """
    window_generator = WindowGenerator(raster, band, window_size, method)
    out_ds = _gdal_temp_dataset(out_file, raster._gdal_driver, raster._gdal_dataset.GetProjection(),
                                window_generator.x_size, window_generator.y_size, raster.nb_band,
                                window_generator.geo_transform, data_type, no_data)

    y = 0
    # chunk size cannot be 0 and cannot
    # be higher than height of window
    # generator (y_size). And it must be
    # a multiple of window generator width
    # (x_size)
    chunk_size = max(min(chunk_size // window_generator.x_size, window_generator.y_size)
                     * window_generator.x_size, window_generator.x_size)
    for win_gen in tqdm(split_into_chunks(window_generator, chunk_size),
                        total=len(window_generator)//chunk_size +
                        int(len(window_generator) % chunk_size != 0),
                        desc="Sliding window computation"):
        with mp.Pool(processes=nb_processes) as pool:
            output = np.asarray(list(pool.map(partial(_set_nan,
                                                      function=function,
                                                      no_data=raster.no_data),
                                              win_gen,
                                              chunksize=MP_CHUNK_SIZE)))

        output[np.isnan(output)] = no_data

        # Set number of rows to write to file
        n_rows = len(output) // window_generator.x_size

        # Write row to raster
        out_ds.GetRasterBand(band).WriteArray(np.reshape(output, (n_rows,
                                                                  window_generator.x_size)), 0, y)

        # Update row index
        y += n_rows

    # Close dataset
    out_ds = None
Ejemplo n.º 6
0
def _clip_raster_by_mask(raster, geodataframe, no_data, all_touched):
    """ Clip raster by mask from geographic layer

    Parameters
    ----------
    raster: pyrasta.raster.RasterBase
        raster to clip
    geodataframe: geopandas.GeoDataFrame or gistools.layer.GeoLayer
    no_data: float or int
        No data value
    all_touched: bool
        if True, clip all pixels that are touched, otherwise clip
        if pixel's centroids are within boundaries

    Returns
    -------
    RasterBase

    """
    clip_raster = raster.clip(bounds=geodataframe.total_bounds)

    with ShapeTempFile() as shp_file, \
            RasterTempFile(clip_raster._gdal_driver.GetMetadata()['DMD_EXTENSION']) as r_file:

        geodataframe.to_file(shp_file.path, driver=ESRI_DRIVER)

        out_ds = _gdal_temp_dataset(r_file.path, clip_raster._gdal_driver,
                                    clip_raster._gdal_dataset.GetProjection(),
                                    clip_raster.x_size, clip_raster.y_size,
                                    clip_raster.nb_band,
                                    clip_raster.geo_transform,
                                    clip_raster.data_type, clip_raster.no_data)

        gdal.Rasterize(out_ds,
                       shp_file.path,
                       burnValues=[1],
                       allTouched=all_touched)

    out_ds = None

    return clip_raster.__class__.raster_calculation(
        [clip_raster, clip_raster.__class__(r_file.path)],
        lambda x, y: x * y,
        no_data=no_data,
        showprogressbar=False)
Ejemplo n.º 7
0
    def _return_classification(raster, nb_classes, *args, **kwargs):
        with RasterTempFile(raster._gdal_driver.GetMetadata()
                            ['DMD_EXTENSION']) as out_file:
            out_ds = _gdal_temp_dataset(out_file.path,
                                        raster._gdal_driver,
                                        raster._gdal_dataset.GetProjection(),
                                        raster.x_size,
                                        raster.y_size,
                                        1,
                                        raster.geo_transform,
                                        gdal.GetDataTypeByName('Int16'),
                                        no_data=CLASSIFICATION_NO_DATA)
            labels = classification(raster, nb_classes, out_ds, *args,
                                    **kwargs)

            # Close dataset
            out_ds = None

            new_raster = raster.__class__(out_file.path)
            new_raster._temp_file = out_file

        return new_raster
Ejemplo n.º 8
0
def _padding(raster, out_file, pad_x, pad_y, pad_value):
    """ Add pad values around raster

    Description
    -----------

    Parameters
    ----------
    raster: RasterBase
        raster to pad
    out_file: str
        output file to which to write new raster
    pad_x: int
        x padding size (new width will therefore be RasterXSize + 2 * pad_x)
    pad_y: int
        y padding size (new height will therefore be RasterYSize + 2 * pad_y)
    pad_value: int or float
        value to set to pad area around raster

    Returns
    -------
    """
    geo_transform = (raster.x_origin - pad_x * raster.resolution[0],
                     raster.resolution[0], 0,
                     raster.y_origin + pad_y * raster.resolution[1], 0,
                     -raster.resolution[1])
    out_ds = _gdal_temp_dataset(out_file, raster._gdal_driver,
                                raster._gdal_dataset.GetProjection(),
                                raster.x_size + 2 * pad_x,
                                raster.y_size + 2 * pad_y, raster.nb_band,
                                geo_transform, raster.data_type,
                                raster.no_data)

    for band in range(1, raster.nb_band + 1):
        out_ds.GetRasterBand(band).Fill(pad_value)
        gdal.Warp(out_ds, raster._gdal_dataset)

    # Close dataset
    out_ds = None
Ejemplo n.º 9
0
def _op(raster1, out_file, raster2, op_type):
    """ Basic arithmetic operations

    """
    out_ds = _gdal_temp_dataset(out_file, raster1._gdal_driver,
                                raster1._gdal_dataset.GetProjection(),
                                raster1.x_size, raster1.y_size,
                                raster1.nb_band, raster1.geo_transform,
                                gdal.GetDataTypeByName('Float32'),
                                raster1.no_data)

    for band in range(1, raster1.nb_band + 1):

        for window in get_block_windows(1000, raster1.x_size, raster1.y_size):
            array1 = raster1._gdal_dataset.GetRasterBand(band).ReadAsArray(
                *window).astype("float32")
            try:
                array2 = raster2._gdal_dataset.GetRasterBand(band).ReadAsArray(
                    *window).astype("float32")
            except AttributeError:
                array2 = raster2  # If second input is not a raster but a scalar

            if op_type == "add":
                result = array1 + array2
            elif op_type == "sub":
                result = array1 - array2
            elif op_type == "mul":
                result = array1 * array2
            elif op_type == "truediv":
                result = array1 / array2
            else:
                result = None

            out_ds.GetRasterBand(band).WriteArray(result, window[0], window[1])

    # Close dataset
    out_ds = None
Ejemplo n.º 10
0
def _raster_calculation(raster_class, sources, fhandle, window_size,
                        gdal_driver, data_type, no_data, nb_processes,
                        chunksize, description):
    """ Calculate raster expression

    """
    if not hasattr(window_size, "__getitem__"):
        window_size = (window_size, window_size)

    master_raster = sources[0]
    window_gen = ([
        src._gdal_dataset.ReadAsArray(*w).astype(GDAL_TO_NUMPY[data_type])
        for src in sources
    ] for w in get_xy_block_windows(window_size, master_raster.x_size,
                                    master_raster.y_size))
    width = int(master_raster.x_size / window_size[0]) + min(
        1, master_raster.x_size % window_size[0])
    height = int(master_raster.y_size / window_size[1]) + min(
        1, master_raster.y_size % window_size[1])

    with RasterTempFile(
            gdal_driver.GetMetadata()['DMD_EXTENSION']) as out_file:

        is_first_run = True
        y = 0

        for win_gen in tqdm(split_into_chunks(window_gen, width),
                            total=height,
                            desc=description):

            with mp.Pool(processes=nb_processes) as pool:
                result = np.concatenate(list(
                    pool.imap(fhandle, win_gen, chunksize=chunksize)),
                                        axis=1)

            if is_first_run:
                if result.ndim == 2:
                    nb_band = 1
                else:
                    nb_band = result.shape[0]

                out_ds = _gdal_temp_dataset(
                    out_file.path, gdal_driver,
                    master_raster._gdal_dataset.GetProjection(),
                    master_raster.x_size, master_raster.y_size, nb_band,
                    master_raster.geo_transform, data_type, no_data)

                is_first_run = False

            if nb_band == 1:
                out_ds.GetRasterBand(1).WriteArray(result, 0, y)
            else:
                for band in range(nb_band):
                    out_ds.GetRasterBand(band + 1).WriteArray(
                        result[band, :, :], 0, y)

            y += window_size[1]

    # Close dataset
    out_ds = None

    return raster_class(out_file.path)