oslocyclotronlab / ompy_Archive_Sept2019

Archived version om ompy as of 27. Sept 2019 -- Please use this instead:
https://github.com/oslocyclotronlab/ompy/
GNU General Public License v3.0
0 stars 1 forks source link

Matrix class as subclass of numpy ndarray? #10

Closed fzeiser closed 5 years ago

fzeiser commented 5 years ago

Issue by fzeiser Wednesday Nov 14, 2018 at 14:10 GMT Originally opened as https://github.com/oslocyclotronlab/ompy/issues/10


Wouldn't it be good to have the matrix class be a subclass of ndarray? Then you can run all numpy functions eg. on the om.firstgen object itself, instead of having to call om.firstgen.matrix every time.

For implementation: https://docs.scipy.org/doc/numpy-1.13.0/user/basics.subclassing.html#slightly-more-realistic-example-attribute-added-to-existing-array

Note that we should change the name from matrixto something else then, in order to not confuse it with numpy.matrix. Eg. the class could be called OsloMatrix or maybe rather OsloArray

fzeiser commented 5 years ago

Comment by fzeiser Friday Nov 23, 2018 at 13:51 GMT


So, subclassing will work. But without a wiser implementation than mine (which was basically copied from the numpy instructions above), the calculations will take more time. Maybe implement in Cython?

import numpy as np
import timeit

class MyClass(np.ndarray):
    def __new__(cls, data, Earr1=None, Earr2=None):
        obj = np.asarray(data).view(cls)
        obj.Earr1 = Earr1
        obj.Earr2 = Earr2
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.Earr1 = getattr(obj, 'Earr1', None)
        self.Earr2 = getattr(obj, 'Earr2', None)

class MyClassGetItem(np.ndarray):
    def __new__(cls, data, Earr1=None, Earr2=None):
        obj = np.asarray(data).view(cls)
        obj.Earr1 = Earr1
        obj.Earr2 = Earr2
        return obj

    def __array_finalize__(self, obj):
        self.Earr1 = getattr(obj, 'Earr1', None)
        self.Earr2 = getattr(obj, 'Earr2', None)

    def __getitem__(self, item):
        ret = super(MyClassGetItem, self).__getitem__(item)
        # need this, such that single entries still keep a energy calibration
        ret = MyClassGetItem(ret,Earr1=self.Earr1, Earr2=self.Earr2)
        if self.Earr1 is not None and isinstance(item[0], (slice, int)):
            ret.Earr1 = self.Earr1.__getitem__(item[0])
        if len(item)==2:
            if self.Earr2 is not None and isinstance(item[1], (slice, int)):
                ret.Earr2 = self.Earr2.__getitem__(item[1])
        return ret

class OsloClass():
    """
    The matrix class stores matrices along with calibration and energy axis arrays.
    """
    def __init__(self, matrix=None, Earr1=None, Earr2=None):
        """
        Initialise the class. There is the option to initialise
        it in an empty state. In that case, all class variables will be None.
        It can be filled later using the load() method.
        """
        self.matrix = matrix
        self.Earr1 = Earr1
        self.Earr2 = Earr2

def print_timing(cmd):
    t = timeit.timeit(cmd,globals=globals(), number=int(1e6))
    print (t)

arr = np.arange(5)
arr2d = np.array([arr,arr,arr-3,arr+7,arr+3])

# numpy result
print_timing('np.sqrt(arr2d)')
# 2.23
print_timing('np.sqrt(arr2d)[2,2]')
# 2.48

# MyClass
a = MyClass(arr2d, Earr1=arr, Earr2=-arr)
print_timing('np.sqrt(a)')
# 3.73
# 3.95

# MyClass with the GetItem attribute
a = MyClassGetItem(arr2d, Earr1=arr, Earr2=-arr)
print_timing('np.sqrt(a)')
# 3.74
print_timing('np.sqrt(a)[2,2]')
# 9.75
fzeiser commented 5 years ago

Comment by fzeiser Thursday May 02, 2019 at 10:27 GMT


Cannot have been closed in 6c93485, can it? Nothing addressed in this regard. @jorgenem: Which #10 did you refer to?

fzeiser commented 5 years ago

Comment by jorgenem Thursday May 02, 2019 at 10:48 GMT


I didn't mean to close anything. This is one of the many times when I feel like Github controls me more than the other way around... :-)

fzeiser commented 5 years ago

Comment by fzeiser Thursday May 02, 2019 at 10:58 GMT


My bad! Actually it was me who wrote a wrong commit message for some reason.

fzeiser commented 5 years ago

Comment by Caronthir Tuesday Sep 03, 2019 at 10:51 GMT


Subclassing ndarray is unrealistic at this stage. Using normal dunder methods is planed.