Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions src/earthkit/data/data/netcdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,32 @@ def to_xarray(self, *args, xarray_open_mfdataset_kwargs=None, **kwargs):

Parameters
----------
*args
Positional arguments to pass to the reader's to_xarray method.
Not used currently. It is there to allow for future extensions or
additional parameters that may be needed for specific use cases.
xarray_open_mfdataset_kwargs: dict, None, optional
Keyword arguments passed to :py:func:`xarray.open_mfdataset`.
Can only be used when converting multiple NetCDF files into a single
Xarray dataset. When specified, this argument takes precedence over
any other keyword arguments passed to the method.
**kwargs
Keyword arguments passed to :py:func:`xarray.open_mfdataset`
``xarray_open_mfdataset_kwargs`` is not set.
Keyword arguments passed to :py:func:`xarray.open_dataset` for
single file conversion or to :py:func:`xarray.open_mfdataset` for
multiple file conversion. Ignored if `xarray_open_mfdataset_kwargs`
is specified.

Returns
-------
:py:class:`xarray.Dataset`
An Xarray dataset containing the NetCDF data.
"""
return self._reader.to_xarray(*args, **kwargs)
if xarray_open_mfdataset_kwargs:
options = dict(xarray_open_mfdataset_kwargs=xarray_open_mfdataset_kwargs)
else:
options = dict()

return self._reader.to_xarray(*args, **options, **kwargs)

def to_pandas(self, *args, **kwargs):
"""Convert into a Pandas DataFrame.
Expand Down
22 changes: 13 additions & 9 deletions src/earthkit/data/readers/netcdf/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ def to_pandas(self):

def to_xarray(self, **kwargs):
return type(self).to_xarray_single_from_path(self.path, **kwargs)
# if isinstance(self.path, str):
# return type(self).to_xarray_single_from_path(self.path, **kwargs)

# return NetCDFReader.to_xarray_multi_from_paths([self.path], **kwargs)

# return type(self).to_xarray_multi_from_paths([self.path], **kwargs)

@classmethod
def to_xarray_multi_from_paths(cls, paths, **kwargs):
Expand All @@ -54,8 +48,13 @@ def to_xarray_multi_from_paths(cls, paths, **kwargs):
if not isinstance(paths, list):
paths = [paths]

kwargs = kwargs.copy() # Make a copy to avoid modifying the original dictionary
xarray_open_mfdataset_kwargs = kwargs.pop("xarray_open_mfdataset_kwargs", None)

options = dict()
options.update(kwargs.get("xarray_open_mfdataset_kwargs", {}))
if xarray_open_mfdataset_kwargs is not None:
options = dict(xarray_open_mfdataset_kwargs)

if not options:
options = dict(**kwargs)

Expand All @@ -71,11 +70,16 @@ def to_xarray_single_from_path(cls, path, **kwargs):
if not isinstance(path, str):
raise ValueError("path must be a string")

if "xarray_open_mfdataset_kwargs" in kwargs:
kwargs = kwargs.copy() # Make a copy to avoid modifying the original dictionary
xarray_open_dataset_kwargs = kwargs.pop("xarray_open_dataset_kwargs", None)
xarray_open_mfdataset_kwargs = kwargs.pop("xarray_open_mfdataset_kwargs", None)
if xarray_open_mfdataset_kwargs:
raise ValueError("xarray_open_mfdataset_kwargs is not supported for single file")

options = dict()
options.update(kwargs.get("xarray_open_dataset_kwargs", {}))
if xarray_open_dataset_kwargs is not None:
options = dict(xarray_open_dataset_kwargs)

if not options:
options = dict(**kwargs)

Expand Down
85 changes: 83 additions & 2 deletions tests/netcdf/test_netcdf_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
# nor does it submit to any jurisdiction.
#


import numpy as np
import pytest

from earthkit.data import from_source
from earthkit.data.utils.testing import earthkit_remote_test_data_file
from earthkit.data.utils.testing import earthkit_remote_test_data_file, earthkit_test_data_file


@pytest.mark.long_test
@pytest.mark.download
def test_netcdf_to_xarray_args():
def test_netcdf_fieldlist_to_xarray_args():
# The JD variable in the NetCDF is defined as follows:
#
# short JD(time, lat, lon) ;
Expand Down Expand Up @@ -55,6 +56,86 @@ def test_netcdf_to_xarray_args():
r["JD"].shape == (1, 20880, 28440)


@pytest.mark.long_test
@pytest.mark.download
def test_netcdf_single_to_xarray_args():
# The JD variable in the NetCDF is defined as follows:
#
# short JD(time, lat, lon) ;
# string JD:long_name = "Date of the first detection" ;
# string JD:units = "days since 2022-01-01" ;
# string JD:comment = "Possible values: 0 when the pixel is not burned; 1 to 366 day of
# the first detection when the pixel is burned; -1 when the pixel is not observed
# in the month; -2 when pixel is not burnable: water bodies, bare areas, urban areas,
# and permanent snow and ice.
#
# when loaded with xarray.open_dataset/xarray.open_mdataset without any kwargs the
# type of the JD variable is datetime64[ns], which is wrong. The correct type should
# be int16.

ds = from_source(
"url",
earthkit_remote_test_data_file("20220401-C3S-L3S_FIRE-BA-OLCI-AREA_3-fv1.1.nc"),
)

r = ds.to_xarray(decode_cf=False, decode_times=False)
assert r["JD"].dtype == "int16"
r["JD"].shape == (1, 20880, 28440)
assert np.isclose(r["JD"].values.min(), -2)
assert np.isclose(r["JD"].values.max(), 120)

r = ds.to_xarray(decode_cf=False, decode_times=False)
assert r["JD"].dtype == "int16"
r["JD"].shape == (1, 20880, 28440)
assert np.isclose(r["JD"].values.min(), -2)
assert np.isclose(r["JD"].values.max(), 120)

r = ds.to_xarray()
assert r["JD"].dtype == "<M8[ns]"
r["JD"].shape == (1, 20880, 28440)


def test_netcdf_single_to_xarray_1():
d = from_source(
"file",
earthkit_test_data_file("era5_2t_1.nc"),
)

r = d.to_xarray(xarray_open_dataset_kwargs=dict(decode_cf=False, decode_times=False))
assert r["t2m"].shape == (1, 9, 18)

r = d.to_xarray(decode_cf=False, decode_times=False)
assert r["t2m"].shape == (1, 9, 18)

with pytest.raises(TypeError):
d.to_xarray(decode_cf=False, decode_times=False, wrong_kwarg=True)

with pytest.raises(ValueError):
d.to_xarray(xarray_open_mfdataset_kwargs=dict(decode_cf=False, decode_times=False))


def test_netcdf_multi_to_xarray_1():
d = from_source(
"file",
[
earthkit_test_data_file("era5_2t_1.nc"),
earthkit_test_data_file("era5_2t_2.nc"),
],
)

r = d.to_xarray(xarray_open_mfdataset_kwargs=dict(decode_cf=False, decode_times=False))
assert r["t2m"].shape == (2, 9, 18)

with pytest.raises(TypeError):
d.to_xarray(xarray_open_dataset_kwargs=dict(decode_cf=False, decode_times=False))

r = d.to_xarray(decode_cf=False, decode_times=False)
assert r["t2m"].shape == (2, 9, 18)

with pytest.raises(TypeError):
d.to_xarray(decode_cf=False, decode_times=False, wrong_kwarg=True)


if __name__ == "__main__":
from earthkit.data.utils.testing import main

Expand Down
Loading