Source code for numcodecs.quantize

import math


import numpy as np


from .abc import Codec
from .compat import ensure_ndarray, ndarray_copy


[docs]class Quantize(Codec): """Lossy filter to reduce the precision of floating point data. Parameters ---------- digits : int Desired precision (number of decimal digits). dtype : dtype Data type to use for decoded data. astype : dtype, optional Data type to use for encoded data. Examples -------- >>> import numcodecs >>> import numpy as np >>> x = np.linspace(0, 1, 10, dtype='f8') >>> x array([0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444, 0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ]) >>> codec = numcodecs.Quantize(digits=1, dtype='f8') >>> codec.encode(x) array([0. , 0.125 , 0.25 , 0.3125, 0.4375, 0.5625, 0.6875, 0.75 , 0.875 , 1. ]) >>> codec = numcodecs.Quantize(digits=2, dtype='f8') >>> codec.encode(x) array([0. , 0.109375 , 0.21875 , 0.3359375, 0.4453125, 0.5546875, 0.6640625, 0.78125 , 0.890625 , 1. ]) >>> codec = numcodecs.Quantize(digits=3, dtype='f8') >>> codec.encode(x) array([0. , 0.11132812, 0.22265625, 0.33300781, 0.44433594, 0.55566406, 0.66699219, 0.77734375, 0.88867188, 1. ]) See Also -------- numcodecs.fixedscaleoffset.FixedScaleOffset """ codec_id = 'quantize' def __init__(self, digits, dtype, astype=None): self.digits = digits self.dtype = np.dtype(dtype) if astype is None: self.astype = self.dtype else: self.astype = np.dtype(astype) if self.dtype.kind != 'f' or self.astype.kind != 'f': raise ValueError('only floating point data types are supported')
[docs] def encode(self, buf): # normalise input arr = ensure_ndarray(buf).view(self.dtype) # apply scaling precision = 10. ** -self.digits exp = math.log(precision, 10) if exp < 0: exp = int(math.floor(exp)) else: exp = int(math.ceil(exp)) bits = math.ceil(math.log(10. ** -exp, 2)) scale = 2. ** bits enc = np.around(scale * arr) / scale # cast dtype enc = enc.astype(self.astype, copy=False) return enc
[docs] def decode(self, buf, out=None): # filter is lossy, decoding is no-op dec = ensure_ndarray(buf).view(self.astype) dec = dec.astype(self.dtype, copy=False) return ndarray_copy(dec, out)
[docs] def get_config(self): # override to handle encoding dtypes return dict( id=self.codec_id, digits=self.digits, dtype=self.dtype.str, astype=self.astype.str )
def __repr__(self): r = '%s(digits=%s, dtype=%r' % \ (type(self).__name__, self.digits, self.dtype.str) if self.astype != self.dtype: r += ', astype=%r' % self.astype.str r += ')' return r