Beispiel #1
0
def write(geo_array,
          file_name,
          dtype=None,
          nodata=None,
          proj=None,
          gdal_driver='GTiff',
          overwrite=False):
    if not overwrite and os.path.isfile(file_name):
        raise IOError('file `{}` already exists.'.format(file_name))
    if dtype is None:
        dtype = geo_array.array.dtype
    raster = gdal.GetDriverByName(gdal_driver).Create(
        utf8_path=file_name,
        xsize=geo_array.width,
        ysize=geo_array.height,
        bands=geo_array.bands,
        eType=gdal_array.flip_code(numpy.dtype(dtype)))
    if not raster:
        raise IOError('an error occurred while creating gdal dataset.')

    # resolve projection
    if proj is None:
        proj = geo_array.proj_origin
    if proj is None:
        proj = DEFAULT_PROJ
    raster.SetProjection(proj)
    raster.SetGeoTransform(geo_array.geotransform.to_list())

    # convert buffer dtype to informed dtype parameter as to write data to raster.
    buffer = geo_array.array.astype(dtype, copy=True)
    byte_string = buffer.tostring()

    # get buffer strides in order to finda data elements position in `byte_string`
    height_size, width_size, bands_size = buffer.strides
    raster.WriteRaster(xoff=0,
                       yoff=0,
                       xsize=geo_array.width,
                       ysize=geo_array.height,
                       buf_string=byte_string,
                       buf_xsize=geo_array.width,
                       buf_ysize=geo_array.height,
                       buf_type=gdal_array.flip_code(dtype),
                       buf_pixel_space=width_size,
                       buf_line_space=height_size,
                       buf_band_space=bands_size)
    # 2-do: capture gdal errors and treat them appropriately.
    raster.FlushCache()

    if nodata is None:
        nodata = geo_array.nodata
    if nodata is not None:
        for i in range(1, raster.RasterCount + 1):
            raster.GetRasterBand(i).SetNoDataValue(nodata)
    for i in range(1, raster.RasterCount + 1):
        raster.GetRasterBand(i).ComputeStatistics(False)
    raster.SetMetadata(geo_array.metadata)
Beispiel #2
0
def test_write_array_to_file(shape: Tuple[int],
                             dst_filename: Optional[PathLikeOrStr] = None):
    np_dtype = np.float32
    a = np.random.rand(*shape)
    a = np.array(a, dtype=np_dtype)
    if dst_filename is None:
        dst_filename = tempfile.mktemp(suffix='.tif')
    ds = write_array_to_file(dst_filename, a)

    if len(shape) == 3:
        a0 = a[0]
        raster_count = shape[0]
        y_size, x_size = shape[1:]
    else:
        a0 = a
        raster_count = 1
        y_size, x_size = shape
    assert ds.RasterCount == raster_count
    assert ds.RasterXSize == x_size
    assert ds.RasterYSize == y_size
    bnd: gdal.Band = ds.GetRasterBand(1)
    assert bnd.DataType == gdal_array.flip_code(a.dtype)
    b = bnd.ReadAsArray()
    assert_almost_equal(a0, b)
    ds = None

    gdal.Unlink(dst_filename)
Beispiel #3
0
def command(source_path, raster_path, target_path, attribute, partial):
    """ Main """
    if partial is None:
        source_features = common.Source(source_path)
    else:
        source_features = common.Source(source_path).select(partial)

    raster = gdal.Open(raster_path)
    geo_transform = GeoTransform(raster.GetGeoTransform())
    sr = osr.SpatialReference(raster.GetProjection())
    band = raster.GetRasterBand(1)
    dtype = gdal_array.flip_code(band.DataType)
    no_data_value = np.array(band.GetNoDataValue(), dtype).item()

    # prepare statistics gathering
    target = common.Target(
        path=target_path,
        template_path=source_path,
        attributes=[attribute],
    )

    for source_feature in source_features:
        geometry = source_feature.geometry()
        geometry.TransformTo(sr)
        xoff, yoff = geo_transform.get_centroid_indices(geometry)
        value = band.ReadAsArray(xoff, yoff, 1, 1).item()
        attributes = {attribute: None if value == no_data_value else value}
        target.append(geometry=geometry,
                      attributes=attributes)
    return 0
