Slicing wrapped numpy arrays

M

Martin Manns

Hi,

I have created a class that wraps a numpy array of custom objects. I
would like to be able to slice respective objects (without copying the
array if possible).

I have browsed the doc and found some hints at __getitem__. However, I
still do not grasp how to do it. How do I implement __getitem__
correctly?


from numpy import *

class Cell(object):
pass

class Map(object):
def __init__(self, dimensions):
self.generate_map(dimensions)

def generate_map(self, dimensions):
map_range = xrange(reduce(lambda x,y: x*y, dimensions))
self.map = array([Cell() for i in map_range])
self.map = self.map.reshape(dimensions)

mymap = Map((100, 100, 100))
mymap[10:20,15:20,:] # This line should work afterwards


Thanks in advance

Martin
 
R

Robert Kern

Martin said:
Hi,

I have created a class that wraps a numpy array of custom objects. I
would like to be able to slice respective objects (without copying the
array if possible).

I have browsed the doc and found some hints at __getitem__. However, I
still do not grasp how to do it. How do I implement __getitem__
correctly?
mymap[10:20,15:20,:] # This line should work afterwards

The first thing you should do is simply implement a very basic, nonfunctional
version just to see what objects come in:

In [1]: class Sliceable(object):
...: def __getitem__(self, arg):
...: print arg
...:

From the output of that you should be able to figure out how to process each of
the various inputs that you want to handle.

In [2]: s = Sliceable()

In [3]: s[0]
0

In [4]: s[-1]
-1

In [5]: s[100]
100

In [6]: s[1:10]
slice(1, 10, None)

In [7]: s[1:10:2]
slice(1, 10, 2)

In [8]: s[1:10:-2]
slice(1, 10, -2)

In [9]: s[:10:2,10]
(slice(None, 10, 2), 10)

In [10]: s[:10:2,10:100:10]
(slice(None, 10, 2), slice(10, 100, 10))

In [11]: s[:10:2,10::10]
(slice(None, 10, 2), slice(10, None, 10))

In [12]: s[::2,10::10]
(slice(None, None, 2), slice(10, None, 10))

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
M

Martin Manns

Martin said:
Hi,

I have created a class that wraps a numpy array of custom objects. I
would like to be able to slice respective objects (without copying
the array if possible).

I have browsed the doc and found some hints at __getitem__.
However, I still do not grasp how to do it. How do I implement
__getitem__ correctly?
mymap[10:20,15:20,:] # This line should work afterwards

The first thing you should do is simply implement a very basic,
nonfunctional version just to see what objects come in:

In [1]: class Sliceable(object):
...: def __getitem__(self, arg):
...: print arg
...:

I did that and got here:
(slice(None, None, 2), slice(10, None, 10))

However, I still do not see how I get a Map object that employs a
slice of the array without creating a new Map object.

Martin
 
R

Robert Kern

Martin said:
Martin said:
Hi,

I have created a class that wraps a numpy array of custom objects. I
would like to be able to slice respective objects (without copying
the array if possible).

I have browsed the doc and found some hints at __getitem__.
However, I still do not grasp how to do it. How do I implement
__getitem__ correctly?
mymap[10:20,15:20,:] # This line should work afterwards
The first thing you should do is simply implement a very basic,
nonfunctional version just to see what objects come in:

In [1]: class Sliceable(object):
...: def __getitem__(self, arg):
...: print arg
...:

I did that and got here:
(slice(None, None, 2), slice(10, None, 10))

However, I still do not see how I get a Map object that employs a
slice of the array without creating a new Map object.

That's because creating a new Map object is the right thing to do.

Instead of making Map.__init__() generate the map array from the dimensions, it
should just take a preconstructed map array. You can use a @classmethod or just
a factory function to provide an alternate constructor which builds a Map from
the dimensions.

When designing classes, I usually try to do as little computation as possible in
an __init__(). Doing a lot of stuff there limits the ways you can build the
object later. For some classes, this doesn't matter a whole lot, but for data
structures that can be sliced and concatenated or otherwise transformed, you
really want that flexibility.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top