def compute_grid_info(cells: Dict[TileIdx_xy, Any], resolution: float = math.inf, title_width: int = 0) -> Dict[TileIdx_xy, Any]: """ Compute geojson feature for every cell in ``cells``. Where ``cells`` is produced by ``odc.index.bin_dataset_stream`` """ if title_width == 0: nmax = max([max(abs(ix), abs(iy)) for ix, iy in cells]) # title_width is the number of digits in the index, +1 for positive or negative title_width = len(str(nmax)) + 1 grid_info = {} for idx, cell in cells.items(): geobox = cell.geobox utc_offset = timedelta_to_hours(solar_offset(geobox.extent)) wrapdateline = utc_offset <= -11 or utc_offset >= 11 geom = geobox.extent.to_crs("epsg:4326", resolution=resolution, wrapdateline=wrapdateline) ix, iy = idx grid_info[idx] = { "type": "Feature", "geometry": geom.json, "properties": { "title": f"{ix:+0{title_width}d},{iy:+0{title_width}d}", "utc_offset": utc_offset, "total": len(cell.dss), }, } return grid_info
def compute_grid_info(cells: Dict[TileIdx_xy, Any], resolution: float = math.inf, title_width: int = 5) -> Dict[TileIdx_xy, Any]: """ Compute geojson feature for every cell in ``cells``. Where ``cells`` is produced by ``odc.index.bin_dataset_stream`` """ grid_info = {} for idx, cell in cells.items(): geobox = cell.geobox utc_offset = timedelta_to_hours(solar_offset(geobox.extent)) wrapdateline = (utc_offset <= -11 or utc_offset >= 11) geom = geobox.extent.to_crs('epsg:4326', resolution=resolution, wrapdateline=wrapdateline) ix, iy = idx grid_info[idx] = { 'type': 'Feature', 'geometry': geom.json, 'properties': { 'title': f'{ix:+0{title_width}d},{iy:+0{title_width}d}', 'utc_offset': utc_offset, 'total': len(cell.dss), }, } return grid_info
def load_with_native_transform(dss: List[Dataset], bands: Tuple[str, ...], geobox: GeoBox, native_transform: Callable[[xr.Dataset], xr.Dataset], basis: Optional[str] = None, groupby: Optional[str] = None, fuser: Optional[Callable[[xr.Dataset], xr.Dataset]] = None, resampling: str = 'nearest', chunks: Optional[Dict[str, int]] = None, load_chunks: Optional[Dict[str, int]] = None, **kw) -> xr.Dataset: """ Load a bunch of datasets with native pixel transform. :param dss: A list of datasets to load :param bands: Which measurements to load :param geobox: GeoBox of the final output :param native_transform: ``xr.Dataset -> xr.Dataset`` transform, should support Dask inputs/outputs :param basis: Name of the band to use as a reference for what is "native projection" :param groupby: One of 'solar_day'|'time'|'idx'|None :param fuser: Optional ``xr.Dataset -> xr.Dataset`` transform :param resampling: Any resampling mode supported by GDAL as a string: nearest, bilinear, average, mode, cubic, etc... :param chunks: If set use Dask, must be in dictionary form ``{'x': 4000, 'y': 4000}`` :param load_chunks: Defaults to ``chunks`` but can be different if supplied (different chunking for native read vs reproject) :param kw: Used to support old names ``dask_chunks`` and ``group_by`` 1. Partition datasets by native Projection 2. For every group do - Load data - Apply native_transform - [Optional] fuse rasters that happened on the same day/time - Reproject to final geobox 3. Stack output of (2) 4. [Optional] fuse rasters that happened on the same day/time """ if fuser is None: fuser = _nodata_fuser if groupby is None: groupby = kw.get('group_by', 'idx') if chunks is None: chunks = kw.get('dask_chunks', None) sources = group_by_nothing(dss, solar_offset(geobox.extent)) xx = [_load_with_native_transform_1(srcs, bands, geobox, native_transform, basis=basis, resampling=resampling, groupby=groupby, fuser=fuser, chunks=chunks, load_chunks=load_chunks) for srcs in _split_by_grid(sources)] if len(xx) == 1: xx = xx[0] else: xx = xr.concat(xx, sources.dims[0]) if groupby != 'idx': xx = xx.groupby(groupby).map(fuser) # TODO: probably want to replace spec MultiIndex with just `time` component return xx