Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates ndpyramid to use the newer version of Xarray that integrated Datatree. #152

Merged
merged 12 commits into from
Nov 22, 2024
2 changes: 1 addition & 1 deletion .github/workflows/codspeed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
conda install --solver=libmamba dask python=3.10 \
esmpy>=8.2.0 mpich netcdf4 numpy pip pooch pydantic>=1.10 pyproj \
pytest pytest-cov pytest-mypy rasterio rioxarray scipy sparse>=0.13.0 \
xarray xarray-datatree>=0.0.11 xesmf zarr cf_xarray>=0.8.0
xarray>=2024.10.0 xesmf zarr cf_xarray>=0.8.0
python -m pip install -U pytest-codspeed setuptools
python -m pip install -e . --no-deps

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.10", "3.11", "3.12"]
timeout-minutes: 20
defaults:
run:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pypi-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- uses: actions/setup-python@v5
name: Install Python
with:
python-version: 3.9
python-version: 3.10
norlandrhagen marked this conversation as resolved.
Show resolved Hide resolved

- name: Install dependencies
run: |
Expand Down Expand Up @@ -51,7 +51,7 @@ jobs:
- uses: actions/setup-python@v5
name: Install Python
with:
python-version: 3.9
python-version: 3.10
norlandrhagen marked this conversation as resolved.
Show resolved Hide resolved
- uses: actions/download-artifact@v4
with:
name: releases
Expand Down
5 changes: 2 additions & 3 deletions ci/doc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ channels:
- nodefaults
dependencies:
# Building docs
- python=3.10
- python=3.12
- pre-commit
- pip
- sphinx>=5.0
Expand All @@ -30,8 +30,7 @@ dependencies:
- s3fs
- scipy
- sparse>=0.13.0
- xarray
- xarray-datatree>=0.0.11
- xarray>=2024.10.0
- xesmf
- zarr
- cf_xarray>=0.8.0
Expand Down
4 changes: 2 additions & 2 deletions ci/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ channels:
- conda-forge
- nodefaults
dependencies:
- python=3.12
norlandrhagen marked this conversation as resolved.
Show resolved Hide resolved
- dask
- ipykernel
- jinja2
Expand All @@ -25,8 +26,7 @@ dependencies:
- s3fs
- scipy
- sparse>=0.13.0
- xarray
- xarray-datatree>=0.0.11
- xarray>=2024.10.0
- xesmf
- zarr
- cf_xarray>=0.8.0
Expand Down
40 changes: 16 additions & 24 deletions docs/examples/geotiff.ipynb

Large diffs are not rendered by default.

42 changes: 17 additions & 25 deletions docs/examples/pyramid-create.ipynb

Large diffs are not rendered by default.

51 changes: 24 additions & 27 deletions docs/examples/pyramid-regrid.ipynb

Large diffs are not rendered by default.

51 changes: 28 additions & 23 deletions docs/examples/pyramid-reproject.ipynb

Large diffs are not rendered by default.

52 changes: 25 additions & 27 deletions docs/examples/pyramid-resample.ipynb

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions ndpyramid/coarsen.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
from __future__ import annotations # noqa: F401

import datatree as dt
import xarray as xr

from .create import pyramid_create


def pyramid_coarsen(
ds: xr.Dataset, *, factors: list[int], dims: list[str], **kwargs
) -> dt.DataTree:
) -> xr.DataTree:
"""Create a multiscale pyramid via coarsening of a dataset by given factors

Parameters
Expand Down
5 changes: 2 additions & 3 deletions ndpyramid/create.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from __future__ import annotations # noqa: F401

from typing import Callable
from collections.abc import Callable

import datatree as dt
import xarray as xr

from .utils import get_version, multiscales_template
Expand Down Expand Up @@ -67,4 +66,4 @@ def pyramid_create(
plevels[str(key)] = func(ds, factor, dims, **kwargs)

plevels['/'] = xr.Dataset(attrs=attrs)
return dt.DataTree.from_dict(plevels)
return xr.DataTree.from_dict(plevels)
27 changes: 13 additions & 14 deletions ndpyramid/regrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import itertools
import typing

import datatree as dt
import numpy as np
import xarray as xr

Expand Down Expand Up @@ -123,7 +122,7 @@ def make_grid_pyramid(
levels: int = 6,
projection: typing.Literal['web-mercator', 'equidistant-cylindrical'] = 'web-mercator',
pixels_per_tile: int = 128,
) -> dt.DataTree:
) -> xr.DataTree:
"""helper function to create a grid pyramid for use with xesmf

