Exemplo n.º 1
0
def write_fc_band_tile(fc, key, filename):
    slim_dataset = fc[[key]]  # create a one band dataset
    attrs = slim_dataset[key].attrs.copy()  # To get nodata in
    del attrs['crs']  # It's format is poor
    del attrs['units']  # It's format is poor
    slim_dataset[key] = fc.data_vars[key].astype('int16', copy=True)
    output_filename = filename + key + '_' + str(tile_no) + '_TEMP' + '.tif'
    write_geotiff(output_filename, slim_dataset, profile_override=attrs)
    return output_filename
Exemplo n.º 2
0
def _save(ds, name):
    """
    saves xarray as a local file

    :param xarray ds: An xarray
    :param str name: the file path including filename
    """
    logging.debug(ds)
    logging.info('Writing file: %s', name)
    helpers.write_geotiff(name, ds)
Exemplo n.º 3
0
def test_write_geotiff(tmpdir, odc_style_xr_dataset):
    """Ensure the geotiff helper writer works, and supports datasets smaller than 256x256."""
    filename = tmpdir + '/test.tif'

    assert len(odc_style_xr_dataset.latitude) < 256

    write_geotiff(filename, odc_style_xr_dataset)

    assert filename.exists()

    with rasterio.open(str(filename)) as src:
        written_data = src.read(1)

        assert (written_data == odc_style_xr_dataset['B10']).all()
Exemplo n.º 4
0
def test_write_geotiff_str_crs(tmpdir, odc_style_xr_dataset):
    """Ensure the geotiff helper writer works, and supports crs as a string."""
    filename = tmpdir + '/test.tif'

    original_crs = odc_style_xr_dataset.crs

    odc_style_xr_dataset.attrs['crs'] = str(original_crs)
    write_geotiff(filename, odc_style_xr_dataset)
    assert filename.exists()

    with rasterio.open(str(filename)) as src:
        written_data = src.read(1)

        assert (written_data == odc_style_xr_dataset['B10']).all()

    del odc_style_xr_dataset.attrs['crs']
    with pytest.raises(ValueError):
        write_geotiff(filename, odc_style_xr_dataset)
Exemplo n.º 5
0
def convert_to_tiff(filename, var=None, outputdir='geotiff'):
    if var is None:
        ds = xr.open_dataset(filename)
        varnames = list(ds.data_vars)
        if None in varnames:
            raise ValueError(varnames)
    else:
        ds = xr.open_dataset(filename)
        varnames = [var]
    for var in varnames:
        outputname = '%s/%s' % (outputdir, filename.split('/')[-1].replace(
            '.nc', '_%s.tif' % var.lower()))
        if os.path.exists(outputname): continue
        #print(outputname)
        try:
            ds_output = ds[var].to_dataset(name=var)
        except:
            print(ds.data_vars)
        #ds_output = ds_output.sortby('y', ascending=False)
    #ds = ds.astype('float64')
        ds_output.attrs['crs'] = geometry.CRS('EPSG:3577')
        #print(ds)
        helpers.write_geotiff(outputname, ds_output)
    return varnames
Exemplo n.º 6
0
def dataset_to_geotif_yaml(dataset: xarray.Dataset,
                           odc_dataset: Dataset,
                           filename: Union[Path, str],
                           variable_params=None):
    """
    Write the dataset out as a set of geotifs with metadata in a yaml file.
    There will be one geotiff file per band.
    The band name is added into the file name.
    i.e ls8_fc.tif -> ls8_fc_BS.tif

    :param dataset:
    :param filename: Output filename
    :param variable_params: dict of variable_name: {param_name: param_value, [...]}
                            Used to get band names.

    """

    bands = variable_params.keys()
    abs_paths, _, yml = tif_filenames(filename, bands)

    Path(filename).parent.mkdir(parents=True, exist_ok=True)

    # Write out the yaml file
    with fileutils.atomic_save(str(yml)) as stream:
        yaml.safe_dump(odc_dataset.metadata_doc, stream, encoding='utf8')

    # Iterate over the bands
    for key, bandfile in abs_paths.items():
        slim_dataset = dataset[[key]]  # create a one band dataset
        attrs = slim_dataset[key].attrs.copy()  # To get nodata in
        del attrs['crs']  # It's  format is poor
        del attrs['units']  # It's  format is poor
        slim_dataset[key] = dataset.data_vars[key].astype('int16', copy=True)
        write_geotiff(bandfile,
                      slim_dataset.isel(time=0),
                      profile_override=attrs)
