[Numpy-discussion] Memory layout of record arrays
Nicolas Rougier
Nicolas.Rougier at loria.fr
Fri Jul 31 10:04:29 EDT 2009
I've cooked a very rudimentary implementation of what I would like to
have, however I've got a small problem concerning array shape. The idea
is to have a parent array (a group) that can be instantiated like a
regular array and that build internally all the relevant contiguous
child arrays. I would like those child arrays to not be reshapable (at
least not without telling their parent first) and I naively overloaded
the shape property but got a lot of problems with infinite recursion. Is
there a way to do that ?
Nicolas
I put the code below (around 100 lines):
class array(np.ndarray):
def __new__(subtype, shape=(1,1), dtype=np.float32, order=None,
group=None):
obj = np.ndarray.__new__(subtype, shape=shape, dtype=dtype,
order=order)
obj._group = group
return obj
def _get_group(self):
return self._group or self
def _set_group(self, group):
if self.size == group.size:
self.shape = group.shape
self._group = group
else:
raise ValueError, \
'shape mismatch: objects cannot be broadcast to a single
shape'
group = property(_get_group, _set_group,
doc = '''Group to which this array belongs to''')
def _get_shape(self):
return self.ctypes.shape
def _set_shape(self, shape):
if self.group == None:
self.ctypes.shape = shape
else:
raise AttributeError, \
'''Cannot reshape a child array (''group'' is not
None)'''
# shape = property(_get_shape, _set_shape, doc='''c-types shape''')
class group(object):
def __init__(self, shape, dtype=None, order=None):
object.__setattr__(self,'_arrays', {})
self._shape = shape
self._dtype = dtype
if len(dtype) == 0:
self._dtype = np.dtype('f0',dtype)
for i in range(len(self._dtype)):
name, dtype = self._dtype[i]
self._arrays[name] =
array(shape=shape,dtype=dtype,order=order)
def __getattr__(self, key):
if key in self._arrays.keys():
return self._arrays[key]
else:
return object.__getattribute__(self, key)
def __setattr__(self, key, value):
if key in self._arrays.keys():
self._arrays[key][...] = value
else:
object.__setattr__(self, key, value)
def __getitem__(self, key):
return self._arrays[key]
def __setitem__(self, key, value):
self._arrays[key][...] = value
def __len__(self):
return len(self._arrays[self._arrays.keys()[0]])
def _get_shape(self):
return self._shape
def _set_shape(self, shape):
for key in self._arrays.keys():
self._arrays[key].shape = shape
self._shape = shape
shape = property(_get_shape, _set_shape)
def _get_dtype(self):
return self._dtype
def _set_dtype(self):
raise AttributeError, \
'''attribute 'dtype' of 'group' objects is not writable'''
dtype = property(_get_dtype, _set_dtype)
def _get_size(self):
return self._arrays[self._arrays.keys()[0]].size
def _set_size(self):
raise AttributeError, \
'''attribute 'size' of 'group' objects is not writable'''
size = property(_get_size, _set_size)
def __repr__(self):
s = 'group(\n'
for i in range(len(self._dtype)):
name,dtype = self._dtype[i]
t = "'%s': " % name
a = repr(self._arrays[name]).replace('\n', '\n' +' '*len(t))
s += t+a+'\n'
s += ')'
return s
if __name__ == '__main__':
G = group((3,3), dtype =
[('r',np.float32),('g',np.int32),('b',np.bool)])
G['r'] = G.g = G.b = 0
print G
print
G.r.shape = (9,1)
print G.r.shape
print G.shape
On Thu, 2009-07-30 at 20:01 +0200, Nicolas Rougier wrote:
>
> Thanks for the quick answer. It makes sense.
> I will have to find some other way to do it then.
>
> Nicolas
>
>
> On 30 Jul, 2009, at 18:52 , David Cournapeau wrote:
>
> > On Fri, Jul 31, 2009 at 12:53 AM, Nicolas
> > Rougier<Nicolas.Rougier at loria.fr> wrote:
> >>
> >>
> >> Hello,
> >>
> >> I've been using record arrays to create arrays with different types
> >> and since I'm doing a lot of computation on each of the different
> >> fields, the default memory layout does not serve my computations.
> >> Ideally, I would like to have record arrays where each field is a
> >> contiguous block of memory.
> >
> > I don't think you can do it with record arrays: one of the fundamental
> > design choice of numpy array layout is that the data pointer points to
> > one block of N items, where each item is described by the dtype. To
> > have contiguous layout for each member of the structured dtype, you
> > need two arrays with the corresponding dtype.
> >
> > cheers,
> >
> > David
> > _______________________________________________
> > NumPy-Discussion mailing list
> > NumPy-Discussion at scipy.org
> > http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
More information about the NumPy-Discussion
mailing list