@@ -212,11 +212,24 @@ class CFScaleOffsetCoder(VariableCoder):
212
212
decode_values = encoded_values * scale_factor + add_offset
213
213
"""
214
214
215
+ @staticmethod
216
+ def _choose_float_dtype (data , attributes ):
217
+ # We default to en/decoding as float64, but for small integer types
218
+ # and no offset it's usually safe to use float32, which saves a lot
219
+ # of memory for eg. TB-scale satellite imagery collections.
220
+ if data .dtype .itemsize <= 2 and \
221
+ np .issubdtype (data .dtype , np .integer ) and \
222
+ 'add_offset' not in attributes and \
223
+ 2 ** - 23 < float (attributes .get ('scale_factor' , 1 )) < 2 ** 8 :
224
+ return np .float32
225
+ return np .float64
226
+
215
227
def encode (self , variable , name = None ):
216
228
dims , data , attrs , encoding = unpack_for_encoding (variable )
217
229
218
230
if 'scale_factor' in encoding or 'add_offset' in encoding :
219
- data = data .astype (dtype = np .float64 , copy = True )
231
+ dtype = self ._choose_float_dtype (data , encoding )
232
+ data = data .astype (dtype = dtype , copy = True )
220
233
if 'add_offset' in encoding :
221
234
data -= pop_to (encoding , attrs , 'add_offset' , name = name )
222
235
if 'scale_factor' in encoding :
@@ -230,7 +243,7 @@ def decode(self, variable, name=None):
230
243
if 'scale_factor' in attrs or 'add_offset' in attrs :
231
244
scale_factor = pop_to (attrs , encoding , 'scale_factor' , name = name )
232
245
add_offset = pop_to (attrs , encoding , 'add_offset' , name = name )
233
- dtype = np . float64
246
+ dtype = self . _choose_float_dtype ( data , attrs )
234
247
transform = partial (_scale_offset_decoding ,
235
248
scale_factor = scale_factor ,
236
249
add_offset = add_offset ,
0 commit comments