Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Derived class from numpy array does not play well with matrix and masked array

I am trying to subclass a numpy ndarray but I am not able to get right the operations with other numpy types such as masked array or matrix. It seems to me that the __array_priority__ is not being honored. As an example, I have created a dummy class that mimicks the important aspects:

import numpy as np

class C(np.ndarray):

    __array_priority__ = 15.0

    def __mul__(self, other):
        print("__mul__")
        return 42

    def __rmul__(self, other):
        print("__rmul__")
        return 42

Operations between my class and normal ndarray work as expected:

>>> c1 = C((3, 3))
>>> o1 = np.ones((3, 3))
>>> print(o1 * c1)
__mul__
42
>>> print(c1 * o1)
__rmul__
42 

But, when I try to operate with matrix (or masked arrays) the array priority is not respected.

>>> m = np.matrix((3, 3))
>>> print(c1 * m)
__mul__
42
>>> print(m * c1)
Traceback (most recent call last):
...
  File "/usr/lib64/python2.7/site-packages/numpy/matrixlib/defmatrix.py", line 330, in __mul__
    return N.dot(self, asmatrix(other))
ValueError: objects are not aligned

It seems to me that the way ufuncs are wrapped for matrix and masked arrays do not honor array priority. Is this the case? Is there a workaround?

like image 666
Hernan Avatar asked Jul 31 '13 01:07

Hernan


1 Answers

One workaround is to subclass np.matrixib.defmatrix.matrix:

class C(np.matrixlib.defmatrix.matrix):

    __array_priority__ = 15.0

    def __mul__(self, other):
        print("__mul__")
        return 42

    def __rmul__(self, other):
        print("__rmul__")
        return 4

In this case the priority is also higher then a np.ndarray and your multiplication methods are always called.

As added in the comments, you can subclass from multiple classes in case you need interoperability:

class C(np.matrixlib.defmatrix.matrix, np.ndarray):
like image 151
Saullo G. P. Castro Avatar answered Oct 11 '22 13:10

Saullo G. P. Castro