Beispiel #4
0
def replace(source_path, target_path):
    source_dataset = gdal.Open(source_path)
    source_values = source_dataset.ReadAsArray()
    source_band = source_dataset.GetRasterBand(1)
    source_no_data_value = source_band.GetNoDataValue()

    data_type = source_band.DataType
    dtype = gdal_array.flip_code(data_type)

    target_no_data_value = np.finfo(dtype).max.item()
    target_values = np.where(
        source_values == source_no_data_value,
        target_no_data_value,
        source_values,
    )

    target_dataset = DRIVER_MEM.CreateCopy('', source_dataset)
    target_band = target_dataset.GetRasterBand(1)
    target_band.WriteArray(target_values)
    target_band.SetNoDataValue(target_no_data_value)

    options = ['compress=deflate', 'tiled=yes']
    gdal.GetDriverByName(str('gtiff')).CreateCopy(
        target_path, target_dataset, options=options,
    )
Beispiel #5
0
def write_array_to_file(dst_filename: PathLikeOrStr,
                        a: MaybeSequence[np.ndarray],
                        gdal_dtype=None) -> gdal.Dataset:
    driver_name = GetOutputDriverFor(dst_filename, is_raster=True)
    driver = gdal.GetDriverByName(driver_name)
    a_shape = a[0].shape
    if len(a_shape) == 1:
        # 2d array, singleband raster
        a = [a]
        bands_count = 1
    elif len(a_shape) == 2:
        # 3d array, multiband raster
        bands_count = a.shape[0]
    else:
        raise Exception('Array should have 2 or 3 dimensions')
    y_size, x_size = a[0].shape

    if gdal_dtype is None:
        np_dtype = a[0].dtype
        gdal_dtype = gdal_array.flip_code(np_dtype)
    ds = driver.Create(dst_filename, x_size, y_size, bands_count, gdal_dtype)
    if ds is None:
        raise Exception(f'failed to create: {dst_filename}')

    for bnd_num in range(bands_count):
        bnd = ds.GetRasterBand(bnd_num + 1)
        if gdal_array.BandWriteArray(bnd, a[bnd_num], xoff=0, yoff=0) != 0:
            raise Exception('I/O error')

    return ds
Beispiel #6
0
def point_from_dataset(dataset, point):
    x, y = point
    p, a, b, q, c, d = dataset.GetGeoTransform()
    minv = np.linalg.inv([[a, b], [c, d]])
    u, v = np.dot(minv, [x - p, y - q])
    band_list = range(1, dataset.RasterCount + 1)
    data = dataset.ReadRaster(int(u), int(v), 1, 1, band_list=band_list)
    data_type = gdal_array.flip_code(dataset.GetRasterBand(1).DataType)
    return np.fromstring(data, dtype=data_type)
Beispiel #7
0
    def get_data_for_polygon(self, wkb, crs, size):
        """
        Return a numpy array for the data.
        """
        # Quick out if polygon bounds match polygon
        geometry = vectors.Geometry(wkb)
        envelope = geometry.envelope
        extent = geometry.extent
        nodatavalue = self.manager.no_data_value
        datatype = self.manager.data_type

        # Initialize resulting array to nodatavalue
        dtype = gdal_array.flip_code(datatype)
        array = np.ones(
            (1, size[1], size[0]),
            dtype=dtype,
        ) * dtype(nodatavalue)

        # Create dataset and use it to retrieve data from the store
        array_dict = dict(
            array=array,
            no_data_value=nodatavalue,
            projection=projections.get_wkt(crs),
            geo_transform=rasters.get_geotransform(
                extent=extent, width=size[0], height=size[1],
            ),
        )
        dataset = rasters.dict2dataset(array_dict)        
        self.warpinto(dataset)
        dataset.FlushCache()        

        # Cut when necessary
        if not envelope.Equals(wkb):            
            source = OGR_MEM_DRIVER.CreateDataSource('')
            sr = projections.get_spatial_reference(crs)
            layer = source.CreateLayer(b'', sr)
            defn = layer.GetLayerDefn()
            feature = ogr.Feature(defn)
            feature.SetGeometry(envelope.Difference(wkb))
            layer.CreateFeature(feature)
            gdal.RasterizeLayer(dataset, (1,), layer,
                                burn_values=(nodatavalue,))
            dataset.FlushCache()

        return np.ma.masked_equal(array, nodatavalue, copy=False)
