-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Dataset.encoding and unlimited dimensions for to_netcdf #1170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 17 commits
271a751
bedad43
c797511
affac00
ca60729
3d24610
e794165
2ba6688
b7bd0b8
fdbd55d
47442e6
2df224c
eead3e4
fac2f89
33dd062
65df346
b076c15
db964a1
cb22ba1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ class InMemoryDataStore(AbstractWritableDataStore): | |
def __init__(self, variables=None, attributes=None, writer=None): | ||
self._variables = OrderedDict() if variables is None else variables | ||
self._attributes = OrderedDict() if attributes is None else attributes | ||
self.encoding = {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. delete |
||
super(InMemoryDataStore, self).__init__(writer) | ||
|
||
def get_attrs(self): | ||
|
@@ -29,7 +30,7 @@ def get_attrs(self): | |
def get_variables(self): | ||
return self._variables | ||
|
||
def prepare_variable(self, k, v, check_encoding=False): | ||
def prepare_variable(self, k, v, *args, **kwargs): | ||
new_var = Variable(v.dims, np.empty_like(v), v.attrs) | ||
# we copy the variable and stuff all encodings in the | ||
# attributes to imitate what happens when writing to disk. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
import numpy as np | ||
|
||
from .. import Variable | ||
from ..conventions import pop_to, cf_encoder | ||
from ..conventions import pop_to | ||
from ..core import indexing | ||
from ..core.utils import (FrozenOrderedDict, NDArrayMixin, | ||
close_on_error, is_remote_uri) | ||
|
@@ -138,13 +138,13 @@ def _force_native_endianness(var): | |
# check to see if encoding has a value for endian its 'native' | ||
if not var.encoding.get('endian', 'native') is 'native': | ||
raise NotImplementedError("Attempt to write non-native endian type, " | ||
"this is not supported by the netCDF4 python " | ||
"library.") | ||
"this is not supported by the netCDF4 " | ||
"python library.") | ||
return var | ||
|
||
|
||
def _extract_nc4_encoding(variable, raise_on_invalid=False, lsd_okay=True, | ||
backend='netCDF4'): | ||
def _extract_nc4_variable_encoding(variable, raise_on_invalid=False, | ||
lsd_okay=True, backend='netCDF4'): | ||
encoding = variable.encoding.copy() | ||
|
||
safe_to_drop = set(['source', 'original_shape']) | ||
|
@@ -154,9 +154,8 @@ def _extract_nc4_encoding(variable, raise_on_invalid=False, lsd_okay=True, | |
valid_encodings.add('least_significant_digit') | ||
|
||
if (encoding.get('chunksizes') is not None and | ||
(encoding.get('original_shape', variable.shape) | ||
!= variable.shape) and | ||
not raise_on_invalid): | ||
(encoding.get('original_shape', variable.shape) != | ||
variable.shape) and not raise_on_invalid): | ||
del encoding['chunksizes'] | ||
|
||
for k in safe_to_drop: | ||
|
@@ -251,6 +250,12 @@ def get_dimensions(self): | |
return FrozenOrderedDict((k, len(v)) | ||
for k, v in iteritems(self.ds.dimensions)) | ||
|
||
def get_encoding(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would lean slightly toward just creating a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other encoding value that comes to mind is the dataset format (e.g. NETCDF4 vs. NETCDF3). Maybe there are others as well but nothing is mind. |
||
encoding = {} | ||
encoding['unlimited_dims'] = { | ||
k for k, v in self.ds.dimensions.items() if v.isunlimited()} | ||
return encoding | ||
|
||
def set_dimension(self, name, length): | ||
self.ds.createDimension(name, size=length) | ||
|
||
|
@@ -259,7 +264,8 @@ def set_attribute(self, key, value): | |
value = encode_nc3_attr_value(value) | ||
self.ds.setncattr(key, value) | ||
|
||
def prepare_variable(self, name, variable, check_encoding=False): | ||
def prepare_variable(self, name, variable, check_encoding=False, | ||
unlimited_dims=None): | ||
attrs = variable.attrs.copy() | ||
|
||
variable = _force_native_endianness(variable) | ||
|
@@ -270,16 +276,16 @@ def prepare_variable(self, name, variable, check_encoding=False): | |
variable = encode_nc3_variable(variable) | ||
datatype = variable.dtype | ||
|
||
self.set_necessary_dimensions(variable) | ||
self.set_necessary_dimensions(variable, unlimited_dims=unlimited_dims) | ||
|
||
fill_value = attrs.pop('_FillValue', None) | ||
if fill_value in ['', '\x00']: | ||
# these are equivalent to the default FillValue, but netCDF4 | ||
# doesn't like setting fill_value to an empty string | ||
fill_value = None | ||
|
||
encoding = _extract_nc4_encoding(variable, | ||
raise_on_invalid=check_encoding) | ||
encoding = _extract_nc4_variable_encoding( | ||
variable, raise_on_invalid=check_encoding) | ||
nc4_var = self.ds.createVariable( | ||
varname=name, | ||
datatype=datatype, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,6 +62,7 @@ class PydapDataStore(AbstractDataStore): | |
def __init__(self, url): | ||
import pydap.client | ||
self.ds = pydap.client.open_url(url) | ||
self.encoding = {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. delete |
||
|
||
def open_store_variable(self, var): | ||
data = indexing.LazilyIndexedArray(PydapArrayWrapper(var)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,7 @@ def __init__(self, filename, mode='r'): | |
self.ds = opener() | ||
self._opener = opener | ||
self._mode = mode | ||
self.encoding = {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. delete |
||
|
||
def open_store_variable(self, name, var): | ||
data = indexing.LazilyIndexedArray(NioArrayWrapper(name, self)) | ||
|
@@ -57,5 +58,11 @@ def get_attrs(self): | |
def get_dimensions(self): | ||
return Frozen(self.ds.dimensions) | ||
|
||
def get_encoding(self): | ||
encoding = {} | ||
encoding['unlimited_dims'] = set( | ||
[k for k in self.ds.dimensions if self.ds.unlimited(k)]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think dap can represent unlimited dimensions: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, but this is pynio which does: https://www.pyngl.ucar.edu/whatsnew.shtml#Version1.4.1 |
||
return encoding | ||
|
||
def close(self): | ||
self.ds.close() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
import warnings | ||
|
||
from .. import Variable | ||
from ..core.pycompat import iteritems, basestring, OrderedDict | ||
from ..core.pycompat import iteritems, OrderedDict | ||
from ..core.utils import Frozen, FrozenOrderedDict | ||
from ..core.indexing import NumpyIndexingAdapter | ||
|
||
|
@@ -102,6 +102,7 @@ def __init__(self, filename_or_obj, mode='r', format=None, group=None, | |
self.ds = opener() | ||
self._opener = opener | ||
self._mode = mode | ||
self.encoding = {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. delete |
||
|
||
super(ScipyDataStore, self).__init__(writer) | ||
|
||
|
@@ -116,9 +117,18 @@ def get_variables(self): | |
def get_attrs(self): | ||
return Frozen(_decode_attrs(self.ds._attributes)) | ||
|
||
def _get_unlimited_dimensions(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think you use this method anymore |
||
return set(k for k, v in iteritems(self.ds.dimensions) if v is None) | ||
|
||
def get_dimensions(self): | ||
return Frozen(self.ds.dimensions) | ||
|
||
def get_encoding(self): | ||
encoding = {} | ||
encoding['unlimited_dims'] = { | ||
k for k, v in self.ds.dimensions.items() if v is None} | ||
return encoding | ||
|
||
def set_dimension(self, name, length): | ||
if name in self.dimensions: | ||
raise ValueError('%s does not support modifying dimensions' | ||
|
@@ -134,13 +144,17 @@ def set_attribute(self, key, value): | |
value = encode_nc3_attr_value(value) | ||
setattr(self.ds, key, value) | ||
|
||
def prepare_variable(self, name, variable, check_encoding=False): | ||
def prepare_variable(self, name, variable, check_encoding=False, | ||
unlimited_dims=None): | ||
variable = encode_nc3_variable(variable) | ||
if check_encoding and variable.encoding: | ||
raise ValueError('unexpected encoding for scipy backend: %r' | ||
% list(variable.encoding)) | ||
|
||
self.set_necessary_dimensions(variable) | ||
if unlimited_dims is not None and len(unlimited_dims) > 1: | ||
raise ValueError('NETCDF3 only supports one unlimited dimension') | ||
self.set_necessary_dimensions(variable, unlimited_dims=unlimited_dims) | ||
|
||
data = variable.data | ||
# nb. this still creates a numpy array in all memory, even though we | ||
# don't write the data yet; scipy.io.netcdf does not not support | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still should go away :)