Skip to content

Commit bd7a3f0

Browse files
committed
Global metadata attributes of target dataset is no longer empty
1 parent 87dbd97 commit bd7a3f0

File tree

4 files changed

+83
-14
lines changed

4 files changed

+83
-14
lines changed

CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## Version 0.4.1 (in development)
22

3+
### Fixes
4+
5+
* Global metadata attributes of target dataset is no longer empty. [#56]
6+
37
## Version 0.4.0 (from 2024-02-08)
48

59
### Enhancements

tests/helpers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ def make_test_dataset(
108108
np.linspace(0, 1, shape[2], dtype="float64"), dims=dims[2]
109109
),
110110
},
111+
attrs={
112+
"Conventions": "CF-1.8",
113+
"title": f"Test {index + 1}-{index + shape[0]}",
114+
},
111115
)
112116

113117
if crs:

tests/test_api.py

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,37 @@ def test_no_slices(self):
2626
zappend([], target_dir=target_dir)
2727
self.assertFalse(FileObj(target_dir).exists())
2828

29+
def test_one_slices_memory(self):
30+
target_dir = "memory://target.zarr"
31+
slices = [make_test_dataset()]
32+
zappend(slices, target_dir=target_dir)
33+
ds = xr.open_zarr(target_dir)
34+
self.assertEqual({"time": 3, "y": 50, "x": 100}, ds.sizes)
35+
self.assertEqual({"chl", "tsm"}, set(ds.data_vars))
36+
self.assertEqual({"time", "y", "x"}, set(ds.coords))
37+
self.assertEqual(
38+
{
39+
"Conventions": "CF-1.8",
40+
"title": "Test 1-3",
41+
},
42+
ds.attrs,
43+
)
44+
2945
def test_some_slices_memory(self):
3046
target_dir = "memory://target.zarr"
31-
slices = [make_test_dataset(), make_test_dataset(), make_test_dataset()]
47+
slices = [make_test_dataset(index=3 * i) for i in range(3)]
3248
zappend(slices, target_dir=target_dir)
3349
ds = xr.open_zarr(target_dir)
3450
self.assertEqual({"time": 9, "y": 50, "x": 100}, ds.sizes)
3551
self.assertEqual({"chl", "tsm"}, set(ds.data_vars))
3652
self.assertEqual({"time", "y", "x"}, set(ds.coords))
53+
self.assertEqual(
54+
{
55+
"Conventions": "CF-1.8",
56+
"title": "Test 1-3",
57+
},
58+
ds.attrs,
59+
)
3760

3861
def test_some_slices_local(self):
3962
target_dir = "target.zarr"
@@ -42,67 +65,96 @@ def test_some_slices_local(self):
4265
"slice-2.zarr",
4366
"slice-3.zarr",
4467
]
45-
for uri in slices:
46-
make_test_dataset(uri=uri)
68+
for index, uri in enumerate(slices):
69+
make_test_dataset(uri=uri, index=3 * index)
4770
try:
4871
zappend(slices, target_dir=target_dir)
4972
ds = xr.open_zarr(target_dir)
5073
self.assertEqual({"time": 9, "y": 50, "x": 100}, ds.sizes)
5174
self.assertEqual({"chl", "tsm"}, set(ds.data_vars))
5275
self.assertEqual({"time", "y", "x"}, set(ds.coords))
76+
self.assertEqual(
77+
{
78+
"Conventions": "CF-1.8",
79+
"title": "Test 1-3",
80+
},
81+
ds.attrs,
82+
)
5383
finally:
5484
shutil.rmtree(target_dir, ignore_errors=True)
5585
for slice_dir in slices:
5686
shutil.rmtree(slice_dir, ignore_errors=True)
5787

5888
def test_some_slices_with_class_slice_source(self):
5989
target_dir = "memory://target.zarr"
60-
slices = [make_test_dataset(), make_test_dataset(), make_test_dataset()]
90+
slices = [make_test_dataset(index=3 * i) for i in range(3)]
6191
zappend(slices, target_dir=target_dir, slice_source=MySliceSource)
6292
ds = xr.open_zarr(target_dir)
6393
self.assertEqual({"time": 9, "y": 50, "x": 100}, ds.sizes)
6494
self.assertEqual({"chl"}, set(ds.data_vars))
6595
self.assertEqual({"time", "y", "x"}, set(ds.coords))
96+
self.assertEqual(
97+
{
98+
"Conventions": "CF-1.8",
99+
"title": "Test 1-3",
100+
},
101+
ds.attrs,
102+
)
66103