Beispiel #8
0
def read_as_shared_array(dataset):
    """
    Return numpy array.

    Puts the array data in shared memory for use with multiprocessing.
    """
    # Derive array properties from the dataset
    dtype = np.dtype(gdal_array.flip_code(
        dataset.GetRasterBand(1).DataType,
    ))
    shape = (dataset.RasterCount,
             dataset.RasterYSize,
             dataset.RasterXSize)
    size = shape[0] * shape[1] * shape[2] * dtype.itemsize
    # Create shared memory array and read into it
    return dataset.ReadAsArray(buf_obj=np.frombuffer(
        multiprocessing.RawArray('b', size), dtype
    ).reshape(*shape))
Beispiel #9
0
def test_gdal2xyz_py_1():
    """ test get_ovr_idx, create_flat_raster """
    pytest.importorskip('numpy')

    size = (3, 3)
    origin = (500_000, 0)
    pixel_size = (10, -10)
    nodata_value = 255
    band_count = 2
    dt = gdal.GDT_Byte
    np_dt = flip_code(dt)
    ds = create_flat_raster(filename='',
                            size=size,
                            origin=origin,
                            pixel_size=pixel_size,
                            nodata_value=nodata_value,
                            fill_value=nodata_value,
                            band_count=band_count,
                            dt=dt)
    src_nodata = nodata_value
    np.random.seed()
    for bnd_idx in range(band_count):
        bnd = ds.GetRasterBand(bnd_idx + 1)
        data = (np.random.random_sample(size) * 255).astype(np_dt)
        data[1, 1] = src_nodata
        bnd.WriteArray(data, 0, 0)
    dst_nodata = 254
    for pre_allocate_np_arrays, skip_nodata in product((True, False),
                                                       (True, False)):
        geo_x, geo_y, data, nodata = \
            gdal2xyz.gdal2xyz(
                ds, None, return_np_arrays=True,
                src_nodata=src_nodata, dst_nodata=dst_nodata,
                skip_nodata=skip_nodata, pre_allocate_np_arrays=pre_allocate_np_arrays)
        _pixels, _lines, data2 = gdallocationinfo.gdallocationinfo(
            ds,
            x=geo_x,
            y=geo_y,
            resample_alg=gdal.GRIORA_NearestNeighbour,
            srs=gdallocationinfo.LocationInfoSRS.SameAsDS_SRS)
        data2[data2 == src_nodata] = dst_nodata
        assert np.all(np.equal(data, data2))
Beispiel #10
0
def point_from_dataset(animation, framenr, point):
    x, y = point
    p, a, b, q, c, d = animation.get_geotransform()
    minv = np.linalg.inv([[a, b], [c, d]])
    u, v = np.dot(minv, [x - p, y - q])

    u = int(u)
    v = int(v)

    if not ((0 <= u < animation.cols) and (0 <= v < animation.rows)):
        # Outside animation
        return None

    dataset = gdal.Open(animation.get_dataset_path(framenr))
    if dataset is None:
        return None

    data = dataset.ReadRaster(u, v, 1, 1, band_list=[1])
    data_type = gdal_array.flip_code(dataset.GetRasterBand(1).DataType)
    return np.fromstring(data, dtype=data_type)[0]
