diff --git a/src/xray/backends.py b/src/xray/backends.py index d6594e5462e..4b849403c9f 100644 --- a/src/xray/backends.py +++ b/src/xray/backends.py @@ -151,7 +151,23 @@ def convert_variable(var): data = np.asscalar(var[...]) attributes = OrderedDict((k, var.getncattr(k)) for k in var.ncattrs()) - return xarray.XArray(dimensions, data, attributes, + # netCDF4 specific encoding; save _FillValue for later + encoding = {} + filters = var.filters() + if filters is not None: + encoding.update(filters) + chunking = var.chunking() + if chunking is not None: + if chunking == 'contiguous': + encoding['contiguous'] = True + encoding['chunksizes'] = None + else: + encoding['contiguous'] = False + encoding['chunksizes'] = tuple(chunking) + encoding['endian'] = var.endian() + encoding['least_significant_digit'] = \ + attributes.pop('least_significant_digit', None) + return xarray.XArray(dimensions, data, attributes, encoding, indexing_mode='orthogonal') return FrozenOrderedDict((k, convert_variable(v)) for k, v in self.ds.variables.iteritems()) @@ -180,10 +196,20 @@ def set_variable(self, name, variable): # we let the package handle the _FillValue attribute # instead of setting it ourselves. fill_value = variable.attributes.pop('_FillValue', None) - self.ds.createVariable(varname=name, - datatype=variable.dtype, - dimensions=variable.dimensions, - fill_value=fill_value) + encoding = variable.encoding + self.ds.createVariable( + varname=name, + datatype=variable.dtype, + dimensions=variable.dimensions, + zlib=encoding.get('zlib', False), + complevel=encoding.get('complevel', 4), + shuffle=encoding.get('shuffle', True), + fletcher32=encoding.get('fletcher32', False), + contiguous=encoding.get('contiguous', False), + chunksizes=encoding.get('chunksizes'), + endian=encoding.get('endian', 'native'), + least_significant_digit=encoding.get('least_significant_digit'), + fill_value=fill_value) nc4_var = self.ds.variables[name] nc4_var.set_auto_maskandscale(False) nc4_var[:] = variable.data[:] diff --git a/test/test_dataset.py b/test/test_dataset.py index 0ba6dcf6e87..1dde96cab0e 100644 --- a/test/test_dataset.py +++ b/test/test_dataset.py @@ -508,7 +508,9 @@ def test_open_encodings(self): actual = open_dataset(tmp_file) self.assertXArrayEqual(actual['time'], expected['time']) - self.assertDictEqual(actual['time'].encoding, expected['time'].encoding) + actual_encoding = {k: v for k, v in actual['time'].encoding.iteritems() + if k in expected['time'].encoding} + self.assertDictEqual(actual_encoding, expected['time'].encoding) os.remove(tmp_file) @@ -539,6 +541,15 @@ def test_dump_and_open_encodings(self): ds.close() os.remove(tmp_file) + def test_compression_encoding(self): + data = create_test_data() + data['var2'].encoding.update({'zlib': True, + 'chunksizes': (10, 10), + 'least_significant_digit': 2}) + actual = self.roundtrip(data) + for k, v in data['var2'].encoding.iteritems(): + self.assertEqual(v, actual['var2'].encoding[k]) + def test_mask_and_scale(self): f, tmp_file = tempfile.mkstemp(suffix='.nc') os.close(f)