Exemplo n.º 7
0
query_2 = {
    "x": (central_lon - buffer, central_lon + buffer),
    "y": (central_lat - buffer, central_lat + buffer),
    "time": (postfire_start, postfire_end),
    "output_crs": "EPSG:32755",
    "resolution": (-10, 10)
}

postfire_data = load_ard(
    dc=dc,
    products=['s2a_ard_granule', 's2b_ard_granule'],
    measurements=['nbart_nir_1', 'nbart_swir_3'],
    min_gooddata=0,
    # dask_chunks={'x': 'auto', 'y': 'auto'},
    group_by='solar_day',
    **query_2)

postfire_image = postfire_data.median(dim='time')
postfire_image = calculate_indices(postfire_image,
                                   index='NBR',
                                   collection='ga_s2_1',
                                   drop=False)
postfire_burnratio = postfire_image.NBR
postfire_burnratio.data

delta_NBR = prefire_burnratio - postfire_burnratio
# delta_NBR.compute()
dnbr_dataset = delta_NBR.to_dataset(name='delta_NBR')
write_geotiff(f'./scratch/wj97/ab4513/tumbarumba_dNBR_full.tif', dnbr_dataset)
def xr_rasterize(gdf,
                 da,
                 attribute_col=False,
                 crs=None,
                 transform=None,
                 name=None,
                 x_dim='x',
                 y_dim='y',
                 export_tiff=None,
                 **rasterio_kwargs):
    """
    Rasterizes a geopandas.GeoDataFrame into an xarray.DataArray.
    
    Parameters
    ----------
    gdf : geopandas.GeoDataFrame
        A geopandas.GeoDataFrame object containing the vector/shapefile
        data you want to rasterise.
    da : xarray.DataArray or xarray.Dataset
        The shape, coordinates, dimensions, and transform of this object 
        are used to build the rasterized shapefile. It effectively 
        provides a template. The attributes of this object are also 
        appended to the output xarray.DataArray.
    attribute_col : string, optional
        Name of the attribute column in the geodataframe that the pixels 
        in the raster will contain.  If set to False, output will be a 
        boolean array of 1's and 0's.
    crs : str, optional
        CRS metadata to add to the output xarray. e.g. 'epsg:3577'.
        The function will attempt get this info from the input 
        GeoDataFrame first.
    transform : affine.Affine object, optional
        An affine.Affine object (e.g. `from affine import Affine; 
        Affine(30.0, 0.0, 548040.0, 0.0, -30.0, "6886890.0) giving the 
        affine transformation used to convert raster coordinates 
        (e.g. [0, 0]) to geographic coordinates. If none is provided, 
        the function will attempt to obtain an affine transformation 
        from the xarray object (e.g. either at `da.transform` or
        `da.geobox.transform`).
    x_dim : str, optional
        An optional string allowing you to override the xarray dimension 
        used for x coordinates. Defaults to 'x'. Useful, for example, 
        if x and y dims instead called 'lat' and 'lon'.   
    y_dim : str, optional
        An optional string allowing you to override the xarray dimension 
        used for y coordinates. Defaults to 'y'. Useful, for example, 
        if x and y dims instead called 'lat' and 'lon'.
    export_tiff: str, optional
        If a filepath is provided (e.g 'output/output.tif'), will export a
        geotiff file. A named array is required for this operation, if one
        is not supplied by the user a default name, 'data', is used
    **rasterio_kwargs : 
        A set of keyword arguments to rasterio.features.rasterize
        Can include: 'all_touched', 'merge_alg', 'dtype'.
    
    Returns
    -------
    xarr : xarray.DataArray
    
    """

    # Check for a crs object
    try:
        crs = da.geobox.crs
    except:
        try:
            crs = da.crs
        except:
            if crs is None:
                raise Exception(
                    "Please add a `crs` attribute to the "
                    "xarray.DataArray, or provide a CRS using the "
                    "function's `crs` parameter (e.g. crs='EPSG:3577')")

    # Check if transform is provided as a xarray.DataArray method.
    # If not, require supplied Affine
    if transform is None:
        try:
            # First, try to take transform info from geobox
            transform = da.geobox.transform
        # If no geobox
        except:
            try:
                # Try getting transform from 'transform' attribute
                transform = da.transform
            except:
                # If neither of those options work, raise an exception telling the
                # user to provide a transform
                raise Exception(
                    "Please provide an Affine transform object using the "
                    "`transform` parameter (e.g. `from affine import "
                    "Affine; Affine(30.0, 0.0, 548040.0, 0.0, -30.0, "
                    "6886890.0)`")

    # Grab the 2D dims (not time)
    try:
        dims = da.geobox.dims
    except:
        dims = y_dim, x_dim

    # Coords
    xy_coords = [da[dims[0]], da[dims[1]]]

    # Shape
    try:
        y, x = da.geobox.shape
    except:
        y, x = len(xy_coords[0]), len(xy_coords[1])

    # Reproject shapefile to match CRS of raster
    print(f'Rasterizing to match xarray.DataArray dimensions ({y}, {x}) '
          f'and projection system/CRS (e.g. {crs})')

    try:
        gdf_reproj = gdf.to_crs(crs=crs)
    except:
        # Sometimes the crs can be a datacube utils CRS object
        # so convert to string before reprojecting
        gdf_reproj = gdf.to_crs(crs={'init': str(crs)})

    # If an attribute column is specified, rasterise using vector
    # attribute values. Otherwise, rasterise into a boolean array
    if attribute_col:
        # Use the geometry and attributes from `gdf` to create an iterable
        shapes = zip(gdf_reproj.geometry, gdf_reproj[attribute_col])
    else:
        # Use geometry directly (will produce a boolean numpy array)
        shapes = gdf_reproj.geometry

    # Rasterise shapes into an array
    arr = rasterio.features.rasterize(shapes=shapes,
                                      out_shape=(y, x),
                                      transform=transform,
                                      **rasterio_kwargs)

    # Convert result to a xarray.DataArray
    xarr = xr.DataArray(arr,
                        coords=xy_coords,
                        dims=dims,
                        attrs=da.attrs,
                        name=name if name else None)

    # Add back crs if xarr.attrs doesn't have it
    if 'crs' not in xarr.attrs:
        xarr.attrs['crs'] = str(crs)

    if export_tiff:
        print(f"Exporting GeoTIFF to {export_tiff}")
        ds = xarr.to_dataset(name=name if name else 'data')
        ds.attrs = xarr.attrs  # xarray bug removes metadata, add it back
        write_geotiff(export_tiff, ds)

    return xarr