Beispiel #11
0
    def read_block(self, block):
        """ Read a block as a dataset. """
        # read the data
        u1, u2, v1, v2 = self.get_offsets(block)
        band_list = range(1, self.raster_count + 1)
        array = np.fromstring(self.dataset.ReadRaster(
            u1, v1, u2 - u1, v2 - v1, band_list=band_list,
        ), dtype=gdal_array.flip_code(self.data_type))
        array.shape = self.raster_count, v2 - v1, u2 - u1

        # dataset properties
        p, a, b, q, c, d = self.geo_transform
        geo_transform = p + a * u1 + b * v1, a, b, q + c * u1 + d * v1, c, d
        dataset = dict2dataset(dict(
            array=array,
            geo_transform=geo_transform,
            projection=self.projection,
            no_data_value=self.no_data_value,
        ))
        return dict(dataset=dataset, array=array)
Beispiel #12
0
def point_from_dataset(animation, framenr, point):
    x, y = point
    p, a, b, q, c, d = animation.get_geotransform()
    minv = np.linalg.inv([[a, b], [c, d]])
    u, v = np.dot(minv, [x - p, y - q])

    u = int(u)
    v = int(v)

    if not ((0 <= u < animation.cols) and (0 <= v < animation.rows)):
        # Outside animation
        return None

    dataset = gdal.Open(animation.get_dataset_path(framenr))
    if dataset is None:
        return None

    data = dataset.ReadRaster(u, v, 1, 1, band_list=[1])
    data_type = gdal_array.flip_code(dataset.GetRasterBand(1).DataType)
    return np.fromstring(data, dtype=data_type)[0]
Beispiel #13
0
def get_dtype(dataset):
    """ Return the numpy dtype. """
    return np.dtype(gdal_array.flip_code(
        dataset.GetRasterBand(1).DataType,
    ))
Beispiel #14
0
def lutx(lut, input, output, format):
    """
    Reads in input image, applies lut and outputs image
    """
    # Read in input image
    gdal.AllRegister()
    src_ds = gdal.Open(input, GA_ReadOnly)
    if src_ds is None:
        print 'Error: could not open {0}'.format(input)
    rows = src_ds.RasterYSize
    cols = src_ds.RasterXSize
    # Read in data
    band = src_ds.GetRasterBand(1)
    dtype = band.DataType
    data = band.ReadAsArray(0, 0, cols,
                            rows).astype(gdal_array.flip_code(dtype))

    # Determine requiredo output datatype
    out_dt = np.byte
    if np.min(lut.values()) < 0:
        # Must be signed int
        if np.max(np.abs(lut.values())) < 2**15:
            # NOTE: put np.int8 as np.int16 since GDAL has no int8
            out_dt = np.int16
        elif np.max(np.abs(lut.values())) < 2**31:
            out_dt = np.int32
        elif np.max(np.abs(lut.values())) < 2**63:
            out_dt = np.int64
        else:
            print 'Required output data type is unknown'
            sys.exit(1)
    else:
        # Can be unsigned
        if np.max(lut.values()) < 2**8:
            out_dt = np.uint8
        elif np.max(lut.values()) < 2**16:
            out_dt = np.uint16
        elif np.max(lut.values()) < 2**32:
            out_dt = np.uint32
        elif np.max(lut.values()) < 2**64:
            out_dt = np.uint64
        else:
            print 'Required output data type is unknown'
            sys.exit(1)

    if DEBUG:
        print 'NumPy data type:  %s' % str(out_dt)
        print 'GDAL data type:   %s' % str(
            gdal.GetDataTypeName(gdal_array.flip_code(out_dt)))

    # Copy data for output
    lutdata = data.copy().astype(out_dt)
    # Apply lut
    for key, value in lut.iteritems():
        np.place(lutdata, data == key, value)

    # Write to output
    driver = gdal.GetDriverByName(format)
    dst_ds = driver.Create(output, src_ds.RasterXSize, src_ds.RasterYSize, 1,
                           gdal_array.flip_code(out_dt))
    dst_ds.SetProjection(src_ds.GetProjection())
    dst_ds.SetGeoTransform(src_ds.GetGeoTransform())
    dst_ds.GetRasterBand(1).WriteArray(lutdata)
    # Close
    src_ds = None
    dst_ds = None
    print 'Wrote output to file {0}'.format(output)
