Skip to content

Commit 4c3c332

Browse files
author
Joe Hamman
authored
Add unlim dims for h5netcdf (#1637)
* initial commit adding unlim dims for h5netcdf * h5netcdf unlimited dimension now roundtrips
1 parent 2949558 commit 4c3c332

File tree

6 files changed

+33
-22
lines changed

6 files changed

+33
-22
lines changed

doc/whats-new.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ Enhancements
186186
functions on data stored as dask arrays (:issue:`1279`).
187187
By `Joe Hamman <https://github.com/jhamman>`_.
188188

189+
- Support reading and writing unlimited dimensions with h5netcdf (:issue:`1636`).
190+
By `Joe Hamman <https://github.com/jhamman>`_.
191+
189192
Bug fixes
190193
~~~~~~~~~
191194

@@ -260,7 +263,7 @@ Bug fixes
260263
The previous behavior unintentionally causing additional tests to be skipped
261264
(:issue:`1531`). By `Joe Hamman <https://github.com/jhamman>`_.
262265

263-
- Fix pynio backend for upcoming release of pynio with python3 support
266+
- Fix pynio backend for upcoming release of pynio with python3 support
264267
(:issue:`1611`). By `Ben Hillman <https://github/brhillman>`_.
265268

266269
.. _whats-new.0.9.6:

xarray/backends/common.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,8 @@ def set_necessary_dimensions(self, variable, unlimited_dims=None):
232232
unlimited_dims = set()
233233
for d, l in zip(variable.dims, variable.shape):
234234
if d not in self.dimensions:
235-
if d in unlimited_dims:
236-
l = None
237-
self.set_dimension(d, l)
235+
is_unlimited = d in unlimited_dims
236+
self.set_dimension(d, l, is_unlimited)
238237

239238

240239
class WritableCFDataStore(AbstractWritableDataStore):

xarray/backends/h5netcdf_.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from __future__ import division
33
from __future__ import print_function
44
import functools
5-
import warnings
65

76
from .. import Variable
87
from ..core import indexing
@@ -106,9 +105,20 @@ def get_dimensions(self):
106105
with self.ensure_open(autoclose=True):
107106
return self.ds.dimensions
108107

109-
def set_dimension(self, name, length):
108+
def get_encoding(self):
109+
with self.ensure_open(autoclose=True):
110+
encoding = {}
111+
encoding['unlimited_dims'] = {
112+
k for k, v in self.ds.dimensions.items() if v is None}
113+
return encoding
114+
115+
def set_dimension(self, name, length, is_unlimited=False):
110116
with self.ensure_open(autoclose=False):
111-
self.ds.createDimension(name, size=length)
117+
if is_unlimited:
118+
self.ds.createDimension(name, size=None)
119+
self.ds.resize_dimension(name, length)
120+
else:
121+
self.ds.createDimension(name, size=length)
112122

113123
def set_attribute(self, key, value):
114124
with self.ensure_open(autoclose=False):
@@ -123,10 +133,6 @@ def prepare_variable(self, name, variable, check_encoding=False,
123133
if dtype is str:
124134
dtype = h5py.special_dtype(vlen=unicode_type)
125135

126-
if unlimited_dims is not None:
127-
warnings.warn('h5netcdf does not support unlimited dimensions, '
128-
'got: %s.' % unlimited_dims)
129-
unlimited_dims = None
130136
self.set_necessary_dimensions(variable, unlimited_dims=unlimited_dims)
131137

132138
fill_value = attrs.pop('_FillValue', None)
@@ -141,7 +147,6 @@ def prepare_variable(self, name, variable, check_encoding=False,
141147
'chunksizes', 'fletcher32']:
142148
if key in encoding:
143149
kwargs[key] = encoding[key]
144-
145150
nc4_var = self.ds.createVariable(name, dtype, variable.dims,
146151
fill_value=fill_value, **kwargs)
147152

xarray/backends/netCDF4_.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,10 @@ def get_encoding(self):
294294
k for k, v in self.ds.dimensions.items() if v.isunlimited()}
295295
return encoding
296296

297-
def set_dimension(self, name, length):
297+
def set_dimension(self, name, length, is_unlimited=False):
298298
with self.ensure_open(autoclose=False):
299-
self.ds.createDimension(name, size=length)
299+
dim_length = length if not is_unlimited else None
300+
self.ds.createDimension(name, size=dim_length)
300301

301302
def set_attribute(self, key, value):
302303
with self.ensure_open(autoclose=False):

xarray/backends/scipy_.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,13 @@ def get_encoding(self):
164164
k for k, v in self.ds.dimensions.items() if v is None}
165165
return encoding
166166

167-
def set_dimension(self, name, length):
167+
def set_dimension(self, name, length, is_unlimited=False):
168168
with self.ensure_open(autoclose=False):
169169
if name in self.dimensions:
170170
raise ValueError('%s does not support modifying dimensions'
171171
% type(self).__name__)
172-
self.ds.createDimension(name, length)
172+
dim_length = length if not is_unlimited else None
173+
self.ds.createDimension(name, dim_length)
173174

174175
def _validate_attr_key(self, key):
175176
if not is_valid_nc3_name(key):

xarray/tests/test_backends.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,12 +1171,14 @@ def test_read_byte_attrs_as_unicode(self):
11711171

11721172
def test_encoding_unlimited_dims(self):
11731173
ds = Dataset({'x': ('y', np.arange(10.0))})
1174+
with self.roundtrip(ds,
1175+
save_kwargs=dict(unlimited_dims=['y'])) as actual:
1176+
self.assertEqual(actual.encoding['unlimited_dims'], set('y'))
1177+
self.assertDatasetEqual(ds, actual)
11741178
ds.encoding = {'unlimited_dims': ['y']}
1175-
with create_tmp_file() as tmp_file:
1176-
with pytest.warns(UserWarning):
1177-
ds.to_netcdf(tmp_file, engine='h5netcdf')
1178-
with pytest.warns(UserWarning):
1179-
ds.to_netcdf(tmp_file, engine='h5netcdf', unlimited_dims=['y'])
1179+
with self.roundtrip(ds) as actual:
1180+
self.assertEqual(actual.encoding['unlimited_dims'], set('y'))
1181+
self.assertDatasetEqual(ds, actual)
11801182

11811183

11821184
# tests pending h5netcdf fix
@@ -1343,7 +1345,7 @@ def test_common_coord_when_datavars_all(self):
13431345
self.assertEqual(var_shape, coord_shape)
13441346
self.assertNotEqual(coord_shape1, coord_shape)
13451347
self.assertNotEqual(coord_shape2, coord_shape)
1346-
1348+
13471349
def test_common_coord_when_datavars_minimal(self):
13481350
opt = 'minimal'
13491351

0 commit comments

Comments
 (0)