Exemplo n.º 9
0
def test_write_geotiff_time_index_deprecated():
    """The `time_index` parameter to `write_geotiff()` was a poorly thought out addition and is now deprecated."""

    with pytest.raises(ValueError):
        write_geotiff("", None, time_index=1)
Exemplo n.º 10
0
def _save(ds, name):
    helpers.write_geotiff(name, ds)
Exemplo n.º 11
0
tv = tv_mask.where(data['PV'] > 0)
# Calculate the proportion of time where total vegetation is greater than the bare soil fraction of a pixel
# for the input year
tv_summary = tv.mean(dim='time', skipna=True)
# Create a boolean layer where vegetation is assigned if greater than .167
# tv_summary_filt = tv_summary > .167
# Convert booleans to binary
# tv_summary_filt = tv_summary_filt * 1
# Change data type to float
# tv_summary_filt = tv_summary_filt.data.astype(float)

meta_d = data.isel(time=0).drop('time')
out = xr.Dataset({'fc_summary': (meta_d.dims, tv_summary)},
                 coords=meta_d.coords,
                 attrs=meta_d.attrs)
helpers.write_geotiff('testarea_pvfcsummary.tif', out)

tv_mask = data['BS'] < data['NPV']
tv = tv_mask.where(data['NPV'] > 0)
# Calculate the proportion of time where total vegetation is greater than the bare soil fraction of a pixel
# for the input year
tv_summary = tv.mean(dim='time')
# Create a boolean layer where vegetation is assigned if greater than .167
# tv_summary_filt = tv_summary > .167
# Convert booleans to binary
# tv_summary_filt = tv_summary_filt * 1
# Change data type to float
# tv_summary_filt = tv_summary_filt.data.astype(float)

