Skip to content
4 changes: 3 additions & 1 deletion docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Release notes

## 0.2.5
- Fix numpy 2.4 and obspy 1.4.2 incompatibilities (@atrabatto).
- Add SampleCoordinate for more SEED-like coordinates (@atrabattoni).
- Add `create_dirs` to `.to_netcdf` methods to create intermediate directories (@aurelienfalco).
- Fix numpy 2.4 and obspy 1.4.2 incompatibilities (@atrabatto).


## 0.2.4
- Add StreamWriter to write long time series to miniSEED (@marbail).
Expand Down
10 changes: 10 additions & 0 deletions tests/test_dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,16 @@ def test_io_attrs(self):
assert result.attrs == attrs
assert result.equals(da)

def test_io_create_dirs(self):
da = xd.DataArray(np.arange(3))
with TemporaryDirectory() as dirpath:
path = os.path.join(dirpath, "subdir", "tmp.nc")
with pytest.raises(FileNotFoundError, match="No such file or directory"):
da.to_netcdf(path)
da.to_netcdf(path, create_dirs=True)
result = xd.DataArray.from_netcdf(path)
assert result.equals(da)

def test_ufunc(self):
da = wavelet_wavefronts()
result = np.add(da, 1)
Expand Down
17 changes: 17 additions & 0 deletions tests/test_datacollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,23 @@ def test_io(self):
result = xd.open_datacollection(path)
assert result.equals(dc)

def test_io_create_dirs(self):
da = wavelet_wavefronts()
dc = xd.DataCollection(
{
"das1": da,
"das2": da,
},
"instrument",
)
with TemporaryDirectory() as dirpath:
path = os.path.join(dirpath, "subdir", "tmp.nc")
with pytest.raises(FileNotFoundError, match="No such file or directory"):
dc.to_netcdf(path)
dc.to_netcdf(path, create_dirs=True)
result = xd.DataCollection.from_netcdf(path)
assert result.equals(dc)

def test_depth_counter(self):
da = wavelet_wavefronts()
da.name = "da"
Expand Down
19 changes: 18 additions & 1 deletion xdas/core/dataarray.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import os
import warnings
from functools import partial

Expand Down Expand Up @@ -825,7 +826,15 @@ def from_stream(cls, st, dims=("channel", "time")):
}
return cls(data, {dims[0]: channel, dims[1]: time})

def to_netcdf(self, fname, mode="w", group=None, virtual=None, encoding=None):
def to_netcdf(
self,
fname,
mode="w",
group=None,
virtual=None,
encoding=None,
create_dirs=False,
):
"""
Write DataArray contents to a netCDF file.

Expand All @@ -849,6 +858,8 @@ def to_netcdf(self, fname, mode="w", group=None, virtual=None, encoding=None):
the `h5netcdf` engine to write the data. If you want to use a specific plugin
for compression, you can use the `hdf5plugin` package. For example, to use the
ZFP compression, you can use the `hdf5plugin.Zfp` class.
create_dirs : bool, optional
Whether to create parent directories if they do not exist. Default is False.

Examples
--------
Expand Down Expand Up @@ -883,6 +894,12 @@ def to_netcdf(self, fname, mode="w", group=None, virtual=None, encoding=None):
for coord in self.coords.values():
dataset, variable_attrs = coord.to_dataset(dataset, variable_attrs)

# create parent directories if needed
if create_dirs:
dirname = os.path.dirname(fname)
if dirname:
os.makedirs(dirname, exist_ok=True)

# write data
with h5netcdf.File(fname, mode=mode) as file:
# group
Expand Down
31 changes: 28 additions & 3 deletions xdas/core/datacollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,26 @@ def fields(self):
)
return uniquifiy(out)

def to_netcdf(self, fname, mode="w", group=None, virtual=None, encoding=None):
def to_netcdf(
self,
fname,
mode="w",
group=None,
virtual=None,
encoding=None,
create_dirs=False,
):
if mode == "w" and group is None and os.path.exists(fname):
os.remove(fname)
for key in self:
name = self.name if self.name is not None else "collection"
location = "/".join([name, str(key)])
if group is not None:
location = "/".join([group, location])
if create_dirs:
dirname = os.path.dirname(fname)
if dirname:
os.makedirs(dirname, exist_ok=True)
self[key].to_netcdf(
fname,
mode="a",
Expand Down Expand Up @@ -441,9 +453,22 @@ def to_mapping(self):
def from_mapping(cls, data):
return cls(data.values(), data.name)

def to_netcdf(self, fname, mode="w", group=None, virtual=None, encoding=None):
def to_netcdf(
self,
fname,
mode="w",
group=None,
virtual=None,
encoding=None,
create_dirs=False,
):
self.to_mapping().to_netcdf(
fname, mode=mode, group=group, virtual=virtual, encoding=encoding
fname,
mode=mode,
group=group,
virtual=virtual,
encoding=encoding,
create_dirs=create_dirs,
)

@classmethod
Expand Down