cf-xarray 0.9.4__tar.gz → 0.10.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.github/workflows/ci.yaml +2 -2
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.github/workflows/pypi.yaml +2 -2
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.pre-commit-config.yaml +8 -8
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.readthedocs.yml +3 -2
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/CITATION.cff +4 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/PKG-INFO +3 -4
- cf_xarray-0.10.0/cf_xarray/_version.py +1 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/accessor.py +28 -49
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/coding.py +6 -3
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/formatting.py +2 -2
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/geometry.py +37 -32
- cf_xarray-0.10.0/cf_xarray/parametric.py +821 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/scripts/make_doc.py +3 -1
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/sgrid.py +2 -1
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/tests/test_accessor.py +17 -45
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/tests/test_geometry.py +1 -1
- cf_xarray-0.10.0/cf_xarray/tests/test_parametric.py +615 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/utils.py +3 -1
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray.egg-info/PKG-INFO +3 -4
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray.egg-info/SOURCES.txt +2 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray.egg-info/requires.txt +1 -1
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/ci/doc.yml +2 -2
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/parametricz.md +1 -1
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/whats-new.rst +1 -3
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/pyproject.toml +4 -5
- cf_xarray-0.9.4/cf_xarray/_version.py +0 -1
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.binder/environment.yml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.deepsource.toml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.github/dependabot.yml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.github/release.yml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.github/workflows/parse_logs.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.github/workflows/testpypi-release.yaml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.github/workflows/upstream-dev-ci.yaml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.gitignore +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/.tributors +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/LICENSE +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/README.rst +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/__init__.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/criteria.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/datasets.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/helpers.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/options.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/py.typed +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/scripts/print_versions.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/tests/__init__.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/tests/conftest.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/tests/test_coding.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/tests/test_helpers.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/tests/test_options.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/tests/test_scripts.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/tests/test_units.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray/units.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray.egg-info/dependency_links.txt +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/cf_xarray.egg-info/top_level.txt +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/ci/environment-no-optional-deps.yml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/ci/environment.yml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/ci/upstream-dev-env.yml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/codecov.yml +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/2D_bounds_averaged.png +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/2D_bounds_error.png +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/2D_bounds_nonunique.png +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/Makefile +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/_static/dataset-diagram-logo.tex +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/_static/full-logo.png +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/_static/logo.png +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/_static/logo.svg +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/_static/rich-repr-example.png +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/_static/style.css +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/api.rst +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/bounds.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/cartopy_rotated_pole.png +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/coding.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/conf.py +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/contributing.rst +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/coord_axes.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/custom-criteria.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/dsg.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/examples/introduction.ipynb +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/faq.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/flags.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/geometry.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/grid_mappings.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/howtouse.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/index.rst +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/make.bat +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/plotting.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/provenance.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/quickstart.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/roadmap.rst +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/selecting.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/sgrid_ugrid.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/doc/units.md +0 -0
- {cf_xarray-0.9.4 → cf_xarray-0.10.0}/setup.cfg +0 -0
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
fail-fast: false
|
|
28
28
|
matrix:
|
|
29
29
|
os: ["ubuntu-latest"]
|
|
30
|
-
python-version: ["3.
|
|
30
|
+
python-version: ["3.10", "3.12"]
|
|
31
31
|
steps:
|
|
32
32
|
- uses: actions/checkout@v4
|
|
33
33
|
with:
|
|
@@ -91,7 +91,7 @@ jobs:
|
|
|
91
91
|
shell: bash -l {0}
|
|
92
92
|
strategy:
|
|
93
93
|
matrix:
|
|
94
|
-
python-version: ["3.
|
|
94
|
+
python-version: ["3.10", "3.12"]
|
|
95
95
|
steps:
|
|
96
96
|
- uses: actions/checkout@v4
|
|
97
97
|
with:
|
|
@@ -72,7 +72,7 @@ jobs:
|
|
|
72
72
|
|
|
73
73
|
- name: Publish package to TestPyPI
|
|
74
74
|
if: github.event_name == 'push'
|
|
75
|
-
uses: pypa/gh-action-pypi-publish@v1.
|
|
75
|
+
uses: pypa/gh-action-pypi-publish@v1.10.2
|
|
76
76
|
with:
|
|
77
77
|
password: ${{ secrets.TESTPYPI_TOKEN }}
|
|
78
78
|
repository_url: https://test.pypi.org/legacy/
|
|
@@ -96,6 +96,6 @@ jobs:
|
|
|
96
96
|
name: releases
|
|
97
97
|
path: dist
|
|
98
98
|
- name: Publish package to PyPI
|
|
99
|
-
uses: pypa/gh-action-pypi-publish@v1.
|
|
99
|
+
uses: pypa/gh-action-pypi-publish@v1.10.2
|
|
100
100
|
with:
|
|
101
101
|
verbose: true
|
|
@@ -3,25 +3,25 @@ ci:
|
|
|
3
3
|
|
|
4
4
|
repos:
|
|
5
5
|
- repo: https://github.com/asottile/pyupgrade
|
|
6
|
-
rev: v3.
|
|
6
|
+
rev: v3.17.0
|
|
7
7
|
hooks:
|
|
8
8
|
- id: pyupgrade
|
|
9
|
-
args: ["--
|
|
9
|
+
args: ["--py310-plus"]
|
|
10
10
|
|
|
11
11
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
12
12
|
# Ruff version.
|
|
13
|
-
rev: 'v0.
|
|
13
|
+
rev: 'v0.6.9'
|
|
14
14
|
hooks:
|
|
15
15
|
- id: ruff
|
|
16
16
|
args: ["--show-fixes", "--fix"]
|
|
17
17
|
|
|
18
18
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
19
|
-
rev: 24.
|
|
19
|
+
rev: 24.10.0
|
|
20
20
|
hooks:
|
|
21
21
|
- id: black
|
|
22
22
|
|
|
23
23
|
- repo: https://github.com/rstcheck/rstcheck
|
|
24
|
-
rev: v6.2.
|
|
24
|
+
rev: v6.2.4
|
|
25
25
|
hooks:
|
|
26
26
|
- id: rstcheck
|
|
27
27
|
additional_dependencies: [sphinx, tomli]
|
|
@@ -36,7 +36,7 @@ repos:
|
|
|
36
36
|
- mdformat-myst
|
|
37
37
|
|
|
38
38
|
- repo: https://github.com/nbQA-dev/nbQA
|
|
39
|
-
rev: 1.8.
|
|
39
|
+
rev: 1.8.7
|
|
40
40
|
hooks:
|
|
41
41
|
- id: nbqa-black
|
|
42
42
|
- id: nbqa-ruff
|
|
@@ -47,7 +47,7 @@ repos:
|
|
|
47
47
|
additional_dependencies: [mdformat==0.7.17]
|
|
48
48
|
|
|
49
49
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
50
|
-
rev:
|
|
50
|
+
rev: v5.0.0
|
|
51
51
|
hooks:
|
|
52
52
|
- id: trailing-whitespace
|
|
53
53
|
- id: end-of-file-fixer
|
|
@@ -67,7 +67,7 @@ repos:
|
|
|
67
67
|
- id: validate-cff
|
|
68
68
|
|
|
69
69
|
- repo: https://github.com/abravalheri/validate-pyproject
|
|
70
|
-
rev: v0.
|
|
70
|
+
rev: v0.20.2
|
|
71
71
|
hooks:
|
|
72
72
|
- id: validate-pyproject
|
|
73
73
|
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
version: 2
|
|
2
2
|
|
|
3
3
|
build:
|
|
4
|
-
os: ubuntu-
|
|
4
|
+
os: ubuntu-lts-latest
|
|
5
5
|
tools:
|
|
6
|
-
python: mambaforge-
|
|
6
|
+
python: mambaforge-latest
|
|
7
7
|
jobs:
|
|
8
8
|
post_checkout:
|
|
9
9
|
- (git --no-pager log --pretty="tformat:%s" -1 | grep -vqF "[skip-rtd]") || exit 183
|
|
10
10
|
pre_install:
|
|
11
11
|
- conda list sphinx
|
|
12
12
|
- conda list cf_xarray
|
|
13
|
+
- conda list
|
|
13
14
|
|
|
14
15
|
conda:
|
|
15
16
|
environment: ci/doc.yml
|
|
@@ -83,6 +83,10 @@ authors:
|
|
|
83
83
|
- family-names: Haëck
|
|
84
84
|
given-names: Clément
|
|
85
85
|
affiliation: Laboratoire d'Océanographie et du Climat (LOCEAN), Paris
|
|
86
|
+
- family-names: Boutte
|
|
87
|
+
given-names: Jason
|
|
88
|
+
orcid: 'https://orcid.org/0009-0009-3996-3772'
|
|
89
|
+
affiliation: Lawrence Livermore National Laboratory
|
|
86
90
|
identifiers:
|
|
87
91
|
- type: doi
|
|
88
92
|
value: 10.5281/zenodo.4749735
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cf_xarray
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: A convenience wrapper for using CF attributes on xarray objects
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -214,14 +214,13 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
214
214
|
Classifier: Natural Language :: English
|
|
215
215
|
Classifier: Operating System :: OS Independent
|
|
216
216
|
Classifier: Programming Language :: Python
|
|
217
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
218
217
|
Classifier: Programming Language :: Python :: 3.10
|
|
219
218
|
Classifier: Programming Language :: Python :: 3.11
|
|
220
219
|
Classifier: Programming Language :: Python :: 3.12
|
|
221
|
-
Requires-Python: >=3.
|
|
220
|
+
Requires-Python: >=3.10
|
|
222
221
|
Description-Content-Type: text/x-rst
|
|
223
222
|
License-File: LICENSE
|
|
224
|
-
Requires-Dist: xarray
|
|
223
|
+
Requires-Dist: xarray>=2022.03.0
|
|
225
224
|
Provides-Extra: all
|
|
226
225
|
Requires-Dist: matplotlib; extra == "all"
|
|
227
226
|
Requires-Dist: pint!=0.24.0,>=0.18; extra == "all"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.10.0"
|
|
@@ -5,14 +5,19 @@ import inspect
|
|
|
5
5
|
import itertools
|
|
6
6
|
import re
|
|
7
7
|
from collections import ChainMap, namedtuple
|
|
8
|
-
from collections.abc import
|
|
8
|
+
from collections.abc import (
|
|
9
|
+
Callable,
|
|
10
|
+
Hashable,
|
|
11
|
+
Iterable,
|
|
12
|
+
Mapping,
|
|
13
|
+
MutableMapping,
|
|
14
|
+
Sequence,
|
|
15
|
+
)
|
|
9
16
|
from datetime import datetime
|
|
10
17
|
from typing import (
|
|
11
18
|
Any,
|
|
12
|
-
Callable,
|
|
13
19
|
Literal,
|
|
14
20
|
TypeVar,
|
|
15
|
-
Union,
|
|
16
21
|
cast,
|
|
17
22
|
overload,
|
|
18
23
|
)
|
|
@@ -25,7 +30,7 @@ from xarray.core.resample import Resample
|
|
|
25
30
|
from xarray.core.rolling import Coarsen, Rolling
|
|
26
31
|
from xarray.core.weighted import Weighted
|
|
27
32
|
|
|
28
|
-
from . import sgrid
|
|
33
|
+
from . import parametric, sgrid
|
|
29
34
|
from .criteria import (
|
|
30
35
|
_DSG_ROLES,
|
|
31
36
|
_GEOMETRY_TYPES,
|
|
@@ -83,7 +88,7 @@ ATTRS["time"] = ATTRS["T"]
|
|
|
83
88
|
ATTRS["vertical"] = ATTRS["Z"]
|
|
84
89
|
|
|
85
90
|
# Type for Mapper functions
|
|
86
|
-
Mapper = Callable[[
|
|
91
|
+
Mapper = Callable[[DataArray | Dataset, Hashable], list[Hashable]]
|
|
87
92
|
|
|
88
93
|
# Type for decorators
|
|
89
94
|
F = TypeVar("F", bound=Callable[..., Any])
|
|
@@ -532,7 +537,7 @@ def _get_coords(obj: DataArray | Dataset, key: Hashable) -> list[Hashable]:
|
|
|
532
537
|
def _variables(func: F) -> F:
|
|
533
538
|
@functools.wraps(func)
|
|
534
539
|
def wrapper(obj: DataArray | Dataset, key: Hashable) -> list[DataArray]:
|
|
535
|
-
return [obj[k] for k in func(obj, key)]
|
|
540
|
+
return [obj[k] for k in func(obj, key)]
|
|
536
541
|
|
|
537
542
|
return cast(F, wrapper)
|
|
538
543
|
|
|
@@ -1144,9 +1149,10 @@ def create_flag_dict(da) -> Mapping[Hashable, FlagParam]:
|
|
|
1144
1149
|
)
|
|
1145
1150
|
|
|
1146
1151
|
flag_params = tuple(
|
|
1147
|
-
FlagParam(mask, value)
|
|
1152
|
+
FlagParam(mask, value)
|
|
1153
|
+
for mask, value in zip(flag_masks, flag_values, strict=False)
|
|
1148
1154
|
)
|
|
1149
|
-
return dict(zip(flag_meanings, flag_params))
|
|
1155
|
+
return dict(zip(flag_meanings, flag_params, strict=False))
|
|
1150
1156
|
|
|
1151
1157
|
|
|
1152
1158
|
class CFAccessor:
|
|
@@ -1362,7 +1368,7 @@ class CFAccessor:
|
|
|
1362
1368
|
kwargs: dict[str, Any] | None = None,
|
|
1363
1369
|
):
|
|
1364
1370
|
if coords is not None:
|
|
1365
|
-
if isinstance(coords,
|
|
1371
|
+
if isinstance(coords, Hashable | DataArray):
|
|
1366
1372
|
coords_iter: Iterable[Hashable | DataArray] = [coords]
|
|
1367
1373
|
else:
|
|
1368
1374
|
coords_iter = coords
|
|
@@ -2748,13 +2754,8 @@ class CFDatasetAccessor(CFAccessor):
|
|
|
2748
2754
|
"""
|
|
2749
2755
|
ds = self._obj
|
|
2750
2756
|
|
|
2751
|
-
requirements = {
|
|
2752
|
-
"ocean_s_coordinate_g1": {"depth_c", "depth", "s", "C", "eta"},
|
|
2753
|
-
"ocean_s_coordinate_g2": {"depth_c", "depth", "s", "C", "eta"},
|
|
2754
|
-
"ocean_sigma_coordinate": {"sigma", "eta", "depth"},
|
|
2755
|
-
}
|
|
2756
|
-
|
|
2757
2757
|
allterms = self.formula_terms
|
|
2758
|
+
|
|
2758
2759
|
for dim in allterms:
|
|
2759
2760
|
if prefix is None:
|
|
2760
2761
|
assert (
|
|
@@ -2776,6 +2777,7 @@ class CFDatasetAccessor(CFAccessor):
|
|
|
2776
2777
|
suffix = dim.split("_")
|
|
2777
2778
|
zname = f"{prefix}_" + "_".join(suffix[1:])
|
|
2778
2779
|
|
|
2780
|
+
# never touched, if standard name is missing it's not included in allterms
|
|
2779
2781
|
if "standard_name" not in ds[dim].attrs:
|
|
2780
2782
|
continue
|
|
2781
2783
|
stdname = ds[dim].attrs["standard_name"]
|
|
@@ -2784,46 +2786,23 @@ class CFDatasetAccessor(CFAccessor):
|
|
|
2784
2786
|
terms = {}
|
|
2785
2787
|
for key, value in allterms[dim].items():
|
|
2786
2788
|
if value not in ds:
|
|
2789
|
+
# is this ever hit, if variable is missing it's missing in decoded allterms
|
|
2787
2790
|
raise KeyError(
|
|
2788
2791
|
f"Variable {value!r} is required to decode coordinate for {dim!r}"
|
|
2789
2792
|
" but it is absent in the Dataset."
|
|
2790
2793
|
)
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
absent_terms = requirements[stdname] - set(terms)
|
|
2794
|
-
if absent_terms:
|
|
2795
|
-
raise KeyError(f"Required terms {absent_terms} absent in dataset.")
|
|
2796
|
-
|
|
2797
|
-
if stdname == "ocean_s_coordinate_g1":
|
|
2798
|
-
# S(k,j,i) = depth_c * s(k) + (depth(j,i) - depth_c) * C(k)
|
|
2799
|
-
S = (
|
|
2800
|
-
terms["depth_c"] * terms["s"]
|
|
2801
|
-
+ (terms["depth"] - terms["depth_c"]) * terms["C"]
|
|
2802
|
-
)
|
|
2794
|
+
# keys should be case insensitive
|
|
2795
|
+
terms[key.lower()] = ds[value]
|
|
2803
2796
|
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
# make sure all necessary terms are present in terms
|
|
2809
|
-
# (depth_c * s(k) + depth(j,i) * C(k)) / (depth_c + depth(j,i))
|
|
2810
|
-
S = (terms["depth_c"] * terms["s"] + terms["depth"] * terms["C"]) / (
|
|
2811
|
-
terms["depth_c"] + terms["depth"]
|
|
2812
|
-
)
|
|
2813
|
-
|
|
2814
|
-
# z(n,k,j,i) = eta(n,j,i) + (eta(n,j,i) + depth(j,i)) * S(k,j,i)
|
|
2815
|
-
ztemp = terms["eta"] + (terms["eta"] + terms["depth"]) * S
|
|
2816
|
-
|
|
2817
|
-
elif stdname == "ocean_sigma_coordinate":
|
|
2818
|
-
# z(n,k,j,i) = eta(n,j,i) + sigma(k)*(depth(j,i)+eta(n,j,i))
|
|
2819
|
-
ztemp = terms["eta"] + terms["sigma"] * (terms["depth"] + terms["eta"])
|
|
2820
|
-
|
|
2821
|
-
else:
|
|
2797
|
+
try:
|
|
2798
|
+
transform = parametric.TRANSFORM_FROM_STDNAME[stdname]
|
|
2799
|
+
except KeyError:
|
|
2800
|
+
# Should occur since stdname is check before
|
|
2822
2801
|
raise NotImplementedError(
|
|
2823
|
-
f"Coordinate function for {stdname!r} not
|
|
2824
|
-
)
|
|
2802
|
+
f"Coordinate function for {stdname!r} not implmented yet. Contributions welcome!"
|
|
2803
|
+
) from None
|
|
2825
2804
|
|
|
2826
|
-
ds.coords[zname] =
|
|
2805
|
+
ds.coords[zname] = transform.from_terms(terms)
|
|
2827
2806
|
|
|
2828
2807
|
|
|
2829
2808
|
@xr.register_dataarray_accessor("cf")
|
|
@@ -3018,7 +2997,7 @@ class CFDataArrayAccessor(CFAccessor):
|
|
|
3018
2997
|
x = self._obj.astype("i")
|
|
3019
2998
|
bit_comp = x & bit_mask
|
|
3020
2999
|
|
|
3021
|
-
for i, (flag, value) in enumerate(zip(flags_reduced, values)):
|
|
3000
|
+
for i, (flag, value) in enumerate(zip(flags_reduced, values, strict=False)):
|
|
3022
3001
|
bit = bit_comp.isel(_mask=i)
|
|
3023
3002
|
if value is not None:
|
|
3024
3003
|
out[flag] = bit == value
|
|
@@ -46,7 +46,7 @@ def encode_multi_index_as_compress(ds, idxnames=None):
|
|
|
46
46
|
encoded = ds.reset_index(idxnames)
|
|
47
47
|
for idxname in idxnames:
|
|
48
48
|
mindex = ds.indexes[idxname]
|
|
49
|
-
coords = dict(zip(mindex.names, mindex.levels))
|
|
49
|
+
coords = dict(zip(mindex.names, mindex.levels, strict=False))
|
|
50
50
|
encoded.update(coords)
|
|
51
51
|
for c in coords:
|
|
52
52
|
encoded[c].attrs = ds[c].attrs
|
|
@@ -112,13 +112,16 @@ def decode_compress_to_multi_index(encoded, idxnames=None):
|
|
|
112
112
|
|
|
113
113
|
variables = {
|
|
114
114
|
dim: encoded[dim].isel({dim: xr.Variable(data=index, dims=idxname)})
|
|
115
|
-
for dim, index in zip(names, indices)
|
|
115
|
+
for dim, index in zip(names, indices, strict=False)
|
|
116
116
|
}
|
|
117
117
|
decoded = decoded.assign_coords(variables).set_xindex(
|
|
118
118
|
names, PandasMultiIndex
|
|
119
119
|
)
|
|
120
120
|
except ImportError:
|
|
121
|
-
arrays = [
|
|
121
|
+
arrays = [
|
|
122
|
+
encoded[dim].data[index]
|
|
123
|
+
for dim, index in zip(names, indices, strict=False)
|
|
124
|
+
]
|
|
122
125
|
mindex = pd.MultiIndex.from_arrays(arrays, names=names)
|
|
123
126
|
decoded.coords[idxname] = mindex
|
|
124
127
|
|
|
@@ -268,14 +268,14 @@ def _format_flags(accessor, rich):
|
|
|
268
268
|
table.add_column("Value", justify="right")
|
|
269
269
|
table.add_column("Bits", justify="center")
|
|
270
270
|
|
|
271
|
-
for val, bit, key in zip(value_text, bit_text, flag_dict):
|
|
271
|
+
for val, bit, key in zip(value_text, bit_text, flag_dict, strict=False):
|
|
272
272
|
table.add_row(_format_cf_name(key, rich), val, bit)
|
|
273
273
|
|
|
274
274
|
return table
|
|
275
275
|
|
|
276
276
|
else:
|
|
277
277
|
rows = []
|
|
278
|
-
for val, bit, key in zip(value_text, bit_text, flag_dict):
|
|
278
|
+
for val, bit, key in zip(value_text, bit_text, flag_dict, strict=False):
|
|
279
279
|
rows.append(
|
|
280
280
|
f"{TAB}{_format_cf_name(key, rich):>{key_width}}: {TAB} {val} {bit}"
|
|
281
281
|
)
|
|
@@ -324,7 +324,7 @@ def encode_geometries(ds: xr.Dataset):
|
|
|
324
324
|
# TODO: this is incomplete. It works for vector data cubes where one of the geometry vars
|
|
325
325
|
# is a dimension coordinate.
|
|
326
326
|
if name in var.dims:
|
|
327
|
-
var = var.copy()
|
|
327
|
+
var = var.copy(deep=False)
|
|
328
328
|
var._attrs = copy.deepcopy(var._attrs)
|
|
329
329
|
var.attrs["geometry"] = container_name
|
|
330
330
|
# The grid_mapping and coordinates attributes can be carried by the geometry container
|
|
@@ -459,11 +459,8 @@ def shapely_to_cf(
|
|
|
459
459
|
"and set the grid mapping variable as a coordinate",
|
|
460
460
|
)
|
|
461
461
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
geom.item().geom_type if isinstance(geom, xr.DataArray) else geom.geom_type
|
|
465
|
-
for geom in geometries
|
|
466
|
-
}
|
|
462
|
+
as_data = geometries.data if isinstance(geometries, xr.DataArray) else geometries
|
|
463
|
+
type_ = as_data[0].geom_type
|
|
467
464
|
|
|
468
465
|
grid_mapping_varname = None
|
|
469
466
|
if (
|
|
@@ -482,16 +479,21 @@ def shapely_to_cf(
|
|
|
482
479
|
suffix=suffix, grid_mapping_name=grid_mapping, grid_mapping=grid_mapping_varname
|
|
483
480
|
)
|
|
484
481
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
482
|
+
try:
|
|
483
|
+
if type_ in ["Point", "MultiPoint"]:
|
|
484
|
+
ds = points_to_cf(geometries, names=names)
|
|
485
|
+
elif type_ in ["LineString", "MultiLineString"]:
|
|
486
|
+
ds = lines_to_cf(geometries, names=names)
|
|
487
|
+
elif type_ in ["Polygon", "MultiPolygon"]:
|
|
488
|
+
ds = polygons_to_cf(geometries, names=names)
|
|
489
|
+
else:
|
|
490
|
+
raise ValueError(
|
|
491
|
+
f"This geometry type is not supported in CF-compliant datasets. Got {type_}"
|
|
492
|
+
)
|
|
493
|
+
except NotImplementedError as e:
|
|
492
494
|
raise ValueError(
|
|
493
|
-
|
|
494
|
-
)
|
|
495
|
+
"Error converting geometries. Possibly you have provided mixed geometry types."
|
|
496
|
+
) from e
|
|
495
497
|
|
|
496
498
|
return ds
|
|
497
499
|
|
|
@@ -841,7 +843,7 @@ def polygons_to_cf(
|
|
|
841
843
|
node_count = part_node_count
|
|
842
844
|
elif len(offsets) >= 2:
|
|
843
845
|
indices = np.take(offsets[0], offsets[1])
|
|
844
|
-
interior_ring = np.isin(offsets[0], indices, invert=True)[:-1]
|
|
846
|
+
interior_ring = np.isin(offsets[0], indices, invert=True)[:-1]
|
|
845
847
|
|
|
846
848
|
if len(offsets) == 3:
|
|
847
849
|
indices = np.take(indices, offsets[2])
|
|
@@ -852,29 +854,32 @@ def polygons_to_cf(
|
|
|
852
854
|
crdX = geom_coords[:, 0]
|
|
853
855
|
crdY = geom_coords[:, 1]
|
|
854
856
|
|
|
857
|
+
data_vars = {names.node_count: (dim, node_count)}
|
|
858
|
+
geometry_attrs = names.geometry_container_attrs
|
|
859
|
+
|
|
860
|
+
# Special case when we have no MultiPolygons and no holes
|
|
861
|
+
if len(part_node_count) != len(node_count):
|
|
862
|
+
data_vars[names.part_node_count] = (names.part_dim, part_node_count)
|
|
863
|
+
geometry_attrs["part_node_count"] = names.part_node_count
|
|
864
|
+
|
|
865
|
+
# Special case when we have no holes
|
|
866
|
+
if interior_ring.any():
|
|
867
|
+
data_vars[names.interior_ring] = (names.part_dim, interior_ring)
|
|
868
|
+
geometry_attrs["interior_ring"] = names.interior_ring
|
|
869
|
+
|
|
870
|
+
data_vars[names.container_name] = ( # type: ignore[assignment]
|
|
871
|
+
(),
|
|
872
|
+
np.nan,
|
|
873
|
+
{"geometry_type": "polygon", **geometry_attrs},
|
|
874
|
+
)
|
|
855
875
|
ds = xr.Dataset(
|
|
856
|
-
data_vars=
|
|
857
|
-
names.node_count: xr.DataArray(node_count, dims=(dim,)),
|
|
858
|
-
names.container_name: xr.DataArray(
|
|
859
|
-
data=np.nan,
|
|
860
|
-
attrs={"geometry_type": "polygon", **names.geometry_container_attrs},
|
|
861
|
-
),
|
|
862
|
-
},
|
|
876
|
+
data_vars=data_vars,
|
|
863
877
|
coords=names.coords(x=x, y=y, crdX=crdX, crdY=crdY, dim=dim),
|
|
864
878
|
)
|
|
865
879
|
|
|
866
880
|
if coord is not None:
|
|
867
881
|
ds = ds.assign_coords({dim: coord})
|
|
868
882
|
|
|
869
|
-
# Special case when we have no MultiPolygons and no holes
|
|
870
|
-
if len(part_node_count) != len(node_count):
|
|
871
|
-
ds[names.part_node_count] = xr.DataArray(part_node_count, dims=names.part_dim)
|
|
872
|
-
ds[names.container_name].attrs["part_node_count"] = names.part_node_count
|
|
873
|
-
|
|
874
|
-
# Special case when we have no holes
|
|
875
|
-
if (interior_ring != 0).any():
|
|
876
|
-
ds[names.interior_ring] = xr.DataArray(interior_ring, dims=names.part_dim)
|
|
877
|
-
ds[names.container_name].attrs["interior_ring"] = names.interior_ring
|
|
878
883
|
return ds
|
|
879
884
|
|
|
880
885
|
|