Source code for oceanum.datamesh.query

import datetime
import orjson
import pandas as pd
import numpy as np
from pydantic import BaseModel, Field
from typing import Optional, Dict, Union, List
from enum import Enum
from geojson_pydantic import Feature, FeatureCollection


def _orjson_dumps(val, *, default):
    return orjson.dumps(val, default=default).decode()


[docs]class QueryError(Exception): pass
[docs]class Timestamp(pd.Timestamp): @classmethod def __get_validators__(cls): yield cls.validate
[docs] @classmethod def validate(cls, v): if not (isinstance(v, str) or isinstance(v, datetime.datetime)): raise TypeError("datetime or time string required") try: return cls(v, tz="UTC").tz_convert(None).to_datetime64() except: raise "Timestamp format not valid"
[docs]class GeoFilterType(Enum): # datasource = "datasource" feature = "feature" radius = "radius" bbox = "bbox"
[docs]class TimeFilterType(str, Enum): range = "range"
[docs]class ResampleType(str, Enum): mean = "mean"
[docs]class DatasourceGeom(BaseModel): id: str = Field(title="Datasource ID") parameters: Optional[Dict] = Field( title="Optional parameters to access datasource", default={} )
[docs]class GeoFilter(BaseModel): """GeoFilter class Describes a spatial subset or interpolation """ type: GeoFilterType = Field( title="Geofilter type", default=GeoFilterType.bbox, description=""" Type of the geofilter. Can be one of: - 'feature': Select with a geojson feature - 'bbox': Select with a bounding box - 'radius': Select within radius of point """, ) geom: Union[List, Feature] = Field( title="Selection geometry", description=""" - For type='feature', geojson feature. - For type='bbox', list[x_min,y_min,x_max,y_max] in CRS units. - For type='radius', list[x0,y0,radius] in CRS units. """, ) resolution: Optional[float] = Field( title="Maximum spatial resolution of data", default=0.0, description="Maximum resolution of the data for downsampling in CRS units", )
[docs]class TimeFilter(BaseModel): """TimeFilter class Describes a temporal subset or interpolation """ type: TimeFilterType = Field( title="Timefilter type", default=TimeFilterType.range, description=""" Type of the timefilter. Can be one of: - 'range': Select times within a range """, ) times: List[Union[Timestamp, None]] = Field( title="Selection times", description=""" - For type='range', [timestart, tend]. """, ) resolution: Optional[str] = Field( title="Temporal resolution of data", default="native", description="Maximum resolution of the data for temporal downsampling. Only valid with range type", ) resample: Optional[ResampleType] = Field( title="Temporal resampling method", default=ResampleType.mean, description="Resampling method applied when reducing tempral resolution. Only valid with range type", )
# Geofilter selection process # a features select can either be a Feature/FeatureCollection or the geometry of another datasource # grid ∩ bbox -> subgrid (optional resolution) # grid ∩ feature -> feature with added properties from grid interpolated onto the geometry # geodf ∩ bbox -> clipped geodf (optional resolution) # geodf ∩ feature -> intersecting features from geodf (optional resolution) # Dataframe with x and y coordinates will be supported (not implemented yet) # df ∩ bbox -> subset df within bbox # df ∩ features -> subset of df within (resolution) of features
[docs]class Query(BaseModel): """ Datamesh query """ datasource: str = Field( title="The id of the datasource", description="Datasource ID" ) parameters: Optional[Dict] = Field( title="Datasource parameters", default={}, description="Dictionary of driver parameters to pass to datasource", ) description: Optional[str] = Field( title="Optional description of this query", default=None, description="Human readable description of this query", ) variables: Optional[List[str]] = Field( title="List of selected variables", default=None, description="List of requested variables.", ) timefilter: Optional[TimeFilter] = Field( title="Time filter", default=None, description="Temporal filter or interplator", ) geofilter: Optional[GeoFilter] = Field( title="Spatial filter or interpolator", default=None ) crs: Optional[Union[str, int]] = Field( title="Spatial reference for filter and output", default="EPSG:4326", description="Valid CRS string for returned data", ) class Config: json_loads = orjson.loads json_dumps = _orjson_dumps json_encoders = {np.datetime64: str}