From 89ceadde5f68ff17e56e2de8687c232a21ad8799 Mon Sep 17 00:00:00 2001 From: cisaacstern <62192187+cisaacstern@users.noreply.github.com> Date: Fri, 12 Nov 2021 16:59:36 -0800 Subject: [PATCH 01/11] remove CLI defaults --- xstac/_generate.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/xstac/_generate.py b/xstac/_generate.py index 516bc05..d2522dc 100644 --- a/xstac/_generate.py +++ b/xstac/_generate.py @@ -8,6 +8,7 @@ import argparse import json import fsspec +import cf_xarray import xarray as xr import xstac @@ -40,16 +41,10 @@ def parse_args(args=None): parser.add_argument("--reference-system", default=None) parser.add_argument( - "--temporal_dimension", - default="time", - help="Coordinate name for the 'time' dimension", - ) - parser.add_argument( - "--x-dimension", default="x", help="Coordinate name for the 'x' dimension" - ) - parser.add_argument( - "--y-dimension", default="y", help="Coordinate name for the 'y' dimension" + "--temporal_dimension", help="Coordinate name for the 'time' dimension" ) + parser.add_argument("--x-dimension", help="Coordinate name for the 'x' dimension") + parser.add_argument("--y-dimension", help="Coordinate name for the 'y' dimension") parser.add_argument( "--no-validate", action="store_false", @@ -62,9 +57,9 @@ def parse_args(args=None): def generate( template, asset_key, - x_dimension="x", - y_dimension="y", - temporal_dimension="time", + x_dimension=None, + y_dimension=None, + temporal_dimension=None, reference_system=None, validate: bool = True, ): From 3d5ee3282d065e8312f2f2fe8050c500be5b8774 Mon Sep 17 00:00:00 2001 From: cisaacstern <62192187+cisaacstern@users.noreply.github.com> Date: Fri, 12 Nov 2021 17:01:16 -0800 Subject: [PATCH 02/11] default to cf standard dim names --- xstac/_xstac.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/xstac/_xstac.py b/xstac/_xstac.py index b10b989..39a1e7b 100644 --- a/xstac/_xstac.py +++ b/xstac/_xstac.py @@ -3,18 +3,40 @@ """ import copy import json +import logging from pystac import stac_object import xarray as xr import numpy as np import pystac import pandas as pd from pyproj import CRS, Transformer -from typing import List, Dict +from typing import Dict from ._types import TemporalDimension, HorizontalSpatialDimension, Datacube, Variable +logger = logging.getLogger(__name__) + SCHEMA_URI = "https://stac-extensions.github.io/datacube/v2.0.0/schema.json" +CF_STANDARD_DIMS = dict( + temporal_dimension="time", x_dimension="longitude", y_dimension="latitude" +) + + +def maybe_use_cf_standard_name(kw, kw_name, ds): + if kw is None: + try: + kw = ds.cf[CF_STANDARD_DIMS[kw_name]].name + except KeyError: + logger.warning( + f"Kwarg `{kw_name}` is None and `{CF_STANDARD_DIMS[kw_name]}` is not a valid key " + "of the provided dataset's `cf` namespace. Therefore, STAC object is generating " + f"without a `{kw_name}` in its Datacube Extension. To correct this, either pass a " + f"string value to `{kw_name}`, or make this attribute accessible via the cf " + "namespace using, e.g., `cf_xarray`'s `guess_coord_axis` method." + ) + return kw + def _bbox_to_geometry(bbox): return { @@ -309,6 +331,12 @@ def xarray_to_stac( **additional_dimensions: A dictionary with keys ``extent``, ``values``, ``step``. """ + temporal_dimension = maybe_use_cf_standard_name( + temporal_dimension, "temporal_dimension", ds + ) + x_dimension = maybe_use_cf_standard_name(x_dimension, "x_dimension", ds) + y_dimension = maybe_use_cf_standard_name(y_dimension, "y_dimension", ds) + datacube = build_datacube( ds, temporal_dimension=temporal_dimension, From 1298a3e8ea84788b7f337772cc0f0691f289dc62 Mon Sep 17 00:00:00 2001 From: cisaacstern <62192187+cisaacstern@users.noreply.github.com> Date: Fri, 12 Nov 2021 17:01:30 -0800 Subject: [PATCH 03/11] import cf_xarray in tests --- test_xstac.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test_xstac.py b/test_xstac.py index 70ea586..c92abc3 100644 --- a/test_xstac.py +++ b/test_xstac.py @@ -1,5 +1,6 @@ from xstac import xarray_to_stac, fix_attrs from xstac._xstac import _bbox_to_geometry +import cf_xarray import xarray as xr import numpy as np import pandas as pd From 418bbbb54b696b310b1cf62f8fea0a7f0bd2b290 Mon Sep 17 00:00:00 2001 From: cisaacstern <62192187+cisaacstern@users.noreply.github.com> Date: Fri, 12 Nov 2021 17:15:32 -0800 Subject: [PATCH 04/11] remove (now redundant) kwargs from tests --- test_xstac.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/test_xstac.py b/test_xstac.py index c92abc3..bf2a60d 100644 --- a/test_xstac.py +++ b/test_xstac.py @@ -127,13 +127,7 @@ def test_xarray_to_stac(ds): "license": "license", "stac_version": "1.0.0", } - result = xarray_to_stac( - ds, - template=template, - temporal_dimension="time", - x_dimension="x", - y_dimension="y", - ) + result = xarray_to_stac(ds, template=template) assert result.id == "id" assert isinstance(result, pystac.Collection) assert result.description == "description" @@ -453,7 +447,7 @@ def test_validation_with_none(): } ) ds.time.attrs["long_name"] = "time" - c = xarray_to_stac(ds, template, temporal_dimension="time") + c = xarray_to_stac(ds, template) c.normalize_hrefs("/") c.validate() @@ -468,13 +462,7 @@ def test_xarray_to_stac_item(ds): "properties": {"datetime": "2021-01-01T00:00:00Z"}, "assets": {}, } - result = xarray_to_stac( - ds, - template=template, - temporal_dimension="time", - x_dimension="x", - y_dimension="y", - ) + result = xarray_to_stac(ds, template=template) assert result.id == "id" assert isinstance(result, pystac.Item) From fa2b721819c0d09e9e536aa20782c09891a5a824 Mon Sep 17 00:00:00 2001 From: cisaacstern <62192187+cisaacstern@users.noreply.github.com> Date: Fri, 12 Nov 2021 17:16:03 -0800 Subject: [PATCH 05/11] use cf standard *axes* --- xstac/_xstac.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/xstac/_xstac.py b/xstac/_xstac.py index 39a1e7b..435ab88 100644 --- a/xstac/_xstac.py +++ b/xstac/_xstac.py @@ -18,22 +18,20 @@ SCHEMA_URI = "https://stac-extensions.github.io/datacube/v2.0.0/schema.json" -CF_STANDARD_DIMS = dict( - temporal_dimension="time", x_dimension="longitude", y_dimension="latitude" -) +CF_STANDARD_AXES = dict(temporal_dimension="T", x_dimension="X", y_dimension="Y") -def maybe_use_cf_standard_name(kw, kw_name, ds): +def maybe_use_cf_standard_axis(kw, kw_name, ds): if kw is None: try: - kw = ds.cf[CF_STANDARD_DIMS[kw_name]].name + kw = ds.cf[CF_STANDARD_AXES[kw_name]].name except KeyError: logger.warning( - f"Kwarg `{kw_name}` is None and `{CF_STANDARD_DIMS[kw_name]}` is not a valid key " + f"Kwarg `{kw_name}` is None and `{CF_STANDARD_AXES[kw_name]}` is not a valid key " "of the provided dataset's `cf` namespace. Therefore, STAC object is generating " f"without a `{kw_name}` in its Datacube Extension. To correct this, either pass a " - f"string value to `{kw_name}`, or make this attribute accessible via the cf " - "namespace using, e.g., `cf_xarray`'s `guess_coord_axis` method." + f"string value to `{kw_name}`, or make `ds.cf['{CF_STANDARD_AXES[kw_name]}']` " + "accessible using, e.g., `cf_xarray`'s `guess_coord_axis` method." ) return kw @@ -331,11 +329,11 @@ def xarray_to_stac( **additional_dimensions: A dictionary with keys ``extent``, ``values``, ``step``. """ - temporal_dimension = maybe_use_cf_standard_name( + temporal_dimension = maybe_use_cf_standard_axis( temporal_dimension, "temporal_dimension", ds ) - x_dimension = maybe_use_cf_standard_name(x_dimension, "x_dimension", ds) - y_dimension = maybe_use_cf_standard_name(y_dimension, "y_dimension", ds) + x_dimension = maybe_use_cf_standard_axis(x_dimension, "x_dimension", ds) + y_dimension = maybe_use_cf_standard_axis(y_dimension, "y_dimension", ds) datacube = build_datacube( ds, From 34c9aef2a331ca40293dc04cac7dd8ef03beb375 Mon Sep 17 00:00:00 2001 From: cisaacstern <62192187+cisaacstern@users.noreply.github.com> Date: Fri, 12 Nov 2021 17:46:18 -0800 Subject: [PATCH 06/11] add cf_xarray as install req --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 334db8f..36c16f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,7 @@ author = "Tom Augspurger" author-email = "taugspurger@microsoft.com" classifiers = [ "License :: OSI Approved :: MIT License",] requires = [ + "cf_xarray", "xarray", "numpy", "pystac>=1.0.0b3", From f575b8d6945715090b3e0df345fa165ac75d574e Mon Sep 17 00:00:00 2001 From: Charles Stern <62192187+cisaacstern@users.noreply.github.com> Date: Sat, 13 Nov 2021 15:40:29 -0800 Subject: [PATCH 07/11] make test dir, add conftest --- .github/workflows/continuous-integration.yml | 2 +- test_xstac.py => tests/conftest.py | 138 +++++++------------ tests/test_xstac.py | 76 ++++++++++ 3 files changed, 129 insertions(+), 87 deletions(-) rename test_xstac.py => tests/conftest.py (92%) create mode 100644 tests/test_xstac.py diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 026b925..4b81fe0 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -25,7 +25,7 @@ jobs: run: python -m pip install .[dev] - name: Run tests - run: pytest -v + run: pytest tests -v - name: Lint run: pre-commit run --all-files diff --git a/test_xstac.py b/tests/conftest.py similarity index 92% rename from test_xstac.py rename to tests/conftest.py index bf2a60d..2901762 100644 --- a/test_xstac.py +++ b/tests/conftest.py @@ -1,14 +1,9 @@ -from xstac import xarray_to_stac, fix_attrs -from xstac._xstac import _bbox_to_geometry +import pytest import cf_xarray -import xarray as xr import numpy as np import pandas as pd -import pytest -import pystac - -import xstac - +import xarray as xr +from xstac import fix_attrs data = np.empty((40, 584, 284), dtype="float32") x = xr.DataArray( @@ -118,7 +113,23 @@ def ds(): return fix_attrs(ds) -def test_xarray_to_stac(ds): +@pytest.fixture +def ds_without_spatial_dims(): + ds = xr.Dataset( + { + "data": xr.DataArray( + [1, 2], + dims=("time",), + coords={"time": pd.to_datetime(["2021-01-01", "2021-01-02"])}, + ) + } + ) + ds.time.attrs["long_name"] = "time" + return ds + + +@pytest.fixture +def collection_template(): template = { "id": "id", "type": "Collection", @@ -127,13 +138,25 @@ def test_xarray_to_stac(ds): "license": "license", "stac_version": "1.0.0", } - result = xarray_to_stac(ds, template=template) - assert result.id == "id" - assert isinstance(result, pystac.Collection) - assert result.description == "description" - assert result.license == "license" + return template + + +@pytest.fixture +def item_template(): + template = { + "id": "id", + "type": "Feature", + "links": [], + "geometry": None, + "stac_version": "1.0.0", + "properties": {"datetime": "2021-01-01T00:00:00Z"}, + "assets": {}, + } + return template + - dimensions = result.extra_fields["cube:dimensions"] +@pytest.fixture +def collection_expected_dims(): expected = { "time": { "type": "temporal", @@ -347,7 +370,11 @@ def test_xarray_to_stac(ds): }, }, } - assert dimensions == expected + return expected + + +@pytest.fixture +def collection_expected_vars(): expected = { "lat": { "type": "auxiliary", @@ -414,59 +441,11 @@ def test_xarray_to_stac(ds): }, }, } - assert result.extra_fields["cube:variables"] == expected + return expected -def test_validation_with_none(): - # https://github.com/TomAugspurger/xstac/issues/9 - template = { - "type": "Collection", - "id": "cesm2-lens", - "stac_version": "1.0.0", - "description": "desc", - "stac_extensions": [ - "https://stac-extensions.github.io/datacube/v2.0.0/schema.json" - ], - "extent": { - "spatial": {"bbox": [[-180, -90, 180, 90]]}, - "temporal": { - "interval": [["1851-01-01T00:00:00Z", "1851-01-01T00:00:00Z"]] - }, - }, - "providers": [], - "license": "CC0-1.0", - "links": [], - } - ds = xr.Dataset( - { - "data": xr.DataArray( - [1, 2], - dims=("time",), - coords={"time": pd.to_datetime(["2021-01-01", "2021-01-02"])}, - ) - } - ) - ds.time.attrs["long_name"] = "time" - c = xarray_to_stac(ds, template) - c.normalize_hrefs("/") - c.validate() - - -def test_xarray_to_stac_item(ds): - template = { - "id": "id", - "type": "Feature", - "links": [], - "geometry": None, - "stac_version": "1.0.0", - "properties": {"datetime": "2021-01-01T00:00:00Z"}, - "assets": {}, - } - result = xarray_to_stac(ds, template=template) - assert result.id == "id" - assert isinstance(result, pystac.Item) - - dimensions = result.properties["cube:dimensions"] +@pytest.fixture +def item_expected_dims(): expected = { "time": { "type": "temporal", @@ -680,7 +659,11 @@ def test_xarray_to_stac_item(ds): }, }, } - assert dimensions == expected + return expected + + +@pytest.fixture +def item_expected_vars(): expected = { "lat": { "type": "auxiliary", @@ -747,21 +730,4 @@ def test_xarray_to_stac_item(ds): }, }, } - assert result.properties["cube:variables"] == expected - - assert result.properties["start_datetime"] == "1980-07-31T00:00:00Z" - assert result.properties["end_datetime"] == "2019-07-31T00:00:00Z" - - -def test_bbox_to_geometry(): - import shapely.geometry - - bbox = [ - -160.2988400944475, - 17.960033949329812, - -154.7780670634169, - 23.51232608231902, - ] - result = shapely.geometry.mapping(shapely.geometry.shape(_bbox_to_geometry(bbox))) - expected = shapely.geometry.mapping(shapely.geometry.box(*bbox)) - assert result == expected + return expected diff --git a/tests/test_xstac.py b/tests/test_xstac.py new file mode 100644 index 0000000..cf8df9c --- /dev/null +++ b/tests/test_xstac.py @@ -0,0 +1,76 @@ +from xstac import xarray_to_stac +from xstac._xstac import _bbox_to_geometry +import cf_xarray +import pytest +import pystac + +import xstac + + +def test_xarray_to_stac( + ds, collection_template, collection_expected_dims, collection_expected_vars +): + result = xarray_to_stac(ds, template=collection_template) + assert result.id == "id" + assert isinstance(result, pystac.Collection) + assert result.description == "description" + assert result.license == "license" + + dimensions = result.extra_fields["cube:dimensions"] + assert dimensions == collection_expected_dims + assert result.extra_fields["cube:variables"] == collection_expected_vars + + +def test_validation_with_none(ds_without_spatial_dims): + # https://github.com/TomAugspurger/xstac/issues/9 + template = { + "type": "Collection", + "id": "cesm2-lens", + "stac_version": "1.0.0", + "description": "desc", + "stac_extensions": [ + "https://stac-extensions.github.io/datacube/v2.0.0/schema.json" + ], + "extent": { + "spatial": {"bbox": [[-180, -90, 180, 90]]}, + "temporal": { + "interval": [["1851-01-01T00:00:00Z", "1851-01-01T00:00:00Z"]] + }, + }, + "providers": [], + "license": "CC0-1.0", + "links": [], + } + c = xarray_to_stac( + ds_without_spatial_dims, template, x_dimension=False, y_dimension=False + ) + c.normalize_hrefs("/") + c.validate() + + +def test_xarray_to_stac_item(ds, item_template, item_expected_dims, item_expected_vars): + + result = xarray_to_stac(ds, template=item_template) + assert result.id == "id" + assert isinstance(result, pystac.Item) + + dimensions = result.properties["cube:dimensions"] + assert dimensions == item_expected_dims + assert result.properties["cube:variables"] == item_expected_vars + + assert result.properties["start_datetime"] == "1980-07-31T00:00:00Z" + assert result.properties["end_datetime"] == "2019-07-31T00:00:00Z" + + +def test_bbox_to_geometry(): + import shapely.geometry + + bbox = [ + -160.2988400944475, + 17.960033949329812, + -154.7780670634169, + 23.51232608231902, + ] + result = shapely.geometry.mapping(shapely.geometry.shape(_bbox_to_geometry(bbox))) + expected = shapely.geometry.mapping(shapely.geometry.box(*bbox)) + assert result == expected From c3e1001a9253dddb7a2ae0113ff278550e21eac6 Mon Sep 17 00:00:00 2001 From: Charles Stern <62192187+cisaacstern@users.noreply.github.com> Date: Sat, 13 Nov 2021 16:40:12 -0800 Subject: [PATCH 08/11] two error conditions for cf handler func --- xstac/_xstac.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/xstac/_xstac.py b/xstac/_xstac.py index 435ab88..d01271d 100644 --- a/xstac/_xstac.py +++ b/xstac/_xstac.py @@ -3,7 +3,6 @@ """ import copy import json -import logging from pystac import stac_object import xarray as xr import numpy as np @@ -14,25 +13,32 @@ from ._types import TemporalDimension, HorizontalSpatialDimension, Datacube, Variable -logger = logging.getLogger(__name__) - SCHEMA_URI = "https://stac-extensions.github.io/datacube/v2.0.0/schema.json" CF_STANDARD_AXES = dict(temporal_dimension="T", x_dimension="X", y_dimension="Y") def maybe_use_cf_standard_axis(kw, kw_name, ds): + GENERIC_SUGGESTION = ( + f"Alternatively, pass `{kw_name}` as a string cooresponding to a the name of the " + f"dataset's {kw_name}. If the dataset does not have a {kw_name}, pass `{kw_name}=False`." + ) + if not hasattr(ds, "cf"): + raise AttributeError( + f"Kwarg `{kw_name}` is None and the dataset does not have a `cf` namespace. Please " + f"ensure that `cf_xarray` (https://cf-xarray.readthedocs.io/) is imported in the " + f"module where you've opened the dataset. {GENERIC_SUGGESTION}" + ) if kw is None: try: kw = ds.cf[CF_STANDARD_AXES[kw_name]].name - except KeyError: - logger.warning( - f"Kwarg `{kw_name}` is None and `{CF_STANDARD_AXES[kw_name]}` is not a valid key " - "of the provided dataset's `cf` namespace. Therefore, STAC object is generating " - f"without a `{kw_name}` in its Datacube Extension. To correct this, either pass a " - f"string value to `{kw_name}`, or make `ds.cf['{CF_STANDARD_AXES[kw_name]}']` " - "accessible using, e.g., `cf_xarray`'s `guess_coord_axis` method." - ) + except KeyError as e: + raise KeyError( + f"Kwarg `{kw_name}` is None and `{CF_STANDARD_AXES[kw_name]}` is not a key of " + f"the dataset's `cf` namespace. Make `ds.cf['{CF_STANDARD_AXES[kw_name]}']` " + "accessible via `cf_xarray`'s `guess_coord_axis` method or by manually editing the " + f"dataset's attributes according to http://cfconventions.org. {GENERIC_SUGGESTION}" + ) from e return kw @@ -239,7 +245,7 @@ def build_datacube( ): dimensions = {} - if temporal_dimension is not None: + if temporal_dimension is not False: dimensions[temporal_dimension] = build_temporal_dimension( ds, temporal_dimension, temporal_extent, temporal_values, temporal_step ) From 363b5f9ba752a5974b9de6efbe0bcdf61de6b881 Mon Sep 17 00:00:00 2001 From: Charles Stern <62192187+cisaacstern@users.noreply.github.com> Date: Sat, 13 Nov 2021 16:42:02 -0800 Subject: [PATCH 09/11] test error conditions and explicit dim passing --- tests/test_xstac.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/tests/test_xstac.py b/tests/test_xstac.py index cf8df9c..216dba7 100644 --- a/tests/test_xstac.py +++ b/tests/test_xstac.py @@ -1,16 +1,30 @@ from xstac import xarray_to_stac from xstac._xstac import _bbox_to_geometry -import cf_xarray +import xarray as xr import pytest import pystac import xstac +# def test_no_time_dimension(ds, collection_template): +# _ = xarray_to_stac(ds, template=collection_template, temporal_dimension=False) + + +@pytest.mark.parametrize("explicit_dims", [False, True]) def test_xarray_to_stac( - ds, collection_template, collection_expected_dims, collection_expected_vars + ds, + collection_template, + collection_expected_dims, + collection_expected_vars, + explicit_dims, ): - result = xarray_to_stac(ds, template=collection_template) + kw = ( + dict() + if not explicit_dims + else dict(temporal_dimension="time", x_dimension="x", y_dimension="y") + ) + result = xarray_to_stac(ds, template=collection_template, **kw) assert result.id == "id" assert isinstance(result, pystac.Collection) assert result.description == "description" @@ -74,3 +88,15 @@ def test_bbox_to_geometry(): result = shapely.geometry.mapping(shapely.geometry.shape(_bbox_to_geometry(bbox))) expected = shapely.geometry.mapping(shapely.geometry.box(*bbox)) assert result == expected + + +def test_missing_dims_error(ds_without_spatial_dims, collection_template): + with pytest.raises(KeyError): + _ = xarray_to_stac(ds_without_spatial_dims, collection_template) + + +def test_cf_namespace_error(collection_template): + delattr(xr.Dataset, "cf") + ds_ = xr.Dataset({"data": xr.DataArray([1, 2])}) + with pytest.raises(AttributeError): + _ = xarray_to_stac(ds_, collection_template) From 78dd46169745af917873b064b85ea5b2b680f430 Mon Sep 17 00:00:00 2001 From: Charles Stern <62192187+cisaacstern@users.noreply.github.com> Date: Sat, 13 Nov 2021 17:02:08 -0800 Subject: [PATCH 10/11] comment out dim=False suggestion --- xstac/_xstac.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xstac/_xstac.py b/xstac/_xstac.py index d01271d..88a709a 100644 --- a/xstac/_xstac.py +++ b/xstac/_xstac.py @@ -20,8 +20,9 @@ def maybe_use_cf_standard_axis(kw, kw_name, ds): GENERIC_SUGGESTION = ( - f"Alternatively, pass `{kw_name}` as a string cooresponding to a the name of the " - f"dataset's {kw_name}. If the dataset does not have a {kw_name}, pass `{kw_name}=False`." + f"Alternatively, pass `{kw_name}` as a string cooresponding to the name of the " + f"dataset's {kw_name}." + # "If the dataset does not have a {kw_name}, pass `{kw_name}=False`." ) if not hasattr(ds, "cf"): raise AttributeError( From b1b400477a3c4a6b69ca9206fdecf9219e903b71 Mon Sep 17 00:00:00 2001 From: Charles Stern <62192187+cisaacstern@users.noreply.github.com> Date: Mon, 15 Nov 2021 11:05:55 -0800 Subject: [PATCH 11/11] cf_xarray import in xstac adds cf namespace --- tests/conftest.py | 1 - tests/test_xstac.py | 7 ------- xstac/_xstac.py | 16 ++++------------ 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 2901762..5878c26 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,4 @@ import pytest -import cf_xarray import numpy as np import pandas as pd import xarray as xr diff --git a/tests/test_xstac.py b/tests/test_xstac.py index 216dba7..2fe847a 100644 --- a/tests/test_xstac.py +++ b/tests/test_xstac.py @@ -93,10 +93,3 @@ def test_bbox_to_geometry(): def test_missing_dims_error(ds_without_spatial_dims, collection_template): with pytest.raises(KeyError): _ = xarray_to_stac(ds_without_spatial_dims, collection_template) - - -def test_cf_namespace_error(collection_template): - delattr(xr.Dataset, "cf") - ds_ = xr.Dataset({"data": xr.DataArray([1, 2])}) - with pytest.raises(AttributeError): - _ = xarray_to_stac(ds_, collection_template) diff --git a/xstac/_xstac.py b/xstac/_xstac.py index 88a709a..c8c48e2 100644 --- a/xstac/_xstac.py +++ b/xstac/_xstac.py @@ -4,6 +4,7 @@ import copy import json from pystac import stac_object +import cf_xarray import xarray as xr import numpy as np import pystac @@ -19,17 +20,6 @@ def maybe_use_cf_standard_axis(kw, kw_name, ds): - GENERIC_SUGGESTION = ( - f"Alternatively, pass `{kw_name}` as a string cooresponding to the name of the " - f"dataset's {kw_name}." - # "If the dataset does not have a {kw_name}, pass `{kw_name}=False`." - ) - if not hasattr(ds, "cf"): - raise AttributeError( - f"Kwarg `{kw_name}` is None and the dataset does not have a `cf` namespace. Please " - f"ensure that `cf_xarray` (https://cf-xarray.readthedocs.io/) is imported in the " - f"module where you've opened the dataset. {GENERIC_SUGGESTION}" - ) if kw is None: try: kw = ds.cf[CF_STANDARD_AXES[kw_name]].name @@ -38,7 +28,9 @@ def maybe_use_cf_standard_axis(kw, kw_name, ds): f"Kwarg `{kw_name}` is None and `{CF_STANDARD_AXES[kw_name]}` is not a key of " f"the dataset's `cf` namespace. Make `ds.cf['{CF_STANDARD_AXES[kw_name]}']` " "accessible via `cf_xarray`'s `guess_coord_axis` method or by manually editing the " - f"dataset's attributes according to http://cfconventions.org. {GENERIC_SUGGESTION}" + "dataset's attributes according to http://cfconventions.org. Alternatively, pass " + f"`{kw_name}` as a string cooresponding to the name of the dataset's {kw_name}." + # "If the dataset does not have a {kw_name}, pass `{kw_name}=False`." ) from e return kw