Skip to content

Commit

Permalink
Coverages: continue TIFF implementation; rangeset
Browse files Browse the repository at this point in the history
- Add an endpoint implementation to return a coverage as a TIFF (not
  yet fully functional due to problems with rioxarray)

- Add a dummy implementation of the recently-deprecated rangeSet
  endpoint. It returns a 501 status to make it clear that the
  endpoint is deliberately not supported.
  • Loading branch information
pont-us committed Aug 30, 2023
1 parent b823163 commit 2b9c7f1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 6 deletions.
38 changes: 34 additions & 4 deletions xcube/webapi/ows/coverages/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

from xcube.server.api import ApiRequest
from xcube.webapi.datasets.context import DatasetsContext
import os
import tempfile
import xarray as xr
import pyproj
import numpy as np
import rasterio


def get_coverage_as_json(ctx: DatasetsContext, collection_id: str):
Expand All @@ -45,9 +48,35 @@ def get_coverage_as_json(ctx: DatasetsContext, collection_id: str):
}


def get_coverage_as_tiff(ctx: DatasetsContext, collection_id: str):
def get_coverage_as_tiff(ctx: DatasetsContext, collection_id: str,
request: ApiRequest, content_type: str):
query = request.query
ds = get_dataset(ctx, collection_id)
return ds.
if 'bbox' in query:
bbox = list(map(float, query['bbox'][0].split(',')))
ds = ds.sel(lat=slice(bbox[0], bbox[2]), lon=slice(bbox[1], bbox[3]))
if 'datetime' in query:
timespec = query['datetime']
if '/' in timespec:
timefrom, timeto = timespec[0].split('/')
ds = ds.sel(time=slice(timefrom, timeto))

Check warning on line 62 in xcube/webapi/ows/coverages/controllers.py

View check run for this annotation

Codecov / codecov/patch

xcube/webapi/ows/coverages/controllers.py#L53-L62

Added lines #L53 - L62 were not covered by tests
else:
ds = ds.sel(time=timespec, method='nearest').squeeze()
if 'properties' in query:
vars_to_keep = set(query['properties'][0].split(','))
data_vars = set(ds.data_vars)
vars_to_drop = list(data_vars - vars_to_keep)
ds = ds.drop_vars(vars_to_drop)
return dataset_to_tiff(ds)

Check warning on line 70 in xcube/webapi/ows/coverages/controllers.py

View check run for this annotation

Codecov / codecov/patch

xcube/webapi/ows/coverages/controllers.py#L64-L70

Added lines #L64 - L70 were not covered by tests


def dataset_to_tiff(ds):
with tempfile.TemporaryDirectory() as tempdir:
path = os.path.join(tempdir, 'out.tiff')
ds.rio.to_raster(path)
with open(path, 'rb') as fh:
data = fh.read()
return data

Check warning on line 79 in xcube/webapi/ows/coverages/controllers.py

View check run for this annotation

Codecov / codecov/patch

xcube/webapi/ows/coverages/controllers.py#L74-L79

Added lines #L74 - L79 were not covered by tests


def get_coverage_domainset(ctx: DatasetsContext, collection_id: str):
Expand Down Expand Up @@ -122,8 +151,9 @@ def get_crs_from_dataset(ds: xr.Dataset):
if var_name in ds.variables:
var = ds[var_name]
if 'spatial_ref' in var.attrs:
crs_string = ds.spatial_ref.attrs['spatial_ref']
crs_string = ds[var_name].attrs['spatial_ref']
return pyproj.crs.CRS(crs_string).to_string()
return 'EPSG:4326'

Check warning on line 156 in xcube/webapi/ows/coverages/controllers.py

View check run for this annotation

Codecov / codecov/patch

xcube/webapi/ows/coverages/controllers.py#L150-L156

Added lines #L150 - L156 were not covered by tests


def get_coverage_rangetype(ctx: DatasetsContext, collection_id: str):
Expand Down
16 changes: 14 additions & 2 deletions xcube/webapi/ows/coverages/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ async def get(self, collectionId: str):
result = get_coverage_as_json(ds_ctx, collectionId)

Check warning on line 48 in xcube/webapi/ows/coverages/routes.py

View check run for this annotation

Codecov / codecov/patch

xcube/webapi/ows/coverages/routes.py#L47-L48

Added lines #L47 - L48 were not covered by tests
else:
actual_content_type='image/tiff'
result = get_coverage_as_tiff()
result = get_coverage_as_tiff(ds_ctx, collectionId, self.request, content_type)
return await self.response.finish(result,

Check warning on line 52 in xcube/webapi/ows/coverages/routes.py

View check run for this annotation

Codecov / codecov/patch

xcube/webapi/ows/coverages/routes.py#L50-L52

Added lines #L50 - L52 were not covered by tests
content_type=actual_content_type)

Expand Down Expand Up @@ -86,12 +86,24 @@ async def get(self, collectionId: str):
))


@api.route('/catalog/collections/{collectionId}/coverage/rangeset')
class CoveragesRangesetHandler(ApiHandler[CoveragesContext]):
# noinspection PyPep8Naming
@api.operation(operation_id='coveragesRangeset',
summary='OGC API - Coverages - rangeset')
async def get(self, collectionId: str):
self.response.set_status(501)
return self.response.finish(

Check warning on line 96 in xcube/webapi/ows/coverages/routes.py

View check run for this annotation

Codecov / codecov/patch

xcube/webapi/ows/coverages/routes.py#L95-L96

Added lines #L95 - L96 were not covered by tests
'The rangeset endpoint has been deprecated and is not supported.'
)


def get_content_type(
request: ApiRequest, available: Optional[Collection[str]] = None
) -> Optional[str]:
if 'f' in request.query: # overrides headers
content_type = request.query['f'][0]
return content_type if content_type in available else None
return content_type if available is None or content_type in available else None

Check warning on line 106 in xcube/webapi/ows/coverages/routes.py

View check run for this annotation

Codecov / codecov/patch

xcube/webapi/ows/coverages/routes.py#L104-L106

Added lines #L104 - L106 were not covered by tests

accept = re.split(', *', request.headers.get('Accept'))

Check warning on line 108 in xcube/webapi/ows/coverages/routes.py

View check run for this annotation

Codecov / codecov/patch

xcube/webapi/ows/coverages/routes.py#L108

Added line #L108 was not covered by tests

Expand Down

0 comments on commit 2b9c7f1

Please sign in to comment.