Parameters
Expand All @@ -133,7 +132,7 @@ def make_grid_pyramid(

Returns
-------
pyramid : dt.DataTree
pyramid : xr.DataTree
Multiscale grid definition
"""
plevels = {
Expand All @@ -142,7 +141,7 @@ def make_grid_pyramid(
).chunk(-1)
for level in range(levels)
}
return dt.DataTree.from_dict(plevels)
return xr.DataTree.from_dict(plevels)


def generate_weights_pyramid(
Expand All @@ -151,7 +150,7 @@ def generate_weights_pyramid(
method: str = 'bilinear',
regridder_kws: dict = None,
projection: typing.Literal['web-mercator', 'equidistant-cylindrical'] = 'web-mercator',
) -> dt.DataTree:
) -> xr.DataTree:
"""helper function to generate weights for a multiscale regridder

Parameters
Expand All @@ -169,7 +168,7 @@ def generate_weights_pyramid(

Returns
-------
weights : dt.DataTree
weights : xr.DataTree
Multiscale weights
"""
import xesmf as xe
Expand All @@ -187,21 +186,21 @@ def generate_weights_pyramid(

root = xr.Dataset(attrs={'levels': levels, 'regrid_method': method})
plevels['/'] = root
return dt.DataTree.from_dict(plevels)
return xr.DataTree.from_dict(plevels)


def pyramid_regrid(
ds: xr.Dataset,
projection: typing.Literal['web-mercator', 'equidistant-cylindrical'] = 'web-mercator',
target_pyramid: dt.DataTree = None,
target_pyramid: xr.DataTree = None,
levels: int = None,
weights_pyramid: dt.DataTree = None,
weights_pyramid: xr.DataTree = None,
method: str = 'bilinear',
regridder_kws: dict = None,
regridder_apply_kws: dict = None,
other_chunks: dict = None,
pixels_per_tile: int = 128,
) -> dt.DataTree:
) -> xr.DataTree:
"""Make a pyramid using xesmf's regridders

Parameters
Expand All @@ -210,11 +209,11 @@ def pyramid_regrid(
Input dataset
projection : str, optional
Projection to use for the grid, by default 'web-mercator'
target_pyramid : dt.DataTree, optional
target_pyramid : xr.DataTree, optional
Target grids, if not provided, they will be generated, by default None
levels : int, optional
Number of levels in pyramid, by default None
weights_pyramid : dt.DataTree, optional
weights_pyramid : xr.DataTree, optional
pyramid containing pregenerated weights
method : str, optional
Regridding method. See :py:class:`~xesmf.Regridder` for valid options, by default 'bilinear'
Expand All @@ -230,7 +229,7 @@ def pyramid_regrid(

Returns
-------
pyramid : dt.DataTree
pyramid : xr.DataTree
Multiscale data pyramid
"""
import xesmf as xe
Expand Down Expand Up @@ -312,7 +311,7 @@ def pyramid_regrid(

root = xr.Dataset(attrs=attrs)
plevels['/'] = root
pyramid = dt.DataTree.from_dict(plevels)
pyramid = xr.DataTree.from_dict(plevels)

pyramid = add_metadata_and_zarr_encoding(
pyramid,
Expand Down
7 changes: 3 additions & 4 deletions ndpyramid/reproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from collections import defaultdict

import datatree as dt
import numpy as np
import xarray as xr
from rasterio.warp import Resampling
Expand Down Expand Up @@ -137,7 +136,7 @@ def pyramid_reproject(
resampling: str | dict = 'average',
extra_dim: str = None,
clear_attrs: bool = False,
) -> dt.DataTree:
) -> xr.DataTree:
"""Create a multiscale pyramid of a dataset via reprojection.

Parameters
Expand All @@ -163,7 +162,7 @@ def pyramid_reproject(

Returns
-------
dt.DataTree
xr.DataTree
The multiscale pyramid.

"""
Expand Down Expand Up @@ -208,7 +207,7 @@ def pyramid_reproject(

# create the final multiscale pyramid
plevels['/'] = xr.Dataset(attrs=attrs)
pyramid = dt.DataTree.from_dict(plevels)
pyramid = xr.DataTree.from_dict(plevels)

pyramid = add_metadata_and_zarr_encoding(
pyramid,
Expand Down
7 changes: 3 additions & 4 deletions ndpyramid/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import warnings
from collections import defaultdict

import datatree as dt
import numpy as np
import xarray as xr
from pyproj.crs import CRS
Expand Down Expand Up @@ -209,7 +208,7 @@ def pyramid_resample(
other_chunks: dict = None,
resampling: ResamplingOptions | dict = 'bilinear',
clear_attrs: bool = False,
) -> dt.DataTree:
) -> xr.DataTree:
"""Create a multiscale pyramid of a dataset via resampling.

Parameters
Expand Down Expand Up @@ -237,7 +236,7 @@ def pyramid_resample(

Returns
-------
dt.DataTree
xr.DataTree
The multiscale pyramid.

Warnings
Expand Down Expand Up @@ -280,7 +279,7 @@ def pyramid_resample(

# create the final multiscale pyramid
plevels['/'] = xr.Dataset(attrs=attrs)
pyramid = dt.DataTree.from_dict(plevels)
pyramid = xr.DataTree.from_dict(plevels)

projection_model = Projection(name=projection)

Expand Down
9 changes: 4 additions & 5 deletions ndpyramid/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import contextlib

import cf_xarray # noqa: F401
import datatree as dt
import numpy as np
import numpy.typing as npt
import xarray as xr
Expand Down Expand Up @@ -140,18 +139,18 @@ def set_zarr_encoding(


def add_metadata_and_zarr_encoding(
pyramid: dt.DataTree,
pyramid: xr.DataTree,
*,
levels: int,
other_chunks: dict = None,
pixels_per_tile: int = 128,
projection: Projection = None,
) -> dt.DataTree:
) -> xr.DataTree:
'''Postprocess data pyramid. Adds multiscales metadata and sets Zarr encoding

Parameters
----------
pyramid : dt.DataTree
pyramid : xr.DataTree
Input data pyramid
levels : int
Number of levels in pyramid
Expand All @@ -164,7 +163,7 @@ def add_metadata_and_zarr_encoding(

Returns
-------
dt.DataTree
xr.DataTree
Updated data pyramid with metadata / encoding set

Notes
Expand Down
13 changes: 7 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,26 @@ description = "A small utility for generating ND array pyramids using Xarray and
readme = "README.md"
license = { text = "MIT" }
authors = [{ name = "CarbonPlan", email = "[email protected]" }]
requires-python = ">=3.9"
requires-python = ">=3.10"
classifiers = [
"Development Status :: 4 - Beta",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Intended Audience :: Science/Research",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",

"Topic :: Scientific/Engineering",
]
dynamic = ["version"]


dependencies = [
"cf_xarray>=0.8.0",
"xarray-datatree>=0.0.11",
"xarray[complete]>=2024.10.0",
"zarr",
"pydantic>=1.10",
"pyproj",
Expand All @@ -37,7 +39,6 @@ dependencies = [
[project.optional-dependencies]
complete = [
"ndpyramid[dask,jupyter,xesmf]",
"xarray[complete]",
"mercantile",
"cftime",
"scipy",
Expand Down Expand Up @@ -86,13 +87,13 @@ write_to_template = '__version__ = "{version}"'

[tool.black]
line-length = 100
target-version = ['py39']
target-version = ['py312']
norlandrhagen marked this conversation as resolved.
Show resolved Hide resolved
skip-string-normalization = true


[tool.ruff]
line-length = 100
target-version = "py39"
target-version = "py312"
norlandrhagen marked this conversation as resolved.
Show resolved Hide resolved
builtins = ["ellipsis"]
# Exclude a variety of commonly ignored directories.
exclude = [
Expand Down
Loading