Beispiel #15
0
def save_raster(outfile, data, info=None):
    """open a GDAL-readable raster file
    returns a pair of (metadata,array)
    """

    proj4txt = (info and info['grid'].srs())
    geoxf = (info and info['grid'].geoxf())
    meta = None  # XXX fixme

    dirname,fname = os.path.split(os.path.abspath(outfile))
    if not os.path.isdir(dirname):
        os.makedirs(dirname)

    if len(data.shape) == 3:
        ysize,xsize,nbands = data.shape
    else:
        ysize,xsize = data.shape
        nbands = 1

    # get the gdal datatype from the numpy datatype
    gdtype = gdal_array.flip_code(data.dtype.type)

    # do not add COMPRESS=DEFLATE here
    # generate all TIFFs in blocks for faster random access
    blocksize = 128
    opts = [
        'TILED=YES',
        'BLOCKXSIZE=%d' % blocksize,
        'BLOCKYSIZE=%d' % blocksize
        ]

    #print 'SAVE %r %r' % (outfile, (data.shape, blocksize, opts))

    gtiff = gdal.GetDriverByName('GTiff')

    #print 'GDTY %r %r %r' % (data.dtype, gdtype, gdalconst.GDT_Byte)

    ds = gtiff.Create(str(outfile), xsize, ysize, nbands,
                      gdtype, opts)

    if proj4txt is not None:
        srs = osr.SpatialReference()
        srs.ImportFromProj4(proj4txt)
        ds.SetProjection(srs.ExportToWkt())

    if geoxf is not None:
        ds.SetGeoTransform(geoxf)

    if meta is not None:
        ds.SetMetadata(meta)

    for i in range(nbands):
        rband = ds.GetRasterBand(i+1)

        if nbands == 1:
            rband.SetRasterColorInterpretation(gdalconst.GCI_GrayIndex)
        elif i == 0:
            rband.SetRasterColorInterpretation(gdalconst.GCI_RedBand)
        elif i == 1:
            rband.SetRasterColorInterpretation(gdalconst.GCI_GreenBand)
        elif i == 2:
            rband.SetRasterColorInterpretation(gdalconst.GCI_BlueBand)
        elif i == 3:
            rband.SetRasterColorInterpretation(gdalconst.GCI_AlphaBand)

        #rband.SetNoDataValue(xxx):

        bdata = data
        if nbands > 1:
            bdata = data[:,:,i]

        # transform data to unsigned byte?
        print 'DATA %r: %f < x < %f' % (outfile, N.min(bdata), N.max(bdata))

        rband.WriteArray(bdata)
