[cctbxbb] Flex array slice assignment work-alike

James Stroud xtald00d at gmail.com
Thu Apr 11 10:08:38 PDT 2013


On Apr 11, 2013, at 9:18 AM, Luc Bourhis wrote:
> On 11 Apr 2013, at 09:49, James Stroud wrote:
> 
>> It seems that flex arrays do not support slice assignment:
> 
> it would not be too difficult to code 1-dimensional slice assignment  but ...
> 
> On 11 Apr 2013, at 10:24, Graeme.Winter at Diamond.ac.uk wrote:
> 
>> [...] 
>>            array[k,:,:] = image.as_numpy_array()[y0:y1, x0:x1]
> 
> that's way more difficult!



In python this type of magic is fairly straightforward because the slice is just a tuple:

py> class Example(object):
...   def __setitem__(self, i, v):
...     print "setting %s to %s" % (i, v)
...
py> e = Example()
py> e[5:6, 4, 8:9, "bob"] = 2
setting (slice(5, 6, None), 4, slice(8, 9, None), 'bob') to 2


This should actually be the case on the C side, too, not that it wouldn't take a few lines of code to build an iterator based on the slice.

But as a way to circumvent all of this magic with slices (which would be very cool, by the way), it might be easiest for the programmer (and somewhat intuitive for those familiar with flex) just to add a signature to set_selected() that uses a flex.grid to represent a slice because flex.grid already encapsulates the most useful aspects of slicing semantics.


Here is a prototype for the suggested behavior in python using ndarray as a back-end:

class Prototype(object):
  def __init__(self, data):
    self.data = numpy.array(data)
  def __getitem__(self, i):
    if isinstance (i, flex.grid):
      slices = [slice(*t) for t in zip(i.origin(), i.last())]
      return self.__class__(self.data[slices])
    else:
      return self.__class__(self.data[i])
  def __setitem__(self, i, v):
    if isinstance (i, flex.grid):
      slices = [slice(*t) for t in zip(i.origin(), i.last())]
      self.data[slices] = v
    else:
      self.data[i] = v
  def __repr__(self):
    return repr(self.data)


And here it is in action:

py> grd = flex.grid((1, 1), (3, 3))  # <== selects [1:3, 1:3]
py> ary = Prototype(numpy.arange(25).reshape((5,5)))
py> ary
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])
py> ary[grd]
array([[ 6,  7],
       [11, 12]])
py> ary[grd] = [[41, 42], [43, 44]]
py> ary[grd]
array([[41, 42],
       [43, 44]])
py> ary
array([[ 0,  1,  2,  3,  4],
       [ 5, 41, 42,  8,  9],
       [10, 43, 44, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

James
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://phenix-online.org/pipermail/cctbxbb/attachments/20130411/1796101d/attachment.htm>


More information about the cctbxbb mailing list