67104
def test_some_slices_with_func_slice_source(self):
68105
def process_slice(ctx, slice_ds: xr.Dataset) -> SliceSource:
69106
return MySliceSource(ctx, slice_ds)
70107

71108
target_dir = "memory://target.zarr"
72-
slices = [make_test_dataset(), make_test_dataset(), make_test_dataset()]
109+
slices = [make_test_dataset(index=3 * i) for i in range(3)]
73110
zappend(slices, target_dir=target_dir, slice_source=process_slice)
74111
ds = xr.open_zarr(target_dir)
75112
self.assertEqual({"time": 9, "y": 50, "x": 100}, ds.sizes)
76113
self.assertEqual({"chl"}, set(ds.data_vars))
77114
self.assertEqual({"time", "y", "x"}, set(ds.coords))
115+
self.assertEqual(
116+
{
117+
"Conventions": "CF-1.8",
118+
"title": "Test 1-3",
119+
},
120+
ds.attrs,
121+
)
78122

79123
def test_some_slices_with_inc_append_step(self):
80124
target_dir = "memory://target.zarr"
81-
slices = [
82-
make_test_dataset(index=0, shape=(1, 50, 100)),
83-
make_test_dataset(index=1, shape=(1, 50, 100)),
84-
make_test_dataset(index=2, shape=(1, 50, 100)),
85-
]
125+
slices = [make_test_dataset(index=i, shape=(1, 50, 100)) for i in range(3)]
86126
zappend(slices, target_dir=target_dir, append_step="1D")
87127
ds = xr.open_zarr(target_dir)
88128
np.testing.assert_array_equal(
89129
ds.time.values,
90130
np.array(["2024-01-01", "2024-01-02", "2024-01-03"], dtype=np.datetime64),
91131
)
132+
self.assertEqual(
133+
{
134+
"Conventions": "CF-1.8",
135+
"title": "Test 1-1",
136+
},
137+
ds.attrs,
138+
)
92139

93140
def test_some_slices_with_dec_append_step(self):
94141
target_dir = "memory://target.zarr"
95142
slices = [
96-
make_test_dataset(index=2, shape=(1, 50, 100)),
97-
make_test_dataset(index=1, shape=(1, 50, 100)),
98-
make_test_dataset(index=0, shape=(1, 50, 100)),
143+
make_test_dataset(index=i, shape=(1, 50, 100)) for i in reversed(range(3))
99144
]
100145
zappend(slices, target_dir=target_dir, append_step="-1D")
101146
ds = xr.open_zarr(target_dir)
102147
np.testing.assert_array_equal(
103148
ds.time.values,
104149
np.array(["2024-01-03", "2024-01-02", "2024-01-01"], dtype=np.datetime64),
105150
)
151+
self.assertEqual(
152+
{
153+
"Conventions": "CF-1.8",
154+
"title": "Test 3-3",
155+
},
156+
ds.attrs,
157+
)
106158

107159
# # See https://github.com/bcdev/zappend/issues/21
108160
#

zappend/tailoring.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,18 @@ def tailor_slice_dataset(
4040
# as dimension, e.g., "x", "y", "crs", ...
4141
dataset = dataset.drop_vars(const_variables)
4242

43+
# https://github.com/bcdev/zappend/issues/56
44+
# slice_dataset.to_zarr(store, mode="a", ...) will replace
45+
# global attributes.
46+
# Therefore, we must replace slice dataset attributes by
47+
# existing target dataset attributes.
48+
# However, users should be able to select the appropriate
49+
# operation, e.g., a new config setting target_attrs_op with
50+
# values "first" (default), "last", "update".
51+
dataset.attrs = target_metadata.attrs
52+
4353
# Remove any encoding and attributes from slice,
4454
# since both are prescribed by target
45-
dataset.attrs.clear()
4655
for variable in dataset.variables.values():
4756
variable.encoding = {}
4857
variable.attrs = {}

0 commit comments

Comments
 (0)