使用特定于轴的属性对numpy数组进行子类化

时间:2018-02-09 16:08:07

标签: python numpy oop

我正在尝试使用额外属性实现np.ndarray的子类。我希望将这些属性传递给此实例的视图。

抄袭numpy docs中的内容,尽管我还不确定({1}}中发生了什么,但我最终得到的这个课程尽管我能说得很好。 / p>

__array_finalize__

现在是时候变得棘手了。我需要实现另一个子类,理想情况下继承自class InfoArray(np.ndarray): """ An array with extra attributes, being passed on to views and results of ufuncs. """ def __new__(cls, array, *args, **kwargs): # Input array is an already formed ndarray instance # We first cast to be our class type obj = np.asarray(array).view(cls) # add the new attributes to the created instance for key, value in kwargs.items(): setattr(obj, key, value) # Finally, we must return the newly created object: return obj def __array_finalize__(self, obj): """ This function ensures that attributes are present in all ways instances are created, including views on the array. """ if type(obj) is not np.ndarray: for key, value in vars(obj).items(): setattr(self, key, value) def __array_wrap__(self, obj, context=None): """Ensure that scalar type is returned instead of 0D array""" if obj.shape == (): return obj[()] # if ufunc output is scalar, return it else: return np.ndarray.__array_wrap__(self, obj) 并且带有轴特定的属性。我的最终目标是让我的实例的低维视图具有截断的属性。

由于我不确定我所问的内容是否清楚,我将举一个具体的例子。我需要一个InfoArray类来存储MedicalImage属性,该属性表示沿每个轴的数组的两个元素之间的距离。例如,spacing用于渐变计算。

这是我到目前为止所拥有的:

spacing

这对于简单的用例非常有用。

class MedicalImage(InfoArray):
    """A medical image (usually 2 or 3 dimensions)"""
    def __init__(self, array, spacing=None, *args, **kwargs):
        """Ensure a spacing attribute is present"""
        if spacing is None:
            spacing = np.ones(self.ndim)
        self.spacing = np.asarray(spacing)

    def gradients(self):
        """Compute spacing-aware gradients"""
        result = np.moveaxis(np.array(np.gradient(self)), 0, -1)
        result /= self.spacing
        return result

渐变考虑间距,这很好。

还为视图保留了属性:

In [3]: image = MedicalImage(np.arange(25).reshape((5,5)),
                             spacing=[1,2],
                             patient_name='john doe')

In [4]: image.gradients()[0,0]
Out[4]: array([5. , 0.5])

现在,让我们来看看轴特定的属性:

In [5]: image[5].patient_name
Out[5]: 'john doe'

这将允许一个不错的In [6]: image[0].spacing Out[6]: array([1, 2]) # Desired output: array([1]) or just 1 In [7]: image.T.spacing Out[7]: array([1, 2]) # Desired output: array([2, 1]) 返回一致的结果。

PS:我知道nibabelmedpysimpleitk(......)的存在,但我这样做是出于教育目的。

0 个答案:

没有答案