def tiles_from_geopolygon( self, geopolygon: geometry.Geometry, tile_buffer: Optional[Tuple[float, float]] = None, geobox_cache: Optional[dict] = None ) -> Iterator[Tuple[Tuple[int, int], geometry.GeoBox]]: """ Returns an iterator of tile_index, :py:class:`GeoBox` tuples across the grid and overlapping with the specified `geopolygon`. .. note:: Grid cells are referenced by coordinates `(x, y)`, which is the opposite to the usual CRS dimension order. :param geometry.Geometry geopolygon: Polygon to tile :param tile_buffer: Optional <float,float> tuple, (extra padding for the query in native units of this GridSpec) :param dict geobox_cache: Optional cache to re-use geoboxes instead of creating new one each time :return: iterator of grid cells with :py:class:`GeoBox` tiles """ geopolygon = geopolygon.to_crs(self.crs) bbox = geopolygon.boundingbox bbox = bbox.buffered(*tile_buffer) if tile_buffer else bbox for tile_index, tile_geobox in self.tiles(bbox, geobox_cache): tile_geobox = tile_geobox.buffered( *tile_buffer) if tile_buffer else tile_geobox if geometry.intersects(tile_geobox.extent, geopolygon): yield (tile_index, tile_geobox)
def select_datasets_inside_polygon(datasets, polygon): # Check against the bounding box of the original scene, can throw away some portions assert polygon is not None query_crs = polygon.crs for dataset in datasets: if intersects(polygon, dataset.extent.to_crs(query_crs)): yield dataset
def tiles_inside_geopolygon(self, geopolygon, tile_buffer=(0, 0)): """ Returns an iterator of tile_index, :py:class:`GeoBox` tuples across the grid and inside the specified `polygon`. .. note:: Grid cells are referenced by coordinates `(x, y)`, which is the opposite to the usual CRS dimension order. :param geometry.Geometry geopolygon: Polygon to tile :param tile_buffer: :return: iterator of grid cells with :py:class:`GeoBox` tiles """ result = [] geopolygon = geopolygon.to_crs(self.crs) for tile_index, tile_geobox in self.tiles( geopolygon.boundingbox.buffered(*tile_buffer)): if tile_buffer: tile_geobox = tile_geobox.buffered(*tile_buffer) if intersects(tile_geobox.extent, geopolygon): result.append((tile_index, tile_geobox)) return result
def cell_observations(self, cell_index=None, geopolygon=None, tile_buffer=None, **indexers): """ List datasets, grouped by cell. :param datacube.utils.Geometry geopolygon: Only return observations with data inside polygon. :param (float,float) tile_buffer: buffer tiles by (y, x) in CRS units :param (int,int) cell_index: The cell index. E.g. (14, -40) :param indexers: Query to match the datasets, see :py:class:`datacube.api.query.Query` :return: Datsets grouped by cell index :rtype: dict[(int,int), list[:py:class:`datacube.model.Dataset`]] .. seealso:: :meth:`datacube.Datacube.find_datasets` :class:`datacube.api.query.Query` """ # pylint: disable=too-many-locals # TODO: split this method into 3: cell/polygon/unconstrained querying if tile_buffer is not None and geopolygon is not None: raise ValueError('Cannot process tile_buffering and geopolygon together.') cells = {} def add_dataset_to_cells(tile_index, tile_geobox, dataset_): cells.setdefault(tile_index, {'datasets': [], 'geobox': tile_geobox})['datasets'].append(dataset_) if cell_index: assert len(cell_index) == 2 cell_index = tuple(cell_index) geobox = self.grid_spec.tile_geobox(cell_index) geobox = geobox.buffered(*tile_buffer) if tile_buffer else geobox datasets, query = self._find_datasets(geobox.extent, indexers) for dataset in datasets: if intersects(geobox.extent, dataset.extent.to_crs(self.grid_spec.crs)): add_dataset_to_cells(cell_index, geobox, dataset) return cells else: datasets, query = self._find_datasets(geopolygon, indexers) geobox_cache = {} if query.geopolygon: # Get a rough region of tiles query_tiles = set( tile_index for tile_index, tile_geobox in self.grid_spec.tiles_from_geopolygon(query.geopolygon, geobox_cache=geobox_cache)) for dataset in datasets: # Go through our datasets and see which tiles each dataset produces, and whether they intersect # our query geopolygon. dataset_extent = dataset.extent.to_crs(self.grid_spec.crs) bbox = dataset_extent.boundingbox bbox = bbox.buffered(*tile_buffer) if tile_buffer else bbox for tile_index, tile_geobox in self.grid_spec.tiles(bbox, geobox_cache=geobox_cache): if tile_index in query_tiles and intersects(tile_geobox.extent, dataset_extent): add_dataset_to_cells(tile_index, tile_geobox, dataset) else: for dataset in datasets: for tile_index, tile_geobox in self.grid_spec.tiles_from_geopolygon(dataset.extent, tile_buffer=tile_buffer, geobox_cache=geobox_cache): add_dataset_to_cells(tile_index, tile_geobox, dataset) return cells
def select_datasets_inside_polygon(datasets, polygon): # Check against the bounding box of the original scene, can throw away some portions for dataset in datasets: if polygon is None or intersects(polygon.to_crs(dataset.crs), dataset.extent): yield dataset