meta_d = data.isel(time=0).drop('time')
out = xr.Dataset({'fc_summary': (meta_d.dims, tv_summary)},
Exemplo n.º 12
0
dc = datacube.Datacube(config='/g/data/u46/users/sc0554/datacube.conf')

# x = (1500000, 1600000)
# y = (-4000000, -3900000)
x = (1199685, 1299651)
y = (-3800197, -3700025)
product = 'fc'
query = {'time': ('2015-01-01', '2015-12-31')}
query['x'] = (x[0], x[1])
query['y'] = (y[0], y[1])
query['crs'] = 'EPSG:3577'

mask_dict = {
    'cloud_acca': 'no_cloud',
    'cloud_fmask': 'no_cloud',
    'contiguous': True
}

data = DEADataHandling.load_clearlandsat(dc=dc,
                                         query=query,
                                         product=product,
                                         masked_prop=0.1,
                                         mask_dict=mask_dict,
                                         satellite_metadata=True)

meta_d = data.isel(time=0).drop('time')
out = xr.Dataset({'fc': (meta_d.dims, data)},
                 coords=meta_d.coords,
                 attrs=meta_d.attrs)
helpers.write_geotiff('testarea.tif', out)
Exemplo n.º 13
0
def dNBR_processing(coordinates):

    # Load all data in baseline period available from s2a/b_ard_granule datasets
    prefire_ard = load_ard(
        dc=dc,
        products=['s2a_ard_granule', 's2b_ard_granule'],
        x=(coordinates.x - 0.1, coordinates.x + 0.1),
        y=(coordinates.y - 0.1, coordinates.y + 0.1),
        time=(prefire_start, prefire_end),
        measurements=['nbart_nir_1', 'nbart_swir_3'],
        min_gooddata=0.1,
        output_crs='EPSG:32755',  # UTM Zone 55S
        resolution=(-10, 10),
        group_by='solar_day')

    prefire_ard = calculate_indices(prefire_ard,
                                    index='NBR',
                                    collection='ga_s2_1',
                                    drop=False)

    # Compute median using all observations in the dataset along the time axis
    prefire_image = prefire_ard.median(dim='time')

    # Delete baseline_combined
    del prefire_ard

    # Select NBR
    prefire_NBR = prefire_image.NBR

    del prefire_image

    # Load all data in post-fire period available from s2a/b_ard_granule datasets
    postfire_ard = load_ard(
        dc=dc,
        products=['s2a_ard_granule', 's2b_ard_granule'],
        x=(coordinates.x - 0.1, coordinates.x + 0.1),
        y=(coordinates.y - 0.1, coordinates.y + 0.1),
        time=(postfire_start, postfire_end),
        measurements=['nbart_nir_1', 'nbart_swir_3'],
        min_gooddata=0.1,
        output_crs='EPSG:32755',  # UTM Zone 55S
        resolution=(-10, 10),
        group_by='solar_day')

    # Calculate NBR on all post-fire images
    postfire_ard = calculate_indices(postfire_ard,
                                     index='NBR',
                                     collection='ga_s2_1',
                                     drop=False)

    # Calculate the median post-fire image
    postfire_image = postfire_ard.median(dim='time')

    del postfire_ard

    # Select NBR
    postfire_NBR = postfire_image.NBR

    del postfire_image

    # Calculate delta
    delta_NBR = prefire_NBR - postfire_NBR

    del prefire_NBR
    del postfire_NBR

    x = np.round_(coordinates.x, decimals=4)
    y = np.round_(coordinates.y, decimals=4)

    # Turn dNBR into a x-array dataset for export to GeoTIFF
    dnbr_dataset = delta_NBR.to_dataset(name='delta_NBR')
    # cog.write_cog(dnbr_dataset, './NBR_geotiffs/{x}_{y}_dNBR.tif')
    write_geotiff(f'/scratch/wj97/ab4513/dNBR_geotiffs/{x}_{y}_dNBR.tif',
                  dnbr_dataset)

    del delta_NBR
    del dnbr_dataset