我正在尝试使用额外属性实现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])
返回一致的结果。