data-access/nexustiles/AbstractTileService.py (79 lines of code) (raw):

# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from abc import ABC, abstractmethod from functools import reduce import numpy as np import numpy.ma as ma class AbstractTileService(ABC): def __init__(self, dataset_name): self._name = dataset_name def heartbeat(self) -> bool: return True @abstractmethod def get_dataseries_list(self, simple=False): raise NotImplementedError() @abstractmethod def find_tile_by_id(self, tile_id, **kwargs): raise NotImplementedError() @abstractmethod def find_tiles_by_id(self, tile_ids, ds=None, **kwargs): raise NotImplementedError() @abstractmethod def find_days_in_range_asc(self, min_lat, max_lat, min_lon, max_lon, dataset, start_time, end_time, metrics_callback=None, **kwargs): raise NotImplementedError() @abstractmethod def find_tile_by_polygon_and_most_recent_day_of_year(self, bounding_polygon, ds, day_of_year, **kwargs): """ Given a bounding polygon, dataset, and day of year, find tiles in that dataset with the same bounding polygon and the closest day of year. For example: given a polygon minx=0, miny=0, maxx=1, maxy=1; dataset=MY_DS; and day of year=32 search for first tile in MY_DS with identical bbox and day_of_year <= 32 (sorted by day_of_year desc) Valid matches: minx=0, miny=0, maxx=1, maxy=1; dataset=MY_DS; day of year = 32 minx=0, miny=0, maxx=1, maxy=1; dataset=MY_DS; day of year = 30 Invalid matches: minx=1, miny=0, maxx=2, maxy=1; dataset=MY_DS; day of year = 32 minx=0, miny=0, maxx=1, maxy=1; dataset=MY_OTHER_DS; day of year = 32 minx=0, miny=0, maxx=1, maxy=1; dataset=MY_DS; day of year = 30 if minx=0, miny=0, maxx=1, maxy=1; dataset=MY_DS; day of year = 32 also exists :param bounding_polygon: The exact bounding polygon of tiles to search for :param ds: The dataset name being searched :param day_of_year: Tile day of year to search for, tile nearest to this day (without going over) will be returned :return: List of one tile from ds with bounding_polygon on or before day_of_year or raise NexusTileServiceException if no tile found """ raise NotImplementedError() @abstractmethod def find_all_tiles_in_box_at_time(self, min_lat, max_lat, min_lon, max_lon, dataset, time, **kwargs): raise NotImplementedError() @abstractmethod def find_all_tiles_in_polygon_at_time(self, bounding_polygon, dataset, time, **kwargs): raise NotImplementedError() @abstractmethod def find_tiles_in_box(self, min_lat, max_lat, min_lon, max_lon, ds=None, start_time=0, end_time=-1, **kwargs): # Find tiles that fall in the given box in the Solr index raise NotImplementedError() @abstractmethod def find_tiles_in_polygon(self, bounding_polygon, ds=None, start_time=0, end_time=-1, **kwargs): # Find tiles that fall within the polygon in the Solr index raise NotImplementedError() @abstractmethod def find_tiles_by_metadata(self, metadata, ds=None, start_time=0, end_time=-1, **kwargs): """ Return list of tiles whose metadata matches the specified metadata, start_time, end_time. :param metadata: List of metadata values to search for tiles e.g ["river_id_i:1", "granule_s:granule_name"] :param ds: The dataset name to search :param start_time: The start time to search for tiles :param end_time: The end time to search for tiles :return: A list of tiles """ raise NotImplementedError() @abstractmethod def find_tiles_by_exact_bounds(self, bounds, ds, start_time, end_time, **kwargs): """ The method will return tiles with the exact given bounds within the time range. It differs from find_tiles_in_polygon in that only tiles with exactly the given bounds will be returned as opposed to doing a polygon intersection with the given bounds. :param bounds: (minx, miny, maxx, maxy) bounds to search for :param ds: Dataset name to search :param start_time: Start time to search (seconds since epoch) :param end_time: End time to search (seconds since epoch) :param kwargs: fetch_data: True/False = whether or not to retrieve tile data :return: """ raise NotImplementedError() @abstractmethod def find_all_boundary_tiles_at_time(self, min_lat, max_lat, min_lon, max_lon, dataset, time, **kwargs): raise NotImplementedError() @abstractmethod def find_tiles_along_line(self, start_point, end_point, ds=None, start_time=0, end_time=-1, **kwargs): raise NotImplementedError() @abstractmethod def get_min_max_time_by_granule(self, ds, granule_name): raise NotImplementedError() @abstractmethod def get_dataset_overall_stats(self, ds): raise NotImplementedError() @abstractmethod def get_stats_within_box_at_time(self, min_lat, max_lat, min_lon, max_lon, dataset, time, **kwargs): raise NotImplementedError() @abstractmethod def get_bounding_box(self, tile_ids): """ Retrieve a bounding box that encompasses all of the tiles represented by the given tile ids. :param tile_ids: List of tile ids :return: shapely.geometry.Polygon that represents the smallest bounding box that encompasses all of the tiles """ raise NotImplementedError() @abstractmethod def get_min_time(self, tile_ids, ds=None): """ Get the minimum tile date from the list of tile ids :param tile_ids: List of tile ids :param ds: Filter by a specific dataset. Defaults to None (queries all datasets) :return: long time in seconds since epoch """ raise NotImplementedError() @abstractmethod def get_max_time(self, tile_ids, ds=None): """ Get the maximum tile date from the list of tile ids :param tile_ids: List of tile ids :param ds: Filter by a specific dataset. Defaults to None (queries all datasets) :return: long time in seconds since epoch """ raise NotImplementedError() @abstractmethod def get_distinct_bounding_boxes_in_polygon(self, bounding_polygon, ds, start_time, end_time): """ Get a list of distinct tile bounding boxes from all tiles within the given polygon and time range. :param bounding_polygon: The bounding polygon of tiles to search for :param ds: The dataset name to search :param start_time: The start time to search for tiles :param end_time: The end time to search for tiles :return: A list of distinct bounding boxes (as shapely polygons) for tiles in the search polygon """ raise NotImplementedError() @abstractmethod def get_tile_count(self, ds, bounding_polygon=None, start_time=0, end_time=-1, metadata=None, **kwargs): """ Return number of tiles that match search criteria. :param ds: The dataset name to search :param bounding_polygon: The polygon to search for tiles :param start_time: The start time to search for tiles :param end_time: The end time to search for tiles :param metadata: List of metadata values to search for tiles e.g ["river_id_i:1", "granule_s:granule_name"] :return: number of tiles that match search criteria """ raise NotImplementedError() @abstractmethod def fetch_data_for_tiles(self, *tiles): raise NotImplementedError() @abstractmethod def _metadata_store_docs_to_tiles(self, *store_docs): raise NotImplementedError()