Beispiel #16
0
def lutx(lut, input, output, format):
    """
    Reads in input image, applies lut and outputs image
    """
    # Read in input image
    gdal.AllRegister()
    src_ds = gdal.Open(input, GA_ReadOnly)
    if src_ds is None:
        print 'Error: could not open {0}'.format(input)
    rows = src_ds.RasterYSize
    cols = src_ds.RasterXSize
    # Read in data
    band = src_ds.GetRasterBand(1)
    dtype = band.DataType
    data = band.ReadAsArray(0, 0, cols, rows).astype(
                                gdal_array.flip_code(dtype))
    
    # Determine requiredo output datatype
    out_dt = np.byte
    if np.min(lut.values()) < 0:
        # Must be signed int
        if np.max(np.abs(lut.values())) < 2 ** 15:
            # NOTE: put np.int8 as np.int16 since GDAL has no int8
            out_dt = np.int16
        elif np.max(np.abs(lut.values())) < 2 ** 31:
            out_dt = np.int32
        elif np.max(np.abs(lut.values())) < 2 ** 63:
            out_dt = np.int64
        else:
            print 'Required output data type is unknown'
            sys.exit(1)
    else:
        # Can be unsigned
        if np.max(lut.values()) < 2 ** 8:
            out_dt = np.uint8
        elif np.max(lut.values()) < 2 ** 16:
            out_dt = np.uint16
        elif np.max(lut.values()) < 2 ** 32:
            out_dt = np.uint32
        elif np.max(lut.values()) < 2 ** 64:
            out_dt = np.uint64
        else:
            print 'Required output data type is unknown'
            sys.exit(1)

    if DEBUG:
        print 'NumPy data type:  %s' % str(out_dt)
        print 'GDAL data type:   %s' % str(
            gdal.GetDataTypeName(gdal_array.flip_code(out_dt)))

    # Copy data for output
    lutdata = data.copy().astype(out_dt)
    # Apply lut
    for key, value in lut.iteritems():
        np.place(lutdata, data == key, value)

    # Write to output
    driver = gdal.GetDriverByName(format)
    dst_ds = driver.Create(output, 
                           src_ds.RasterXSize, src_ds.RasterYSize, 1,
                           gdal_array.flip_code(out_dt))
    dst_ds.SetProjection(src_ds.GetProjection())
    dst_ds.SetGeoTransform(src_ds.GetGeoTransform())
    dst_ds.GetRasterBand(1).WriteArray(lutdata)
    # Close
    src_ds = None
    dst_ds = None
    print 'Wrote output to file {0}'.format(output)
Beispiel #17
0
def read(raster,
         geom=None,
         band_list=None,
         dtype=None,
         resample_alg=GRIORA_NearestNeighbour):
    raster = _open_raster(raster)
    if not isinstance(raster, gdal.Dataset):
        raise ValueError('invalid informed `raster` argument.')
    if raster.RasterCount < 1:
        raise ValueError('informed `raster` has no bands')

    # calculate the interested area
    geotransform = GeoTransform(*raster.GetGeoTransform())
    if geom is None:
        x_off, y_off, x_size, y_size = 0, 0, raster.RasterXSize, raster.RasterYSize
    else:
        geom_raster = geotransform.transform(
            geometry.box(0, 0, raster.RasterXSize, raster.RasterYSize))
        intersection = geom_raster.intersection(geom)
        if intersection.is_empty:
            raise ValueError('`geom` do not intersects with `raster`.')

        # get offset to read from raster
        x_off, y_off, x_size, y_size = tuple(
            map(int,
                geotransform.get_inverse().transform(intersection).bounds))
        x_size, y_size = x_size - x_off, y_size - y_off

        # update resulting geotransform
        x_ul, y_min, _, y_max = intersection.exterior.bounds
        y_ul = y_max if geotransform.y_res < 0 else y_min

        geotransform = GeoTransform(x_ul, geotransform.x_res,
                                    geotransform.x_skew, y_ul,
                                    geotransform.y_skew, geotransform.y_res)
    bands = raster.RasterCount if band_list is None else len(band_list)

    # prepare raster buffer: get buffer strides
    if dtype is None:
        dtype = gdal_array.flip_code(raster.GetRasterBand(1).DataType)
    sizeof_dtype = numpy.dtype(dtype).itemsize
    line_space, pixel_space, band_space = sizeof_dtype * x_size * bands, sizeof_dtype * bands, sizeof_dtype

    # read to buffer
    buffer = raster.ReadRaster(xoff=x_off,
                               yoff=y_off,
                               xsize=x_size,
                               ysize=y_size,
                               buf_type=gdal_array.flip_code(
                                   numpy.dtype(dtype)),
                               buf_xsize=x_size,
                               buf_ysize=y_size,
                               band_list=band_list,
                               buf_pixel_space=pixel_space,
                               buf_line_space=line_space,
                               buf_band_space=band_space,
                               resample_alg=resample_alg)
    array = numpy.fromstring(buffer, dtype=dtype)
    array.shape = (y_size, x_size, -1)
    return GeoArray(array,
                    geotransform,
                    proj_origin=raster.GetProjection(),
                    **raster.GetMetadata_Dict())