Python Numpy子类属性切片
Python Numpy子类属性切片,python,numpy,slice,Python,Numpy,Slice,Myclass是一个numpy.ndarray子类,用于表示一组随时间变化的图像。每个图像都有一组元数据,如时间、环境温度和相机温度。我已将这些元数据存储在字典列表中,因此每个字典都对应于数组中的一个层(myclass.metadata[0]是对应于myclass[0]中图像的字典) 我还重载了getattr(),使字典中的项可以通过它们的键访问,因此myclass.etemp产生了例如[24.9,25.0,25.1] 当我切片Myclass对象时,如何实现属性数组以相同的方式切片 现在如果我做
Myclass
是一个numpy.ndarray
子类,用于表示一组随时间变化的图像。每个图像都有一组元数据,如时间、环境温度和相机温度。我已将这些元数据存储在字典列表中,因此每个字典都对应于数组中的一个层(myclass.metadata[0]
是对应于myclass[0]
中图像的字典)
我还重载了getattr()
,使字典中的项可以通过它们的键访问,因此myclass.etemp
产生了例如[24.9,25.0,25.1]
当我切片Myclass对象时,如何实现属性数组以相同的方式切片
现在如果我做myobject[1].etemp
,我得到[24.9,25.0,25.1]
,但我想要[25.0]
这是我的班级:
class Stack(numpy.ndarray):
props= [
'version',
'width',
'height',
'shotrange',
'calibrange',
'unit',
'irb_fname',
'fidx',
'distance',
'etemp',
'zoom',
'ctemp',
'date',
'recdate',
'rectime',
]
def __new__(cls, input_array, mdata=None):
obj = numpy.asarray(input_array).view(cls)
if isinstance(mdata, collections.Iterable): # when reading from text file
obj.mdata = mdata
else:
obj.mdata = [arr.mdata[0] for arr in input_array] # when combining Stack-type objects
return obj
def __array_finalize__(self, obj):
if obj is None: return
self.mdata = getattr(obj, 'mdata', None)
def __getattr__(self, name):
print(numpy.shape(self))
if numpy.rank(self) < 3: # we're looking at a single slice
pass
if name == 'starttime':
return self.mdata[0]['date']
elif name == 'time':
return [(item['date'] - self.mdata[0]['date']).total_seconds() for item in self.mdata]
elif name in Stack.props:
return [item[name] for item in self.mdata]
else:
raise AttributeError
类堆栈(numpy.ndarray):
道具=[
“版本”,
“宽度”,
“高度”,
“射程”,
“calibrange”,
"单位",,
“irb_fname”,
“fidx”,
“距离”,
“etemp”,
“缩放”,
“ctemp”,
“日期”,
“记录日期”,
'矩形',
]
def _u新建(cls,输入数组,mdata=None):
obj=numpy.asarray(输入数组).view(cls)
如果isinstance(mdata,collections.Iterable):#从文本文件读取时
obj.mdata=mdata
其他:
obj.mdata=[arr.mdata[0]表示输入数组中的arr]#组合堆栈类型对象时
返回obj
def _;阵列_;最终确定___;(自身,obj):
如果obj为无:返回
self.mdata=getattr(obj,'mdata',无)
def _ugetattr _;(self,name):
打印(numpy.shape(自身))
如果numpy.rank(self)<3:#我们只看一个片段
通过
如果名称==“开始时间”:
返回self.mdata[0]['date']
elif名称==“时间”:
返回[(item['date']-self.mdata[0]['date'])。self.mdata中项目的总秒数()
Stack.props中的elif名称:
返回[self.mdata中项目的项目[名称]
其他:
提高属性错误
我需要做什么来实现这种行为?或者是否有其他更好的方法来存储元数据?将属性附加到数组中的对象,而不是附加到数组中可能会有所帮助。您需要重写
\uu getitem\uuuu
方法
class Foo(object):
def __getitem__(self,items):
print items
f = Foo()
f[1,2,3]
f[1:3]
f[1,1:3,2:3]
这将返回:
1
(1, 2, 3)
slice(1, 3, None)
(1, slice(1, 3, None), slice(2, 3, None))
在
\uuuu getitem\uuuuu
中,您需要适当地分割属性,并处理上述情况。还可能需要查看PyTables,这是一种存储数据和相关元数据的好方法。超快也!我已经在使用h5py在磁盘上存储数据了,但是我会不会失去像myclass[0,0,0]和myclass[0:3]这样的功能?这是我将NdarayTank you子类化的主要原因,这是我失败的地方,但现在问题似乎已经解决了。我无意中发现了numpy.ndarray.\uuuu array\uuuu()
。我的\uu getitem\uu()
现在检查self
是否为等级3,然后才修改元数据。每次调用都会返回一个新的堆栈对象。此外,我还必须修改\uuuu getslice\uuuu(self,I,j)
以调用self[I:j:None]
,这样切片就成为扩展切片并传递给\uuu getitem\uuuu()
。默认情况下不应该发生这种情况吗?为了向后兼容,在\uuuuuu getitem\uuuuu
之前会尝试\uuuuu getslice\uuuuu
。因此,如果基类实现了\uuu getslice\uuu
,那么您也必须重写它。