quantities.Quantity is a subclass of numpy.ndarray that handles arithmetic and conversions of physical quantities. How can I make use of it’s arithmetics without subclassing it? The following approach uses an __array__-method — but just works 80%, as you can see in the end:
class Numeric(object):
def __init__(self, signal):
self.signal = signal
self._dimensionality = self.signal._dimensionality
self.dimensionality = self.signal.dimensionality
def __array__(self):
return self.signal
def __mul__(self, obj):
return self.signal.__mul__(obj)
def __rmul__(self, obj):
return self.signal.__rmul__(obj)
With this I can do:
import quantities as pq
import numpy as np
num = Numeric(pq.Quantity([1,2,3], 'mV'))
q = pq.Quantity([2,3,4], 'mV')
n = np.array([3,4,5])
All of the following operations return the correct unit — except the last, there the unit is missing:
print num * num
# [1 4 9] mV**2
print num * q
# [ 2 6 12] mV**2
print num * n
# [ 3 8 15] mV
print q * num
# [ 2 6 12] mV**2
print n * num
# [ 3 8 15] <------- no unit!
Any idea, what to fix in order to keep the correct unit?
edit: The return type/value of an arithmentic opperation should be equivalent to:
num.signal * num.signalnum.signal * qnum.signal * nq * num.signaln * num.signal # this doesn't work
When Python sees
x * yhere’s what happens:yis a subclass ofx–>y.__rmul__(x)is calledotherwise:
x.__mul__(y)is calledIF
x.__mul__(y)returnsNotImplemented(which is different fromraise NotImplementedErrory.__rmul__(x)is calledSo, there are two ways that
__rmul__can be called — subclassndarray, or havendarraynot be able to multiply withNumeric.You are unable to subclass, and apparently
ndarrayis happy to work withNumeric, so . . .Thankfully, the
numpyfolks prepared for situations such as this — the answer lies in the__array_wrap__method:We are using the original
signalclass, along with the original dimensionality, to create a new signal for the newNumericobject.The entire bit looks like this:
And when run: