Skip to content

Commit

Permalink
Extract metadata logic placeholder
Browse files Browse the repository at this point in the history
  • Loading branch information
mpiannucci committed Nov 21, 2024
1 parent 3a625ea commit 51a2744
Showing 1 changed file with 3 additions and 158 deletions.
161 changes: 3 additions & 158 deletions xpublish_edr/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@

from xpublish_edr.formats.to_covjson import to_cf_covjson
from xpublish_edr.geometry.area import select_by_area
from xpublish_edr.geometry.common import (
DEFAULT_CRS,
dataset_crs,
project_dataset,
spatial_bounds,
)
from xpublish_edr.geometry.common import project_dataset
from xpublish_edr.geometry.position import select_by_position
from xpublish_edr.logger import logger
from xpublish_edr.metadata import collection_metadata
from xpublish_edr.query import EDRQuery, edr_query


Expand All @@ -36,29 +32,6 @@ def output_formats():
return formats


def variable_description(variable: xr.DataArray):
"""
Return CF version of EDR Parameter metadata for a given xarray variable
"""
name = variable.attrs.get("name", None)
standard_name = variable.attrs.get("standard_name", name if name else "")
label = standard_name if not name else name
long_name = variable.attrs.get("long_name", "")
units = variable.attrs.get("units", "")
return {
"type": "Parameter",
"description": long_name,
"unit": {
"label": units,
},
"observedProperty": {
"label": label,
"standard_name": standard_name,
"long_name": long_name,
},
}


class CfEdrPlugin(Plugin):
"""
OGC EDR compatible endpoints for Xpublish datasets
Expand Down Expand Up @@ -117,136 +90,8 @@ def get_collection_metadata(dataset: xr.Dataset = Depends(deps.dataset)):
for the current dataset as the a single collection. See the spec for more information:
https://docs.ogc.org/is/19-086r6/19-086r6.html#_162817c2-ccd7-43c9-b1ea-ad3aea1b4d6b
"""
id = dataset.attrs.get("_xpublish_id", "unknown")
title = dataset.attrs.get("title", "unknown")
description = dataset.attrs.get("description", "no description")

crs = dataset_crs(dataset)

available_output_formats = list(output_formats().keys())

ds_cf = dataset.cf

# We will use the dataset's CRS as the default CRS, but use 4326 for the extents
# since it is always available
extent_crs = DEFAULT_CRS
projected_ds = project_dataset(dataset, DEFAULT_CRS)
bounds = spatial_bounds(projected_ds)

extents: dict = {
"spatial": {
"bbox": [bounds],
"crs": extent_crs.to_string(),
},
}

if "T" in ds_cf:
time_min = ds_cf["T"].min().dt.strftime("%Y-%m-%dT%H:%M:%S").values
time_max = ds_cf["T"].max().dt.strftime("%Y-%m-%dT%H:%M:%S").values

extents["temporal"] = {
"interval": [
str(time_min),
str(time_max),
],
"values": [
f"{time_min}/{time_max}",
],
# TODO: parse `ds.cf["time"].dt.calendar`
"trs": 'TIMECRS["DateTime",TDATUM["Gregorian Calendar"],CS[TemporalDateTime,1],AXIS["Time (T)",unspecified]]', # noqa
}

if "Z" in ds_cf:
units = ds_cf["Z"].attrs.get("units", "unknown")
positive = ds_cf["Z"].attrs.get("positive", "up")
elevations = ds_cf["Z"].values
min_z = elevations.min()
max_z = elevations.max()
elevation_values = ",".join([str(e) for e in elevations])

extents["vertical"] = {
"interval": [
min_z,
max_z,
],
"values": elevation_values,
"vrs": f"VERTCRS[VERT_CS['unknown'],AXIS['Z',{positive}],UNIT[{units},1]]", # noqa
"positive": positive,
"units": units,
}

parameters = {
k: variable_description(v)
for k, v in projected_ds.variables.items()
if "axis" not in v.attrs
}

crs_details = [
{
"crs": crs.to_string(),
"wkt": crs.to_wkt(),
},
]

# 4326 is always available
if crs != DEFAULT_CRS:
crs_details.append(
{
"crs": DEFAULT_CRS.to_string(),
"wkt": DEFAULT_CRS.to_wkt(),
},
)

return {
"id": id,
"title": title,
"description": description,
"links": [],
"extent": extents,
"data_queries": {
"position": {
"href": "/edr/position?coords={coords}",
"hreflang": "en",
"rel": "data",
"templated": True,
"variables": {
"title": "Position query",
"description": "Returns position data based on WKT `POINT(lon lat)` or `MULTIPOINT(lon lat, ...)` coordinates", # noqa
"query_type": "position",
"coords": {
"type": "string",
"description": "WKT `POINT(lon lat)` or `MULTIPOINT(lon lat, ...)` coordinates", # noqa
"required": True,
},
"output_format": available_output_formats,
"default_output_format": "cf_covjson",
"crs_details": crs_details,
},
},
"area": {
"href": "/edr/area",
"hreflang": "en",
"rel": "data",
"templated": True,
"variables": {
"title": "Area query",
"description": "Returns data in a polygon based on WKT `POLYGON(lon lat, ...)` coordinates", # noqa
"query_type": "position",
"coords": {
"type": "string",
"description": "WKT `POLYGON(lon lat, ...)` coordinates",
"required": True,
},
"output_format": available_output_formats,
"default_output_format": "cf_covjson",
"crs_details": crs_details,
},
},
},
"crs": [crs.to_string()],
"output_formats": available_output_formats,
"parameter_names": parameters,
}
return collection_metadata(dataset, available_output_formats)

@router.get("/position", summary="Position query")
def get_position(
Expand Down

0 comments on commit 51a2744

Please sign in to comment.