From 08fa2b728671d40f4e63b6b845d052d8398044f4 Mon Sep 17 00:00:00 2001 From: Sarah Jordan Date: Wed, 15 Nov 2023 17:03:15 -0600 Subject: [PATCH] Valid EDR cube queries for data with decreasing coordinates (#1402) * resolving case when lat dimensions are decreasing CF conventions state only that a "coordinate variable must have values that are strictly monotonic (increasing or decreasing)." In the case of PRISM, the lat coordinates are decreasing. pygeoapi failed due to the lat dimension being empty with existing implementation; this update addresses the issue. * remove blank space * resolving case when lat dimensions are decreasing CF conventions state only that a "coordinate variable must have values that are strictly monotonic (increasing or decreasing)." In the case of PRISM, the lat coordinates are decreasing. pygeoapi failed due to the lat dimension being empty with existing implementation; this update addresses the issue. * remove blank space * test decreasing latitude The new test will now uncover if you can successfully serve data stored on S3 AND test if you can perform a cube query on data with monotonically decreasing latitude coordinates at the same time. * flake8 py3 fixes --- pygeoapi/provider/xarray_edr.py | 21 ++++++++++++++++++--- tests/pygeoapi-test-config.yml | 19 ++++++++++--------- tests/test_api.py | 20 +++++++++++--------- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/pygeoapi/provider/xarray_edr.py b/pygeoapi/provider/xarray_edr.py index cade6dc..0d746e3 100644 --- a/pygeoapi/provider/xarray_edr.py +++ b/pygeoapi/provider/xarray_edr.py @@ -33,7 +33,11 @@ import numpy as np from pygeoapi.provider.base import ProviderNoDataError, ProviderQueryError from pygeoapi.provider.base_edr import BaseEDRProvider -from pygeoapi.provider.xarray_ import _to_datetime_string, XarrayProvider +from pygeoapi.provider.xarray_ import ( + _to_datetime_string, + _convert_float32_to_float64, + XarrayProvider, +) LOGGER = logging.getLogger(__name__) @@ -180,9 +184,11 @@ class XarrayEDRProvider(BaseEDRProvider, XarrayProvider): LOGGER.debug(f"Query type: {kwargs.get('query_type')}") bbox = kwargs.get('bbox') + xmin, ymin, xmax, ymax = self._configure_bbox(bbox) + if len(bbox) == 4: - query_params[self.x_field] = slice(bbox[0], bbox[2]) - query_params[self.y_field] = slice(bbox[1], bbox[3]) + query_params[self.x_field] = slice(bbox[xmin], bbox[xmax]) + query_params[self.y_field] = slice(bbox[ymin], bbox[ymax]) else: raise ProviderQueryError('z-axis not supported') @@ -206,6 +212,7 @@ class XarrayEDRProvider(BaseEDRProvider, XarrayProvider): else: data = self._data data = data.sel(query_params) + data = _convert_float32_to_float64(data) except KeyError: raise ProviderNoDataError() @@ -288,3 +295,11 @@ class XarrayEDRProvider(BaseEDRProvider, XarrayProvider): except KeyError: time_steps = kwargs.get('limit') return time, time_steps + + def _configure_bbox(self, bbox): + xmin, ymin, xmax, ymax = 0, 1, 2, 3 + if self._data[self.x_field][0] > self._data[self.x_field][-1]: + xmin, xmax = xmax, xmin + if self._data[self.y_field][0] > self._data[self.y_field][-1]: + ymin, ymax = ymax, ymin + return xmin, ymin, xmax, ymax diff --git a/tests/pygeoapi-test-config.yml b/tests/pygeoapi-test-config.yml index 1b92a76..18017aa 100644 --- a/tests/pygeoapi-test-config.yml +++ b/tests/pygeoapi-test-config.yml @@ -314,28 +314,27 @@ resources: name: NetCDF mimetype: application/x-netcdf - nasa-power: + usgs-prism: type: collection - title: NASA Prediction Of Worldwide Energy Resources (POWER) - description: NASA Prediction Of Worldwide Energy Resources (POWER) + title: Parameter-elevation Regressions on Independent Slopes Model (PRISM) + description: PRISM Monthly Climate Data for the Continental United States keywords: - - nasa - - energy - - power + - temperature + - precipitation extents: spatial: - bbox: [-180,-90,180,90] + bbox: [-125.020836, 24.104166, -66.520836, 49.9375] crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84 links: - type: text/html rel: canonical title: information - href: https://power.larc.nasa.gov/ + href: https://cida.usgs.gov/thredds/catalog.html?dataset=cida.usgs.gov/prism_v2 hreflang: en-US providers: - type: edr name: xarray-edr - data: s3://power-analysis-ready-datastore/power_901_annual_meteorology_utc.zarr + data: s3://mdmf/gdp/PRISM_v2.zarr format: name: zarr mimetype: application/zip @@ -343,6 +342,8 @@ resources: s3: anon: true requester_pays: false + client_kwargs: + endpoint_url: https://usgs.osn.mghpcc.org/ objects: type: collection diff --git a/tests/test_api.py b/tests/test_api.py index 9aeabb3..cd6070a 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -2002,15 +2002,6 @@ def test_get_collection_edr_query(config, api_): req, 'icoads-sst', None, 'position') assert code == HTTPStatus.NO_CONTENT - # S3 EDR - req = mock_request({ - 'coords': 'POINT(-100 40)', - 'parameter-name': 'GWETROOT' - }) - rsp_headers, code, response = api_.get_collection_edr_query( - req, 'nasa-power', None, 'position') - assert code == HTTPStatus.OK - # position no coords req = mock_request({ 'datetime': '2000-01-17' @@ -2041,6 +2032,17 @@ def test_get_collection_edr_query(config, api_): req, 'icoads-sst', None, 'cube') assert code == HTTPStatus.BAD_REQUEST + # cube decreasing latitude coords and S3 + req = mock_request({ + 'bbox': '-100,40,-99,45', + 'parameter-name': 'tmn', + 'datetime': '1994-01-01/1994-12-31', + }) + + rsp_headers, code, response = api_.get_collection_edr_query( + req, 'usgs-prism', None, 'cube') + assert code == HTTPStatus.OK + def test_validate_bbox(): assert validate_bbox('1,2,3,4') == [1, 2, 3, 4]