def mk_sample_xr_dataset(crs="EPSG:3578", shape=(33, 74), resolution=None, xy=(0, 0), time='2020-02-13T11:12:13.1234567Z', name='band', dtype='int16', nodata=-999, units='1'): """ Note that resolution is in Y,X order to match that of GeoBox. shape (height, width) resolution (y: float, x: float) - in YX, to match GeoBox/shape notation xy (x: float, y: float) -- location of the top-left corner of the top-left pixel in CRS units """ if isinstance(crs, str): crs = CRS(crs) if resolution is None: resolution = (-10, 10) if crs is None or crs.projected else (-0.01, 0.01) t_coords = {} if time is not None: t_coords['time'] = mk_time_coord([time]) transform = Affine.translation(*xy)*Affine.scale(*resolution[::-1]) h, w = shape geobox = GeoBox(w, h, transform, crs) return Datacube.create_storage(t_coords, geobox, [Measurement(name=name, dtype=dtype, nodata=nodata, units=units)])
def odc_style_xr_dataset(): """An xarray.Dataset with ODC style coordinates and CRS, and no time dimension. Contains an EPSG:4326, single variable 'B10' of 100x100 int16 pixels.""" affine = Affine.scale(0.1, 0.1) * Affine.translation(20, 30) geobox = geometry.GeoBox(100, 100, affine, geometry.CRS(GEO_PROJ)) return Datacube.create_storage({}, geobox, [Measurement(name='B10', dtype='int16', nodata=0, units='1')])
def fractional_cover(nbar_tile, measurements=None, regression_coefficients=None): """ Given a tile of spectral observations compute the fractional components. The data should be a 2D array :param xarray.Dataset nbar_tile: A dataset with the following data variables (0-10000): * green * red * nir * swir1 * swir2 :param list(dict) measurements: A list of measurement item dicts, each containing: * name - name of output data_var * src_var - (optional) if `name` is not one of `['PV', 'NPV', 'BS', 'UE']`, use one of them here * dtype - dtype to use, eg `'int8'` * nodata - value to fill in for no data, eg `-1` * units' - eg `'percent'` :param dict regression_coefficients: A dictionary with six pairs of coefficients to apply to the green, red, nir, swir1 and swir2 values (blue is not used) :return: An xarray.Dataset containing: * Green vegetation (PV) * Non-green vegetation (NPV) * Bare soil (BS) * Unmixing error (UE) :rtype: xarray.Dataset """ if measurements is None: measurements = DEFAULT_MEASUREMENTS # Ensure the bands are all there and in the right order nbar_tile = nbar_tile[['green', 'red', 'nir', 'swir1', 'swir2']] # Set nodata to 0 no_data = 0 is_valid_array = valid_data_mask(nbar_tile).to_array(dim='band').all( dim='band') nbar = nbar_tile.to_array(dim='band') nbar.data[:, ~is_valid_array.data] = no_data output_data = compute_fractions(nbar.data, regression_coefficients) def data_func(measurement): band_names = ['PV', 'NPV', 'BS', 'UE'] src_var = measurement.get('src_var', None) or measurement.get('name') i = band_names.index(src_var) # Set nodata value into output array band_nodata = numpy.dtype(measurement['dtype']).type( measurement['nodata']) compute_error = (output_data[i, :, :] == -1) output_data[i, compute_error] = band_nodata output_data[i, ~is_valid_array.data] = band_nodata return output_data[i, :, :] dataset = Datacube.create_storage({}, nbar_tile.geobox, measurements, data_func) return dataset
def fractional_cover( nbar_tile: xarray.Dataset, measurements: Sequence[Measurement] = None, regression_coefficients: Mapping[str, Sequence[int]] = None) -> xarray.Dataset: """ Given a tile of spectral observations compute the fractional components. The data should be a 2D array :param nbar_tile: A dataset with the following data variables (0-10000): * green * red * nir * swir1 * swir2 :param measurements: A list of Measurements, each containing: * name - name of output data_var * src_var - (optional) if `name` is not one of `['PV', 'NPV', 'BS', 'UE']`, use one of them here * dtype - dtype to use, eg `'int8'` * nodata - value to fill in for no data, eg `-1` * units' - eg `'percent'` :param regression_coefficients: A dictionary with six pairs of coefficients to apply to the green, red, nir, swir1 and swir2 values (blue is not used) :return: An xarray.Dataset containing: * Green vegetation (PV) * Non-green vegetation (NPV) * Bare soil (BS) * Unmixing error (UE) :rtype: xarray.Dataset """ if measurements is None: measurements = DEFAULT_MEASUREMENTS # Ensure the bands are all there and in the right order nbar_tile = nbar_tile[['green', 'red', 'nir', 'swir1', 'swir2']] # Set nodata to 0 no_data = 0 is_valid_array = valid_data_mask(nbar_tile).to_array(dim='band').all( dim='band') nbar = nbar_tile.to_array(dim='band') nbar = nbar.where(is_valid_array, no_data) output_data = compute_fractions(nbar.data, regression_coefficients) error_val = -1 where = numpy.where if not isinstance( output_data, dask_array_type) else dask.array.where def data_func(measurement): band_names = ['PV', 'NPV', 'BS', 'UE'] src_var = measurement.get('src_var', None) or measurement.get('name') i = band_names.index(src_var.upper()) unmasked_var = output_data[i] # Set nodata value into output array band_nodata = numpy.dtype(measurement['dtype']).type( measurement['nodata']) no_error = (unmasked_var != error_val) return where(is_valid_array.data & no_error, unmasked_var, band_nodata) dataset = Datacube.create_storage({}, nbar_tile.geobox, measurements, data_func) return dataset