Assignment to wrapped fragment of numpy array

I have a large image Aand a smaller image B, both expressed as 2-D numpyarrays. I want to use Aas a canvas and write on it translated copies B, packed in a hexagonal layout. The part I can't figure out with is how to process it so that the image wraps both vertically and horizontally - essentially, I want regular tessellation of the (augmented, if necessary) sub-image on torus.

I have seen the discussion numpy.takeand numpy.rollto wrap pieces in the Python / numpy , and it shows me how to access and restore a copy of the wrapped array slice, but I want to do, ie, for any integers rowOffsetand columnOffsetI want to make the equivalent:

  A = numpy.zeros((5,11), int)
  B = numpy.array([[1,2,3,4,5,6,7]]) * numpy.array([[10,100,1000]]).T
  # OK, we wouldn't be able to fit more than one or two copies of B into A, but they demonstrate the wrapped placement problem

  wrappedRowIndices = ( numpy.arange(B.shape[0]) + rowOffset ) % A.shape[0]
  wrappedColumnIndices = ( numpy.arange(B.shape[1]) + columnOffset ) % A.shape[1]
  A[ wrappedRowIndices,  : ][ :, wrappedColumnIndices ] = B 

I see from the commentary on the issue , and from the moment of reflection on the path numpy, arrays are presented that cannot be returned by a wrapped slice as viewin accordance with how it is required.

Is there a (Y) way to assign wrapped slices to an array this way or (X) an existing utility to do the type of tessellation I'm trying to achieve?

+2
source share
3

__getitem__ __setitem__. __getitem__ , , __setitem__ .

__setitem__ (.. ):

A[wrappedRowIndices[:,np.newaxis], wrappedColumnIndices] = B

- :

A[wrappedRowIndices[:,np.newaxis], wrappedColumnIndices[np.newaxis,:]] = B

:

# ... here is NOT the python Ellipsis!
y = x[a, b, c, ...]
y[i, j, ..] = x[a[i,j,...], b[i,j,...], ...]

np.ix_():

A[np.ix_(wrappedRowIndices, wrappedColumnIndices)] = B

ND, :

def place_wrapped(canvas, brush, position):
    assert canvas.ndim == brush.ndim == len(position)
    ind = np.ix_(*(
        (np.arange(b_dim) + shift) % c_dim
        for b_dim, c_dim, shift in zip(brush.shape, canvas.shape, position)
    ))
    canvas[ind] = brush

+1

np.put 1d np.take:

In [1270]: A=np.arange(10)
In [1271]: np.take(A,[8,9,10,11],mode='wrapped')
Out[1271]: array([8, 9, 0, 1])
In [1272]: np.put(A,[8,9,10,11],[10,11,12,13],mode='wrapped')
In [1273]: A
Out[1273]: array([12, 13,  2,  3,  4,  5,  6,  7, 10, 11])
In [1274]: np.take(A,[8,9,10,11],mode='wrapped')
Out[1274]: array([10, 11, 12, 13])

np.place np.putmask ( np.copyto). , B, .

=================

place:

In [1313]: A=np.arange(24).reshape(4,6)
In [1314]: mask=np.zeros(A.shape,bool)
In [1315]: mask[:3,:4]=True
In [1316]: B=-np.arange(12).reshape(3,4)

, mask , A, "" B.

mask, B place A wrapped.

In [1317]: np.place(A, np.roll(mask,-2,0), np.roll(B,1,0).flat)
In [1318]: A
Out[1318]: 
array([[ -8,  -9, -10, -11,   4,   5],
       [  6,   7,   8,   9,  10,  11],
       [  0,  -1,  -2,  -3,  16,  17],
       [ -4,  -5,  -6,  -7,  22,  23]])

2d

In [1332]: m=np.roll(np.roll(mask,-2,0),-1,1)
In [1333]: m
Out[1333]: 
array([[ True,  True,  True, False, False,  True],
       [False, False, False, False, False, False],
       [ True,  True,  True, False, False,  True],
       [ True,  True,  True, False, False,  True]], dtype=bool)
In [1334]: b=np.roll(np.roll(B,1,0),-1,1)
In [1335]: b
Out[1335]: 
array([[ -9, -10, -11,  -8],
       [ -1,  -2,  -3,   0],
       [ -5,  -6,  -7,  -4]])
In [1336]: A=np.zeros((4,6),int)
In [1337]: np.place(A, m, b.flat)
In [1338]: A
Out[1338]: 
array([[ -9, -10, -11,   0,   0,  -8],
       [  0,   0,   0,   0,   0,   0],
       [ -1,  -2,  -3,   0,   0,   0],
       [ -5,  -6,  -7,   0,   0,  -4]])
+3

Here is a function that works to solve my Y problem based on hpaulj answer. This is probably not the most efficient way to solve X, however, due to all the hard lifting done at numpy.roll.

import numpy

def place_wrapped(canvas, brush, position):
    mask = numpy.zeros(canvas.shape, bool)
    mask[[slice(extent) for extent in brush.shape]] = True
    for axis, shift in enumerate(position):
        canvas_extent = canvas.shape[axis]
        brush_extent = brush.shape[axis]
        shift %= canvas_extent
        if shift:
            mask = numpy.roll(mask, shift, axis=axis)
            nwrapped = shift + brush_extent - canvas_extent
            if nwrapped > 0: brush = numpy.roll(brush, nwrapped, axis=axis)
    numpy.place(canvas, mask, brush.flat)


A = numpy.zeros((5,11), int)
B = numpy.array([[1,2,3,4,5,6,7]]) * numpy.array([[10,100,1000]]).T
print(B)

rowOffset = 3
columnOffset = 7
place_wrapped(A, B, (rowOffset, columnOffset))
print(A)

Eric's corrected approach also worked, and I think it should be more efficient because it does not need to make copies of any data:

def place_wrapped2(canvas, brush, position):
    ind = [
        ((numpy.arange(brush.shape[axis]) + shift) % canvas.shape[axis]).reshape([
            extent if i == axis else 1
            for i, extent in enumerate(brush.shape)
        ])
        for axis, shift in enumerate(position)
    ]
    canvas[ind] = brush

A *= 0 # reset
place_wrapped2(A, B, (rowOffset, columnOffset))
print(A)
+1
source

Source: https://habr.com/ru/post/1659352/


All Articles