cf-xarray 0.10.0__tar.gz → 0.10.2__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.10.0 → cf_xarray-0.10.2}/.github/workflows/ci.yaml +28 -33
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.github/workflows/pypi.yaml +2 -2
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.github/workflows/upstream-dev-ci.yaml +2 -2
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.pre-commit-config.yaml +7 -19
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.readthedocs.yml +2 -1
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/PKG-INFO +4 -3
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/__init__.py +6 -1
- cf_xarray-0.10.2/cf_xarray/_version.py +1 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/accessor.py +14 -6
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/datasets.py +7 -7
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/geometry.py +10 -1
- cf_xarray-0.10.2/cf_xarray/groupers.py +40 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/options.py +0 -1
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/__init__.py +1 -2
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/test_accessor.py +4 -3
- cf_xarray-0.10.2/cf_xarray/tests/test_groupers.py +47 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/utils.py +6 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray.egg-info/PKG-INFO +4 -3
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray.egg-info/SOURCES.txt +3 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray.egg-info/requires.txt +1 -1
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/ci/doc.yml +1 -1
- cf_xarray-0.10.2/ci/environment-all-min-deps.yml +24 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/api.rst +8 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/bounds.md +1 -1
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/coord_axes.md +2 -2
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/custom-criteria.md +1 -1
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/flags.md +32 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/selecting.md +3 -3
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/sgrid_ugrid.md +1 -1
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/units.md +2 -2
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/pyproject.toml +12 -9
- cf_xarray-0.10.0/cf_xarray/_version.py +0 -1
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.binder/environment.yml +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.deepsource.toml +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.github/dependabot.yml +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.github/release.yml +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.github/workflows/parse_logs.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.github/workflows/testpypi-release.yaml +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.gitignore +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/.tributors +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/CITATION.cff +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/LICENSE +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/README.rst +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/coding.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/criteria.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/formatting.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/helpers.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/parametric.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/py.typed +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/scripts/make_doc.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/scripts/print_versions.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/sgrid.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/conftest.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/test_coding.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/test_geometry.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/test_helpers.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/test_options.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/test_parametric.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/test_scripts.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/tests/test_units.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray/units.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray.egg-info/dependency_links.txt +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/cf_xarray.egg-info/top_level.txt +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/ci/environment-no-optional-deps.yml +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/ci/environment.yml +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/ci/upstream-dev-env.yml +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/codecov.yml +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/2D_bounds_averaged.png +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/2D_bounds_error.png +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/2D_bounds_nonunique.png +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/Makefile +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/_static/dataset-diagram-logo.tex +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/_static/full-logo.png +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/_static/logo.png +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/_static/logo.svg +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/_static/rich-repr-example.png +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/_static/style.css +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/cartopy_rotated_pole.png +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/coding.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/conf.py +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/contributing.rst +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/dsg.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/examples/introduction.ipynb +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/faq.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/geometry.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/grid_mappings.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/howtouse.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/index.rst +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/make.bat +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/parametricz.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/plotting.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/provenance.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/quickstart.md +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/roadmap.rst +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/doc/whats-new.rst +0 -0
- {cf_xarray-0.10.0 → cf_xarray-0.10.2}/setup.cfg +0 -0
|
@@ -18,7 +18,7 @@ env:
|
|
|
18
18
|
|
|
19
19
|
jobs:
|
|
20
20
|
build:
|
|
21
|
-
name: Build (${{ matrix.python-version }}, ${{ matrix.os }})
|
|
21
|
+
name: Build (${{ matrix.python-version }}, ${{ matrix.os }}), ${{ matrix.env }}
|
|
22
22
|
runs-on: ${{ matrix.os }}
|
|
23
23
|
defaults:
|
|
24
24
|
run:
|
|
@@ -27,7 +27,15 @@ jobs:
|
|
|
27
27
|
fail-fast: false
|
|
28
28
|
matrix:
|
|
29
29
|
os: ["ubuntu-latest"]
|
|
30
|
-
python-version: ["3.10", "3.
|
|
30
|
+
python-version: ["3.10", "3.13"]
|
|
31
|
+
env: [""]
|
|
32
|
+
include:
|
|
33
|
+
- env: "all-min-deps"
|
|
34
|
+
python-version: "3.10"
|
|
35
|
+
os: ubuntu-latest
|
|
36
|
+
- env: "no-optional-deps"
|
|
37
|
+
python-version: "3.13"
|
|
38
|
+
os: ubuntu-latest
|
|
31
39
|
steps:
|
|
32
40
|
- uses: actions/checkout@v4
|
|
33
41
|
with:
|
|
@@ -35,10 +43,22 @@ jobs:
|
|
|
35
43
|
- name: Set environment variables
|
|
36
44
|
run: |
|
|
37
45
|
echo "PYTHON_VERSION=${{ matrix.python-version }}" >> $GITHUB_ENV
|
|
46
|
+
if [[ "${{ matrix.env }}" == "" ]] ;
|
|
47
|
+
then
|
|
48
|
+
echo "CONDA_ENV_FILE=ci/environment.yml" >> $GITHUB_ENV
|
|
49
|
+
fi
|
|
50
|
+
if [[ "${{ matrix.env }}" == "no-optional-deps" ]] ;
|
|
51
|
+
then
|
|
52
|
+
echo "CONDA_ENV_FILE=ci/environment-no-optional-deps.yml" >> $GITHUB_ENV
|
|
53
|
+
fi
|
|
54
|
+
if [[ "${{ matrix.env }}" == "all-min-deps" ]] ;
|
|
55
|
+
then
|
|
56
|
+
echo "CONDA_ENV_FILE=ci/environment-all-min-deps.yml" >> $GITHUB_ENV
|
|
57
|
+
fi
|
|
38
58
|
- name: Set up conda environment
|
|
39
|
-
uses: mamba-org/setup-micromamba@
|
|
59
|
+
uses: mamba-org/setup-micromamba@v2
|
|
40
60
|
with:
|
|
41
|
-
environment-file:
|
|
61
|
+
environment-file: ${{ env.CONDA_ENV_FILE }}
|
|
42
62
|
environment-name: cf_xarray_test
|
|
43
63
|
cache-environment: true
|
|
44
64
|
create-args: >-
|
|
@@ -50,7 +70,7 @@ jobs:
|
|
|
50
70
|
run: |
|
|
51
71
|
pytest -n auto --cov=./ --cov-report=xml
|
|
52
72
|
- name: Upload code coverage to Codecov
|
|
53
|
-
uses: codecov/codecov-action@
|
|
73
|
+
uses: codecov/codecov-action@v5.4.0
|
|
54
74
|
with:
|
|
55
75
|
file: ./coverage.xml
|
|
56
76
|
flags: unittests
|
|
@@ -58,31 +78,6 @@ jobs:
|
|
|
58
78
|
name: codecov-umbrella
|
|
59
79
|
fail_ci_if_error: false
|
|
60
80
|
|
|
61
|
-
no-optional-deps:
|
|
62
|
-
name: no-optional-deps
|
|
63
|
-
runs-on: ubuntu-latest
|
|
64
|
-
defaults:
|
|
65
|
-
run:
|
|
66
|
-
shell: bash -l {0}
|
|
67
|
-
steps:
|
|
68
|
-
- uses: actions/checkout@v4
|
|
69
|
-
with:
|
|
70
|
-
# need to fetch all tags to get a correct version
|
|
71
|
-
fetch-depth: 0 # fetch all branches and tags
|
|
72
|
-
- name: Set up conda environment
|
|
73
|
-
uses: mamba-org/setup-micromamba@v1
|
|
74
|
-
with:
|
|
75
|
-
environment-file: ci/environment-no-optional-deps.yml
|
|
76
|
-
environment-name: cf_xarray_test
|
|
77
|
-
cache-environment: true
|
|
78
|
-
- name: Install cf_xarray
|
|
79
|
-
run: |
|
|
80
|
-
python -m pip install --no-deps -e .
|
|
81
|
-
- name: Run Tests
|
|
82
|
-
shell: bash -l {0}
|
|
83
|
-
run: |
|
|
84
|
-
pytest -n 2
|
|
85
|
-
|
|
86
81
|
mypy:
|
|
87
82
|
name: mypy
|
|
88
83
|
runs-on: "ubuntu-latest"
|
|
@@ -91,13 +86,13 @@ jobs:
|
|
|
91
86
|
shell: bash -l {0}
|
|
92
87
|
strategy:
|
|
93
88
|
matrix:
|
|
94
|
-
python-version: ["3.10", "3.
|
|
89
|
+
python-version: ["3.10", "3.13"]
|
|
95
90
|
steps:
|
|
96
91
|
- uses: actions/checkout@v4
|
|
97
92
|
with:
|
|
98
93
|
fetch-depth: 0 # Fetch all history for all branches and tags.
|
|
99
94
|
- name: Set up conda environment
|
|
100
|
-
uses: mamba-org/setup-micromamba@
|
|
95
|
+
uses: mamba-org/setup-micromamba@v2
|
|
101
96
|
with:
|
|
102
97
|
environment-file: ci/environment.yml
|
|
103
98
|
environment-name: cf_xarray_test
|
|
@@ -114,7 +109,7 @@ jobs:
|
|
|
114
109
|
run: |
|
|
115
110
|
python -m mypy --install-types --non-interactive --cobertura-xml-report mypy_report cf_xarray/
|
|
116
111
|
- name: Upload mypy coverage to Codecov
|
|
117
|
-
uses: codecov/codecov-action@
|
|
112
|
+
uses: codecov/codecov-action@v5.4.0
|
|
118
113
|
with:
|
|
119
114
|
file: mypy_report/cobertura.xml
|
|
120
115
|
flags: mypy
|
|
@@ -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.12.4
|
|
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.12.4
|
|
100
100
|
with:
|
|
101
101
|
verbose: true
|
|
@@ -29,7 +29,7 @@ jobs:
|
|
|
29
29
|
strategy:
|
|
30
30
|
fail-fast: false
|
|
31
31
|
matrix:
|
|
32
|
-
python-version: ["3.
|
|
32
|
+
python-version: ["3.13"]
|
|
33
33
|
steps:
|
|
34
34
|
- uses: actions/checkout@v4
|
|
35
35
|
with:
|
|
@@ -38,7 +38,7 @@ jobs:
|
|
|
38
38
|
run: |
|
|
39
39
|
echo "PYTHON_VERSION=${{ matrix.python-version }}" >> $GITHUB_ENV
|
|
40
40
|
- name: Set up conda environment
|
|
41
|
-
uses: mamba-org/setup-micromamba@
|
|
41
|
+
uses: mamba-org/setup-micromamba@v2
|
|
42
42
|
with:
|
|
43
43
|
environment-file: ci/upstream-dev-env.yml
|
|
44
44
|
environment-name: cf_xarray_test
|
|
@@ -3,22 +3,18 @@ ci:
|
|
|
3
3
|
|
|
4
4
|
repos:
|
|
5
5
|
- repo: https://github.com/asottile/pyupgrade
|
|
6
|
-
rev: v3.
|
|
6
|
+
rev: v3.19.1
|
|
7
7
|
hooks:
|
|
8
8
|
- id: pyupgrade
|
|
9
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.9.3'
|
|
14
14
|
hooks:
|
|
15
15
|
- id: ruff
|
|
16
|
-
args: ["--
|
|
17
|
-
|
|
18
|
-
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
19
|
-
rev: 24.10.0
|
|
20
|
-
hooks:
|
|
21
|
-
- id: black
|
|
16
|
+
args: ["--fix", "--show-fixes"]
|
|
17
|
+
- id: ruff-format
|
|
22
18
|
|
|
23
19
|
- repo: https://github.com/rstcheck/rstcheck
|
|
24
20
|
rev: v6.2.4
|
|
@@ -28,7 +24,7 @@ repos:
|
|
|
28
24
|
args: ['--config', 'pyproject.toml']
|
|
29
25
|
|
|
30
26
|
- repo: https://github.com/executablebooks/mdformat
|
|
31
|
-
rev: 0.7.
|
|
27
|
+
rev: 0.7.21
|
|
32
28
|
hooks:
|
|
33
29
|
- id: mdformat
|
|
34
30
|
additional_dependencies:
|
|
@@ -36,10 +32,8 @@ repos:
|
|
|
36
32
|
- mdformat-myst
|
|
37
33
|
|
|
38
34
|
- repo: https://github.com/nbQA-dev/nbQA
|
|
39
|
-
rev: 1.
|
|
35
|
+
rev: 1.9.1
|
|
40
36
|
hooks:
|
|
41
|
-
- id: nbqa-black
|
|
42
|
-
- id: nbqa-ruff
|
|
43
37
|
- id: nbqa
|
|
44
38
|
entry: nbqa mdformat
|
|
45
39
|
name: nbqa-mdformat
|
|
@@ -55,19 +49,13 @@ repos:
|
|
|
55
49
|
- id: check-yaml
|
|
56
50
|
- id: debug-statements
|
|
57
51
|
|
|
58
|
-
- repo: https://github.com/keewis/blackdoc
|
|
59
|
-
rev: v0.3.9
|
|
60
|
-
hooks:
|
|
61
|
-
- id: blackdoc
|
|
62
|
-
files: .+\.py$
|
|
63
|
-
|
|
64
52
|
- repo: https://github.com/citation-file-format/cff-converter-python
|
|
65
53
|
rev: "44e8fc9"
|
|
66
54
|
hooks:
|
|
67
55
|
- id: validate-cff
|
|
68
56
|
|
|
69
57
|
- repo: https://github.com/abravalheri/validate-pyproject
|
|
70
|
-
rev: v0.
|
|
58
|
+
rev: v0.23
|
|
71
59
|
hooks:
|
|
72
60
|
- id: validate-pyproject
|
|
73
61
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: cf_xarray
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.2
|
|
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
|
|
@@ -217,10 +217,11 @@ Classifier: Programming Language :: Python
|
|
|
217
217
|
Classifier: Programming Language :: Python :: 3.10
|
|
218
218
|
Classifier: Programming Language :: Python :: 3.11
|
|
219
219
|
Classifier: Programming Language :: Python :: 3.12
|
|
220
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
220
221
|
Requires-Python: >=3.10
|
|
221
222
|
Description-Content-Type: text/x-rst
|
|
222
223
|
License-File: LICENSE
|
|
223
|
-
Requires-Dist: xarray>=
|
|
224
|
+
Requires-Dist: xarray>=2023.09.0
|
|
224
225
|
Provides-Extra: all
|
|
225
226
|
Requires-Dist: matplotlib; extra == "all"
|
|
226
227
|
Requires-Dist: pint!=0.24.0,>=0.18; extra == "all"
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import xarray
|
|
2
|
+
from packaging.version import Version
|
|
3
|
+
|
|
4
|
+
from . import geometry as geometry
|
|
1
5
|
from . import sgrid # noqa
|
|
2
6
|
from .accessor import CFAccessor # noqa
|
|
3
7
|
from .coding import ( # noqa
|
|
@@ -9,6 +13,7 @@ from .helpers import bounds_to_vertices, vertices_to_bounds # noqa
|
|
|
9
13
|
from .options import set_options # noqa
|
|
10
14
|
from .utils import _get_version
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
if Version(xarray.__version__) >= Version("2024.07.0"):
|
|
17
|
+
from . import groupers as groupers
|
|
13
18
|
|
|
14
19
|
__version__ = _get_version()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.10.2"
|
|
@@ -680,7 +680,7 @@ def _getattr(
|
|
|
680
680
|
None,
|
|
681
681
|
):
|
|
682
682
|
raise AttributeError(
|
|
683
|
-
f"{obj.__class__.__name__+'.cf'!r} object has no attribute {attr!r}"
|
|
683
|
+
f"{obj.__class__.__name__ + '.cf'!r} object has no attribute {attr!r}"
|
|
684
684
|
) from None
|
|
685
685
|
raise AttributeError(
|
|
686
686
|
f"{attr!r} is not a valid attribute on the underlying xarray object."
|
|
@@ -1374,7 +1374,11 @@ class CFAccessor:
|
|
|
1374
1374
|
coords_iter = coords
|
|
1375
1375
|
coords = [
|
|
1376
1376
|
apply_mapper(
|
|
1377
|
-
[_single(_get_coords)],
|
|
1377
|
+
[_single(_get_coords)], # type:ignore[arg-type]
|
|
1378
|
+
self._obj,
|
|
1379
|
+
v,
|
|
1380
|
+
error=False,
|
|
1381
|
+
default=[v],
|
|
1378
1382
|
)[0]
|
|
1379
1383
|
for v in coords_iter
|
|
1380
1384
|
]
|
|
@@ -1385,7 +1389,11 @@ class CFAccessor:
|
|
|
1385
1389
|
reduce_dims_iter = list(reduce_dims)
|
|
1386
1390
|
reduce_dims = [
|
|
1387
1391
|
apply_mapper(
|
|
1388
|
-
[_single(_get_dims)],
|
|
1392
|
+
[_single(_get_dims)], # type:ignore[arg-type]
|
|
1393
|
+
self._obj,
|
|
1394
|
+
v,
|
|
1395
|
+
error=False,
|
|
1396
|
+
default=[v],
|
|
1389
1397
|
)[0]
|
|
1390
1398
|
for v in reduce_dims_iter
|
|
1391
1399
|
]
|
|
@@ -2758,9 +2766,9 @@ class CFDatasetAccessor(CFAccessor):
|
|
|
2758
2766
|
|
|
2759
2767
|
for dim in allterms:
|
|
2760
2768
|
if prefix is None:
|
|
2761
|
-
assert (
|
|
2762
|
-
|
|
2763
|
-
)
|
|
2769
|
+
assert outnames is not None, (
|
|
2770
|
+
"if prefix is None, outnames must be provided"
|
|
2771
|
+
)
|
|
2764
2772
|
# set outnames here
|
|
2765
2773
|
try:
|
|
2766
2774
|
zname = outnames[dim]
|
|
@@ -21,15 +21,14 @@ ds_with_tuple = airds.rename({"air": (1, 2, 3)})
|
|
|
21
21
|
|
|
22
22
|
# POM dataset
|
|
23
23
|
pomds = xr.Dataset()
|
|
24
|
+
# fmt: off
|
|
24
25
|
pomds["sigma"] = (
|
|
25
|
-
# fmt: off
|
|
26
26
|
"sigma",
|
|
27
27
|
[-0.983333, -0.95 , -0.916667, -0.883333, -0.85 , -0.816667,
|
|
28
28
|
-0.783333, -0.75 , -0.716667, -0.683333, -0.65 , -0.616667,
|
|
29
29
|
-0.583333, -0.55 , -0.516667, -0.483333, -0.45 , -0.416667,
|
|
30
30
|
-0.383333, -0.35 , -0.316667, -0.283333, -0.25 , -0.216667,
|
|
31
31
|
-0.183333, -0.15 , -0.116667, -0.083333, -0.05 , -0.016667],
|
|
32
|
-
# fmt: on
|
|
33
32
|
{
|
|
34
33
|
"units": "sigma_level",
|
|
35
34
|
"long_name": "Sigma Stretched Vertical Coordinate at Nodes",
|
|
@@ -38,6 +37,7 @@ pomds["sigma"] = (
|
|
|
38
37
|
"formula_terms": "sigma: sigma eta: zeta depth: depth",
|
|
39
38
|
}
|
|
40
39
|
)
|
|
40
|
+
# fmt: on
|
|
41
41
|
pomds["depth"] = 175.0
|
|
42
42
|
pomds["zeta"] = ("ocean_time", [-0.155356, -0.127435])
|
|
43
43
|
|
|
@@ -109,15 +109,14 @@ multiple["v2"] = (("x2", "y2"), np.ones((10, 5)) * 15)
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
romsds = xr.Dataset()
|
|
112
|
+
# fmt: off
|
|
112
113
|
romsds["s_rho"] = (
|
|
113
|
-
# fmt: off
|
|
114
114
|
"s_rho",
|
|
115
115
|
[-0.983333, -0.95 , -0.916667, -0.883333, -0.85 , -0.816667,
|
|
116
116
|
-0.783333, -0.75 , -0.716667, -0.683333, -0.65 , -0.616667,
|
|
117
117
|
-0.583333, -0.55 , -0.516667, -0.483333, -0.45 , -0.416667,
|
|
118
118
|
-0.383333, -0.35 , -0.316667, -0.283333, -0.25 , -0.216667,
|
|
119
119
|
-0.183333, -0.15 , -0.116667, -0.083333, -0.05 , -0.016667],
|
|
120
|
-
# fmt: on
|
|
121
120
|
{
|
|
122
121
|
"long_name": "S-coordinate at RHO-points",
|
|
123
122
|
"valid_min": -1.0,
|
|
@@ -125,13 +124,14 @@ romsds["s_rho"] = (
|
|
|
125
124
|
"standard_name": "ocean_s_coordinate_g2",
|
|
126
125
|
"formula_terms": "s: s_rho C: Cs_r eta: zeta depth: h depth_c: hc",
|
|
127
126
|
"field": "s_rho, scalar",
|
|
128
|
-
}
|
|
127
|
+
},
|
|
129
128
|
)
|
|
129
|
+
# fmt: on
|
|
130
130
|
romsds.coords["hc"] = 20.0
|
|
131
131
|
romsds.coords["h"] = 603.9
|
|
132
132
|
romsds.coords["Vtransform"] = 2.0
|
|
133
|
+
# fmt: off
|
|
133
134
|
romsds.coords["Cs_r"] = (
|
|
134
|
-
# fmt: off
|
|
135
135
|
"s_rho",
|
|
136
136
|
[-9.33010396e-01, -8.09234736e-01, -6.98779853e-01, -6.01008926e-01,
|
|
137
137
|
-5.15058562e-01, -4.39938913e-01, -3.74609181e-01, -3.18031817e-01,
|
|
@@ -141,8 +141,8 @@ romsds.coords["Cs_r"] = (
|
|
|
141
141
|
-2.53860004e-02, -1.95414261e-02, -1.46880431e-02, -1.06952600e-02,
|
|
142
142
|
-7.45515186e-03, -4.87981407e-03, -2.89916971e-03, -1.45919898e-03,
|
|
143
143
|
-5.20560097e-04, -5.75774004e-05],
|
|
144
|
-
# fmt: on
|
|
145
144
|
)
|
|
145
|
+
# fmt: on
|
|
146
146
|
romsds["zeta"] = ("ocean_time", [-0.155356, -0.127435])
|
|
147
147
|
romsds["temp"] = (
|
|
148
148
|
("ocean_time", "s_rho"),
|
|
@@ -4,6 +4,7 @@ import copy
|
|
|
4
4
|
from collections import ChainMap
|
|
5
5
|
from collections.abc import Hashable, Sequence
|
|
6
6
|
from dataclasses import dataclass
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
7
8
|
|
|
8
9
|
import numpy as np
|
|
9
10
|
import pandas as pd
|
|
@@ -21,6 +22,9 @@ __all__ = [
|
|
|
21
22
|
]
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from shapely import MultiPoint, Point
|
|
27
|
+
|
|
24
28
|
# Useful convention language:
|
|
25
29
|
# 1. Whether linked to normal CF space-time coordinates with a nodes attribute or not, inclusion of such coordinates is
|
|
26
30
|
# recommended to maintain backward compatibility with software that has not implemented geometry capabilities.
|
|
@@ -547,7 +551,11 @@ def cf_to_shapely(ds: xr.Dataset, *, container: Hashable = GEOMETRY_CONTAINER_NA
|
|
|
547
551
|
return geometries.rename("geometry")
|
|
548
552
|
|
|
549
553
|
|
|
550
|
-
def points_to_cf(
|
|
554
|
+
def points_to_cf(
|
|
555
|
+
pts: xr.DataArray | Sequence[Point | MultiPoint],
|
|
556
|
+
*,
|
|
557
|
+
names: GeometryNames | None = None,
|
|
558
|
+
):
|
|
551
559
|
"""Get a list of points (shapely.geometry.[Multi]Point) and return a CF-compliant geometry dataset.
|
|
552
560
|
|
|
553
561
|
Parameters
|
|
@@ -563,6 +571,7 @@ def points_to_cf(pts: xr.DataArray | Sequence, *, names: GeometryNames | None =
|
|
|
563
571
|
"""
|
|
564
572
|
from shapely.geometry import MultiPoint
|
|
565
573
|
|
|
574
|
+
pts_: Sequence[Point | MultiPoint]
|
|
566
575
|
if isinstance(pts, xr.DataArray):
|
|
567
576
|
# TODO: Fix this hardcoding
|
|
568
577
|
if pts.ndim != 1:
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from xarray.groupers import EncodedGroups, UniqueGrouper
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class FlagGrouper(UniqueGrouper):
|
|
10
|
+
"""
|
|
11
|
+
Grouper object that allows convenient categorical grouping by a CF flag variable.
|
|
12
|
+
|
|
13
|
+
Labels in the grouped output will be restricted to those listed in ``flag_meanings``.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def factorize(self, group) -> EncodedGroups:
|
|
17
|
+
if "flag_values" not in group.attrs or "flag_meanings" not in group.attrs:
|
|
18
|
+
raise ValueError(
|
|
19
|
+
"FlagGrouper can only be used with flag variables that have"
|
|
20
|
+
"`flag_values` and `flag_meanings` specified in attrs."
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
values = np.array(group.attrs["flag_values"])
|
|
24
|
+
full_index = pd.Index(group.attrs["flag_meanings"].split(" "))
|
|
25
|
+
|
|
26
|
+
self.labels = values
|
|
27
|
+
|
|
28
|
+
# TODO: we could optimize here, since `group` is already factorized,
|
|
29
|
+
# but there are subtleties. For example, the attrs must be up to date,
|
|
30
|
+
# any value that is not in flag_values will cause an error, etc.
|
|
31
|
+
ret = super().factorize(group)
|
|
32
|
+
|
|
33
|
+
ret.codes.attrs.pop("flag_values")
|
|
34
|
+
ret.codes.attrs.pop("flag_meanings")
|
|
35
|
+
|
|
36
|
+
return EncodedGroups(
|
|
37
|
+
codes=ret.codes,
|
|
38
|
+
full_index=full_index,
|
|
39
|
+
group_indices=ret.group_indices,
|
|
40
|
+
)
|
|
@@ -38,7 +38,6 @@ class set_options: # numpydoc ignore=PR01,PR02
|
|
|
38
38
|
>>> ds = xr.Dataset({"elev": np.arange(1000)})
|
|
39
39
|
>>> with cf_xarray.set_options(custom_criteria=my_custom_criteria):
|
|
40
40
|
... xr.testing.assert_identical(ds["elev"], ds.cf["ssh"])
|
|
41
|
-
...
|
|
42
41
|
|
|
43
42
|
Or to set global options:
|
|
44
43
|
|
|
@@ -32,8 +32,7 @@ class CountingScheduler:
|
|
|
32
32
|
self.total_computes += 1
|
|
33
33
|
if self.total_computes > self.max_computes:
|
|
34
34
|
raise RuntimeError(
|
|
35
|
-
"Too many computes. Total:
|
|
36
|
-
% (self.total_computes, self.max_computes)
|
|
35
|
+
f"Too many computes. Total:{self.total_computes} > max: {self.max_computes}."
|
|
37
36
|
)
|
|
38
37
|
return dask.get(dsk, keys, **kwargs)
|
|
39
38
|
|
|
@@ -453,7 +453,7 @@ def test_rename_like() -> None:
|
|
|
453
453
|
@pytest.mark.parametrize(
|
|
454
454
|
"attr, xrkwargs, cfkwargs",
|
|
455
455
|
(
|
|
456
|
-
("resample", {"time": "
|
|
456
|
+
("resample", {"time": "ME"}, {"T": "ME"}),
|
|
457
457
|
("rolling", {"lat": 5}, {"Y": 5}),
|
|
458
458
|
("groupby", {"group": "time"}, {"group": "T"}),
|
|
459
459
|
("groupby", {"group": "time.month"}, {"group": "T.month"}),
|
|
@@ -1748,7 +1748,7 @@ def test_add_canonical_attributes(override, skip, verbose, capsys):
|
|
|
1748
1748
|
|
|
1749
1749
|
# Attributes have been added
|
|
1750
1750
|
for var in sum(ds.cf.standard_names.values(), []):
|
|
1751
|
-
assert set(ds[var].attrs)
|
|
1751
|
+
assert set(ds[var].attrs) <= set(cf_ds[var].attrs)
|
|
1752
1752
|
|
|
1753
1753
|
# Time units did not change
|
|
1754
1754
|
assert ds["time"].attrs.get("units") is cf_ds["time"].attrs.get("units") is None
|
|
@@ -2047,7 +2047,8 @@ def test_ancillary_variables_extra_dim():
|
|
|
2047
2047
|
),
|
|
2048
2048
|
}
|
|
2049
2049
|
)
|
|
2050
|
-
|
|
2050
|
+
with pytest.warns(UserWarning):
|
|
2051
|
+
assert_identical(ds.cf["X"], ds["x"])
|
|
2051
2052
|
|
|
2052
2053
|
|
|
2053
2054
|
def test_geometry_association(geometry_ds):
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
import xarray as xr
|
|
4
|
+
from xarray.testing import assert_identical
|
|
5
|
+
|
|
6
|
+
pytest.importorskip("xarray", "2024.07.0")
|
|
7
|
+
|
|
8
|
+
from cf_xarray.datasets import flag_excl
|
|
9
|
+
from cf_xarray.groupers import FlagGrouper
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_flag_grouper():
|
|
13
|
+
ds = flag_excl.to_dataset().set_coords("flag_var").copy(deep=True)
|
|
14
|
+
ds["foo"] = ("time", np.arange(8))
|
|
15
|
+
actual = ds.groupby(flag_var=FlagGrouper()).mean()
|
|
16
|
+
expected = ds.groupby("flag_var").mean()
|
|
17
|
+
expected["flag_var"] = ["flag_1", "flag_2", "flag_3"]
|
|
18
|
+
expected["flag_var"].attrs["standard_name"] = "flag_mutual_exclusive"
|
|
19
|
+
assert_identical(actual, expected)
|
|
20
|
+
|
|
21
|
+
del ds.flag_var.attrs["flag_values"]
|
|
22
|
+
with pytest.raises(ValueError):
|
|
23
|
+
ds.groupby(flag_var=FlagGrouper())
|
|
24
|
+
|
|
25
|
+
ds.flag_var.attrs["flag_values"] = [0, 1, 2]
|
|
26
|
+
del ds.flag_var.attrs["flag_meanings"]
|
|
27
|
+
with pytest.raises(ValueError):
|
|
28
|
+
ds.groupby(flag_var=FlagGrouper())
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.mark.parametrize(
|
|
32
|
+
"values",
|
|
33
|
+
[
|
|
34
|
+
[1, 2],
|
|
35
|
+
[1, 2, 3], # value out of range of flag_values
|
|
36
|
+
],
|
|
37
|
+
)
|
|
38
|
+
def test_flag_grouper_optimized(values):
|
|
39
|
+
ds = xr.Dataset(
|
|
40
|
+
{"foo": ("x", values, {"flag_values": [0, 1, 2], "flag_meanings": "a b c"})}
|
|
41
|
+
)
|
|
42
|
+
ret = FlagGrouper().factorize(ds.foo)
|
|
43
|
+
expected = ds.foo
|
|
44
|
+
expected.data[ds.foo.data > 2] = -1
|
|
45
|
+
del ds.foo.attrs["flag_meanings"]
|
|
46
|
+
del ds.foo.attrs["flag_values"]
|
|
47
|
+
assert_identical(ret.codes, ds.foo)
|
|
@@ -108,10 +108,16 @@ def parse_cf_standard_name_table(source=None):
|
|
|
108
108
|
if not source:
|
|
109
109
|
import pooch
|
|
110
110
|
|
|
111
|
+
downloader = pooch.HTTPDownloader(
|
|
112
|
+
# https://github.com/readthedocs/readthedocs.org/issues/11763
|
|
113
|
+
headers={"User-Agent": "cf-xarray"}
|
|
114
|
+
)
|
|
115
|
+
|
|
111
116
|
source = pooch.retrieve(
|
|
112
117
|
"https://raw.githubusercontent.com/cf-convention/cf-convention.github.io/"
|
|
113
118
|
"master/Data/cf-standard-names/current/src/cf-standard-name-table.xml",
|
|
114
119
|
known_hash=None,
|
|
120
|
+
downloader=downloader,
|
|
115
121
|
)
|
|
116
122
|
root = ElementTree.parse(source).getroot()
|
|
117
123
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: cf_xarray
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.2
|
|
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
|
|
@@ -217,10 +217,11 @@ Classifier: Programming Language :: Python
|
|
|
217
217
|
Classifier: Programming Language :: Python :: 3.10
|
|
218
218
|
Classifier: Programming Language :: Python :: 3.11
|
|
219
219
|
Classifier: Programming Language :: Python :: 3.12
|
|
220
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
220
221
|
Requires-Python: >=3.10
|
|
221
222
|
Description-Content-Type: text/x-rst
|
|
222
223
|
License-File: LICENSE
|
|
223
|
-
Requires-Dist: xarray>=
|
|
224
|
+
Requires-Dist: xarray>=2023.09.0
|
|
224
225
|
Provides-Extra: all
|
|
225
226
|
Requires-Dist: matplotlib; extra == "all"
|
|
226
227
|
Requires-Dist: pint!=0.24.0,>=0.18; extra == "all"
|
|
@@ -24,6 +24,7 @@ cf_xarray/criteria.py
|
|
|
24
24
|
cf_xarray/datasets.py
|
|
25
25
|
cf_xarray/formatting.py
|
|
26
26
|
cf_xarray/geometry.py
|
|
27
|
+
cf_xarray/groupers.py
|
|
27
28
|
cf_xarray/helpers.py
|
|
28
29
|
cf_xarray/options.py
|
|
29
30
|
cf_xarray/parametric.py
|
|
@@ -43,12 +44,14 @@ cf_xarray/tests/conftest.py
|
|
|
43
44
|
cf_xarray/tests/test_accessor.py
|
|
44
45
|
cf_xarray/tests/test_coding.py
|
|
45
46
|
cf_xarray/tests/test_geometry.py
|
|
47
|
+
cf_xarray/tests/test_groupers.py
|
|
46
48
|
cf_xarray/tests/test_helpers.py
|
|
47
49
|
cf_xarray/tests/test_options.py
|
|
48
50
|
cf_xarray/tests/test_parametric.py
|
|
49
51
|
cf_xarray/tests/test_scripts.py
|
|
50
52
|
cf_xarray/tests/test_units.py
|
|
51
53
|
ci/doc.yml
|
|
54
|
+
ci/environment-all-min-deps.yml
|
|
52
55
|
ci/environment-no-optional-deps.yml
|
|
53
56
|
ci/environment.yml
|
|
54
57
|
ci/upstream-dev-env.yml
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: cf_xarray_test
|
|
2
|
+
channels:
|
|
3
|
+
- conda-forge
|
|
4
|
+
dependencies:
|
|
5
|
+
- pytest-cov
|
|
6
|
+
- pytest
|
|
7
|
+
- pytest-xdist
|
|
8
|
+
- dask
|
|
9
|
+
- flox
|
|
10
|
+
- lxml
|
|
11
|
+
- matplotlib-base
|
|
12
|
+
- netcdf4
|
|
13
|
+
- pandas
|
|
14
|
+
- pint==0.19
|
|
15
|
+
- pooch
|
|
16
|
+
- regex
|
|
17
|
+
- rich
|
|
18
|
+
- pooch
|
|
19
|
+
- scipy
|
|
20
|
+
- shapely
|
|
21
|
+
- xarray==2023.09.0
|
|
22
|
+
- pip
|
|
23
|
+
- pip:
|
|
24
|
+
- pytest-pretty
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
`cf_xarray` supports parsing [coordinate bounds](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.10/cf-conventions.html#cell-boundaries) as encoded in the CF `bounds` attribute. A useful feature for incomplete dataset is also the automatic bounds estimation possible through `cf.add_bounds`. This method will estimate the missing bounds by finding the middle points between elements of the given coordinate, but also by extrapolating to find the outer bounds of the grid. This linear estimation works well with rectilinear grids, but it is only a coarse approximation for curvilinear and simple irregular grids.
|
|
16
16
|
|
|
17
|
-
As an example, we present a "rotated pole" grid. It is defined on a rotated rectilinear grid which uses the `rlat` and
|
|
17
|
+
As an example, we present a "rotated pole" grid. It is defined on a rotated rectilinear grid which uses the `rlat` and `rlon` 1D coordinates, over North America at a resolution of 0.44°. The datasets comes with 2D `lat` and `lon` coordinates. `cf_xarray` will estimate the bounds by linear interpolation (extrapolation at the edges) of the existing `lon` and `lat`, which yields good results on parts of the grid where the rotation is small. However the errors is larger in other places, as seen when visualizing the distance in degrees between the estimated bounds and the true bounds.
|
|
18
18
|
|
|
19
19
|

|
|
20
20
|
|
|
@@ -55,7 +55,7 @@ This table lists these internal criteria
|
|
|
55
55
|
:stub-columns: 1
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
Any DataArray that has `standard_name: "latitude"` or `_CoordinateAxisType: "Lat"` or `"units": "degrees_north"` in its `attrs` will be identified as the `"latitude"` variable by cf-xarray.
|
|
58
|
+
Any DataArray that has `standard_name: "latitude"` or `_CoordinateAxisType: "Lat"` or `"units": "degrees_north"` in its `attrs` will be identified as the `"latitude"` variable by cf-xarray. Similarly for other coordinate names.
|
|
59
59
|
|
|
60
60
|
## Axis Names
|
|
61
61
|
|
|
@@ -68,7 +68,7 @@ Similar criteria exist for the concept of "axes".
|
|
|
68
68
|
:stub-columns: 1
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
## `.axes` and
|
|
71
|
+
## `.axes` and `.coordinates` properties
|
|
72
72
|
|
|
73
73
|
Alternatively use the special properties {py:attr}`DataArray.cf.axes` or {py:attr}`DataArray.cf.coordinates` to access the variable names. These properties return dictionaries that map "CF names" to a list of variable names. Note that a list is always returned even if only one variable name matches the name `"latitude"` (for example).
|
|
74
74
|
|
|
@@ -73,7 +73,7 @@ with cfxr.set_options(custom_criteria=salt_criteria):
|
|
|
73
73
|
salty
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
Note that `salty` contains both `salt1` and `salt2`. Without setting these criteria, we
|
|
76
|
+
Note that `salty` contains both `salt1` and `salt2`. Without setting these criteria, we would only get `salt1` by default
|
|
77
77
|
|
|
78
78
|
```{code-cell}
|
|
79
79
|
ds.cf[["sea_water_salinity"]]
|
|
@@ -60,6 +60,38 @@ You can also check whether a DataArray has the appropriate attributes to be reco
|
|
|
60
60
|
da.cf.is_flag_variable
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
+
## GroupBy
|
|
64
|
+
|
|
65
|
+
Flag variables, such as that above, are naturally used for GroupBy operations.
|
|
66
|
+
cf-xarray provides a `FlagGrouper` that understands the `flag_meanings` and `flag_values` attributes.
|
|
67
|
+
|
|
68
|
+
Let's load an example dataset where the `flag_var` array has the needed attributes.
|
|
69
|
+
|
|
70
|
+
```{code-cell}
|
|
71
|
+
import cf_xarray as cfxr
|
|
72
|
+
import numpy as np
|
|
73
|
+
|
|
74
|
+
from cf_xarray.datasets import flag_excl
|
|
75
|
+
|
|
76
|
+
ds = flag_excl.to_dataset().set_coords('flag_var')
|
|
77
|
+
ds["foo"] = ("time", np.arange(8))
|
|
78
|
+
ds.flag_var
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Now use the :py:class:`~cf_xarray.groupers.FlagGrouper` to group by this flag variable:
|
|
82
|
+
|
|
83
|
+
```{code-cell}
|
|
84
|
+
from cf_xarray.groupers import FlagGrouper
|
|
85
|
+
|
|
86
|
+
ds.groupby(flag_var=FlagGrouper()).mean()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Note how the output coordinate has the values from `flag_meanings`!
|
|
90
|
+
|
|
91
|
+
```{seealso}
|
|
92
|
+
See the Xarray docs on using [Grouper objects](https://docs.xarray.dev/en/stable/user-guide/groupby.html#grouper-objects).
|
|
93
|
+
```
|
|
94
|
+
|
|
63
95
|
## Flag Masks
|
|
64
96
|
|
|
65
97
|
```{warning}
|
|
@@ -30,7 +30,7 @@ CF conventions on
|
|
|
30
30
|
1. [ancillary data](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#ancillary-data)
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
A powerful feature of `cf_xarray` is the ability select DataArrays using special "CF names" like the "latitude", or "longitude" coordinate names, "X"
|
|
33
|
+
A powerful feature of `cf_xarray` is the ability select DataArrays using special "CF names" like the "latitude", or "longitude" coordinate names, "X" or "Y" axes names, oreven using the `standard_name` attribute if present.
|
|
34
34
|
|
|
35
35
|
To demonstrate this, let's load a few datasets
|
|
36
36
|
|
|
@@ -91,7 +91,7 @@ anc
|
|
|
91
91
|
|
|
92
92
|
## Selecting multiple variables
|
|
93
93
|
|
|
94
|
-
Sometimes a Dataset may contain multiple `X` or multiple `longitude` variables. In that case a simple `.cf["X"]` will raise an error. Instead follow Xarray convention and pass a
|
|
94
|
+
Sometimes a Dataset may contain multiple `X` or multiple `longitude` variables. In that case a simple `.cf["X"]` will raise an error. Instead follow Xarray convention and pass a list `.cf[["X"]]` to receive a Dataset with all available `"X"` variables
|
|
95
95
|
|
|
96
96
|
```{code-cell}
|
|
97
97
|
multiple.cf[["X"]]
|
|
@@ -103,7 +103,7 @@ pop.cf[["longitude"]]
|
|
|
103
103
|
|
|
104
104
|
## Mixing names
|
|
105
105
|
|
|
106
|
-
cf_xarray aims to be as friendly as possible, so it is
|
|
106
|
+
cf_xarray aims to be as friendly as possible, so it is possible to mix "CF names" and normal variable names. Here we select `UVEL` and `TEMP` by using the `standard_name` of `TEMP` (which is `sea_water_potential_temperature`)
|
|
107
107
|
|
|
108
108
|
```{code-cell}
|
|
109
109
|
pop.cf[["sea_water_potential_temperature", "UVEL"]]
|
|
@@ -65,7 +65,7 @@ variable `grid` list many more dimension names.
|
|
|
65
65
|
|
|
66
66
|
### Topology variable
|
|
67
67
|
|
|
68
|
-
`cf_xarray` supports identifying
|
|
68
|
+
`cf_xarray` supports identifying the `mesh_topology` variable using the `cf_role` attribute.
|
|
69
69
|
|
|
70
70
|
## More?
|
|
71
71
|
|
|
@@ -14,9 +14,9 @@ hide-toc: true
|
|
|
14
14
|
1. [CF conventions on units](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#units)
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
The xarray ecosystem supports unit-aware arrays using
|
|
17
|
+
The xarray ecosystem supports unit-aware arrays using [pint](https://pint.readthedocs.io) and [pint-xarray](https://pint-xarray.readthedocs.io). Some changes are required to make these packages work well with [UDUNITS format recommended by the CF conventions](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#units).
|
|
18
18
|
|
|
19
|
-
`cf_xarray` makes those recommended changes when you `import cf_xarray.units`. These changes allow pint to parse and format UDUNIT units strings, and add several custom units like `degrees_north` for latitude, `psu` for ocean salinity, etc.
|
|
19
|
+
`cf_xarray` makes those recommended changes when you `import cf_xarray.units`. These changes allow pint to parse and format UDUNIT units strings, and add several custom units like `degrees_north` for latitude, `psu` for ocean salinity, etc. Be aware that pint supports some units that UDUNITS does not recognize but `cf-xarray` will not try to detect them and raise an error. For example, a temperature subtraction returns "delta_degC" units in pint, which does not exist in UDUNITS.
|
|
20
20
|
|
|
21
21
|
## Formatting units
|
|
22
22
|
|
|
@@ -14,9 +14,10 @@ classifiers = [
|
|
|
14
14
|
"Programming Language :: Python :: 3.10",
|
|
15
15
|
"Programming Language :: Python :: 3.11",
|
|
16
16
|
"Programming Language :: Python :: 3.12",
|
|
17
|
+
"Programming Language :: Python :: 3.13",
|
|
17
18
|
]
|
|
18
19
|
dependencies = [
|
|
19
|
-
"xarray>=
|
|
20
|
+
"xarray>=2023.09.0",
|
|
20
21
|
]
|
|
21
22
|
dynamic = ["version"]
|
|
22
23
|
|
|
@@ -32,7 +33,7 @@ changelog = "https://cf-xarray.readthedocs.io/en/latest/whats-new.html"
|
|
|
32
33
|
[build-system]
|
|
33
34
|
requires = [
|
|
34
35
|
# xarray is need for dynamic version string
|
|
35
|
-
"xarray>=
|
|
36
|
+
"xarray>=2023.09.0",
|
|
36
37
|
"setuptools>=45",
|
|
37
38
|
"setuptools_scm[toml]>=6.2",
|
|
38
39
|
]
|
|
@@ -53,9 +54,6 @@ write_to = "cf_xarray/_version.py"
|
|
|
53
54
|
write_to_template= '__version__ = "{version}"'
|
|
54
55
|
tag_regex= "^(?P<prefix>v)?(?P<version>[^\\+]+)(?P<suffix>.*)?$"
|
|
55
56
|
|
|
56
|
-
[tool.black]
|
|
57
|
-
target-version = ["py310"]
|
|
58
|
-
|
|
59
57
|
[tool.ruff]
|
|
60
58
|
target-version = "py310"
|
|
61
59
|
builtins = ["ellipsis"]
|
|
@@ -66,14 +64,18 @@ exclude = [
|
|
|
66
64
|
|
|
67
65
|
[tool.ruff.lint]
|
|
68
66
|
# E402: module level import not at top of file
|
|
69
|
-
# E501: line too long - let
|
|
67
|
+
# E501: line too long - let black worry about that
|
|
68
|
+
# E731: do not assign a lambda expression, use a def
|
|
70
69
|
ignore = [
|
|
71
70
|
"E402",
|
|
72
71
|
"E501",
|
|
72
|
+
"E731",
|
|
73
73
|
"B018",
|
|
74
74
|
"B015",
|
|
75
75
|
]
|
|
76
76
|
select = [
|
|
77
|
+
# Bugbear
|
|
78
|
+
"B",
|
|
77
79
|
# Pyflakes
|
|
78
80
|
"F",
|
|
79
81
|
# Pycodestyle
|
|
@@ -84,9 +86,6 @@ select = [
|
|
|
84
86
|
# Pyupgrade
|
|
85
87
|
"UP",
|
|
86
88
|
]
|
|
87
|
-
extend-select = [
|
|
88
|
-
"B", # flake8-bugbear
|
|
89
|
-
]
|
|
90
89
|
|
|
91
90
|
[tool.ruff.lint.isort]
|
|
92
91
|
known-first-party = ["cf_xarray"]
|
|
@@ -103,6 +102,10 @@ known-third-party = [
|
|
|
103
102
|
"xarray"
|
|
104
103
|
]
|
|
105
104
|
|
|
105
|
+
[tool.ruff.format]
|
|
106
|
+
# Enable reformatting of code snippets in docstrings.
|
|
107
|
+
docstring-code-format = true
|
|
108
|
+
|
|
106
109
|
|
|
107
110
|
[tool.pytest]
|
|
108
111
|
python_files = "test_*.py"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.10.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|