Skip to content

Commit

Permalink
remove cdms2 (#8441)
Browse files Browse the repository at this point in the history
* remove `cdms2` from all environments

* remove any code related to `cdms2`

* remove the `mypy` override for `cdms2`

* remove the special environment files for python 3.11

* whats-new

* more info on the replacement

* remove the `cdms2` methods from the api docs

* remove all mentions of UV-CDAT / cdms2 from the faq

* also change the binder environment
  • Loading branch information
keewis authored Nov 14, 2023
1 parent 49bd63a commit 28053ba
Show file tree
Hide file tree
Showing 15 changed files with 8 additions and 359 deletions.
4 changes: 1 addition & 3 deletions .binder/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ dependencies:
- boto3
- bottleneck
- cartopy
- cdms2
- cfgrib
- cftime
- coveralls
Expand Down Expand Up @@ -38,5 +37,4 @@ dependencies:
- toolz
- xarray
- zarr
- pip:
- numbagg
- numbagg
8 changes: 1 addition & 7 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,7 @@ jobs:
run: |
echo "TODAY=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
if [[ "${{matrix.python-version}}" == "3.11" ]]; then
if [[ ${{matrix.os}} == windows* ]]; then
echo "CONDA_ENV_FILE=ci/requirements/environment-windows-py311.yml" >> $GITHUB_ENV
else
echo "CONDA_ENV_FILE=ci/requirements/environment-py311.yml" >> $GITHUB_ENV
fi
elif [[ ${{ matrix.os }} == windows* ]] ;
if [[ ${{ matrix.os }} == windows* ]] ;
then
echo "CONDA_ENV_FILE=ci/requirements/environment-windows.yml" >> $GITHUB_ENV
elif [[ "${{ matrix.env }}" != "" ]] ;
Expand Down
2 changes: 0 additions & 2 deletions ci/requirements/all-but-dask.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ channels:
- conda-forge
- nodefaults
dependencies:
- python=3.10
- black
- aiobotocore
- boto3
- bottleneck
- cartopy
- cdms2
- cftime
- coveralls
- flox
Expand Down
47 changes: 0 additions & 47 deletions ci/requirements/environment-py311.yml

This file was deleted.

43 changes: 0 additions & 43 deletions ci/requirements/environment-windows-py311.yml

This file was deleted.

1 change: 0 additions & 1 deletion ci/requirements/environment-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ dependencies:
- boto3
- bottleneck
- cartopy
# - cdms2 # Not available on Windows
- cftime
- dask-core
- distributed
Expand Down
1 change: 0 additions & 1 deletion ci/requirements/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ dependencies:
- boto3
- bottleneck
- cartopy
- cdms2
- cftime
- dask-core
- distributed
Expand Down
1 change: 0 additions & 1 deletion ci/requirements/min-all-deps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ dependencies:
- boto3=1.24
- bottleneck=1.3
- cartopy=0.20
- cdms2=3.1
- cftime=1.6
- coveralls
- dask-core=2022.7
Expand Down
2 changes: 0 additions & 2 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -628,11 +628,9 @@ DataArray methods
load_dataarray
open_dataarray
DataArray.as_numpy
DataArray.from_cdms2
DataArray.from_dict
DataArray.from_iris
DataArray.from_series
DataArray.to_cdms2
DataArray.to_dask_dataframe
DataArray.to_dataframe
DataArray.to_dataset
Expand Down
13 changes: 3 additions & 10 deletions doc/getting-started-guide/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -168,18 +168,11 @@ integration with Cartopy_.
.. _Iris: https://scitools-iris.readthedocs.io/en/stable/
.. _Cartopy: https://scitools.org.uk/cartopy/docs/latest/

`UV-CDAT`__ is another Python library that implements in-memory netCDF-like
variables and `tools for working with climate data`__.

__ https://uvcdat.llnl.gov/
__ https://drclimate.wordpress.com/2014/01/02/a-beginners-guide-to-scripting-with-uv-cdat/

We think the design decisions we have made for xarray (namely, basing it on
pandas) make it a faster and more flexible data analysis tool. That said, Iris
and CDAT have some great domain specific functionality, and xarray includes
methods for converting back and forth between xarray and these libraries. See
:py:meth:`~xarray.DataArray.to_iris` and :py:meth:`~xarray.DataArray.to_cdms2`
for more details.
has some great domain specific functionality, and xarray includes
methods for converting back and forth between xarray and Iris. See
:py:meth:`~xarray.DataArray.to_iris` for more details.

What other projects leverage xarray?
------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ New Features

Breaking changes
~~~~~~~~~~~~~~~~
- drop support for `cdms2 <https://github.com/CDAT/cdms>`_. Please use
`xcdat <https://github.com/xCDAT/xcdat>`_ instead (:pull:`8441`).
By `Justus Magin <https://github.com/keewis`_.

- Bump minimum tested pint version to ``>=0.22``. By `Deepak Cherian <https://github.com/dcherian>`_.

Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ module = [
"affine.*",
"bottleneck.*",
"cartopy.*",
"cdms2.*",
"cf_units.*",
"cfgrib.*",
"cftime.*",
Expand Down
88 changes: 0 additions & 88 deletions xarray/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from collections import Counter

import numpy as np
import pandas as pd

from xarray.coding.times import CFDatetimeCoder, CFTimedeltaCoder
from xarray.conventions import decode_cf
Expand All @@ -12,7 +11,6 @@
from xarray.core.dtypes import get_fill_value
from xarray.core.pycompat import array_type

cdms2_ignored_attrs = {"name", "tileIndex"}
iris_forbidden_keys = {
"standard_name",
"long_name",
Expand Down Expand Up @@ -60,92 +58,6 @@ def _filter_attrs(attrs, ignored_attrs):
return {k: v for k, v in attrs.items() if k not in ignored_attrs}


def from_cdms2(variable):
"""Convert a cdms2 variable into an DataArray"""
values = np.asarray(variable)
name = variable.id
dims = variable.getAxisIds()
coords = {}
for axis in variable.getAxisList():
coords[axis.id] = DataArray(
np.asarray(axis),
dims=[axis.id],
attrs=_filter_attrs(axis.attributes, cdms2_ignored_attrs),
)
grid = variable.getGrid()
if grid is not None:
ids = [a.id for a in grid.getAxisList()]
for axis in grid.getLongitude(), grid.getLatitude():
if axis.id not in variable.getAxisIds():
coords[axis.id] = DataArray(
np.asarray(axis[:]),
dims=ids,
attrs=_filter_attrs(axis.attributes, cdms2_ignored_attrs),
)
attrs = _filter_attrs(variable.attributes, cdms2_ignored_attrs)
dataarray = DataArray(values, dims=dims, coords=coords, name=name, attrs=attrs)
return decode_cf(dataarray.to_dataset())[dataarray.name]


def to_cdms2(dataarray, copy=True):
"""Convert a DataArray into a cdms2 variable"""
# we don't want cdms2 to be a hard dependency
import cdms2

def set_cdms2_attrs(var, attrs):
for k, v in attrs.items():
setattr(var, k, v)

# 1D axes
axes = []
for dim in dataarray.dims:
coord = encode(dataarray.coords[dim])
axis = cdms2.createAxis(coord.values, id=dim)
set_cdms2_attrs(axis, coord.attrs)
axes.append(axis)

# Data
var = encode(dataarray)
cdms2_var = cdms2.createVariable(
var.values, axes=axes, id=dataarray.name, mask=pd.isnull(var.values), copy=copy
)

# Attributes
set_cdms2_attrs(cdms2_var, var.attrs)

# Curvilinear and unstructured grids
if dataarray.name not in dataarray.coords:
cdms2_axes = {}
for coord_name in set(dataarray.coords.keys()) - set(dataarray.dims):
coord_array = dataarray.coords[coord_name].to_cdms2()

cdms2_axis_cls = (
cdms2.coord.TransientAxis2D
if coord_array.ndim
else cdms2.auxcoord.TransientAuxAxis1D
)
cdms2_axis = cdms2_axis_cls(coord_array)
if cdms2_axis.isLongitude():
cdms2_axes["lon"] = cdms2_axis
elif cdms2_axis.isLatitude():
cdms2_axes["lat"] = cdms2_axis

if "lon" in cdms2_axes and "lat" in cdms2_axes:
if len(cdms2_axes["lon"].shape) == 2:
cdms2_grid = cdms2.hgrid.TransientCurveGrid(
cdms2_axes["lat"], cdms2_axes["lon"]
)
else:
cdms2_grid = cdms2.gengrid.AbstractGenericGrid(
cdms2_axes["lat"], cdms2_axes["lon"]
)
for axis in cdms2_grid.getAxisList():
cdms2_var.setAxis(cdms2_var.getAxisIds().index(axis.id), axis)
cdms2_var.setGrid(cdms2_grid)

return cdms2_var


def _pick_attrs(attrs, keys):
"""Return attrs with keys in keys list"""
return {k: v for k, v in attrs.items() if k in keys}
Expand Down
46 changes: 0 additions & 46 deletions xarray/core/dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
ReprObject,
_default,
either_dict_or_kwargs,
emit_user_level_warning,
)
from xarray.core.variable import (
IndexVariable,
Expand All @@ -81,10 +80,6 @@
from dask.delayed import Delayed
except ImportError:
Delayed = None # type: ignore
try:
from cdms2 import Variable as cdms2_Variable
except ImportError:
cdms2_Variable = None
try:
from iris.cube import Cube as iris_Cube
except ImportError:
Expand Down Expand Up @@ -4402,47 +4397,6 @@ def from_series(cls, series: pd.Series, sparse: bool = False) -> DataArray:
result.name = series.name
return result

def to_cdms2(self) -> cdms2_Variable:
"""Convert this array into a cdms2.Variable
.. deprecated:: 2023.06.0
The `cdms2`_ library has been deprecated. Please consider using the
`xcdat`_ library instead.
.. _cdms2: https://github.com/CDAT/cdms
.. _xcdat: https://github.com/xCDAT/xcdat
"""
from xarray.convert import to_cdms2

emit_user_level_warning(
"The cdms2 library has been deprecated."
" Please consider using the xcdat library instead.",
DeprecationWarning,
)

return to_cdms2(self)

@classmethod
def from_cdms2(cls, variable: cdms2_Variable) -> Self:
"""Convert a cdms2.Variable into an xarray.DataArray
.. deprecated:: 2023.06.0
The `cdms2`_ library has been deprecated. Please consider using the
`xcdat`_ library instead.
.. _cdms2: https://github.com/CDAT/cdms
.. _xcdat: https://github.com/xCDAT/xcdat
"""
from xarray.convert import from_cdms2

emit_user_level_warning(
"The cdms2 library has been deprecated."
" Please consider using the xcdat library instead.",
DeprecationWarning,
)

return from_cdms2(variable)

def to_iris(self) -> iris_Cube:
"""Convert this array into a iris.cube.Cube"""
from xarray.convert import to_iris
Expand Down
Loading

0 comments on commit 28053ba

Please sign in to comment.