Discussion:
[Numpy-discussion] Reflect array?
Benjamin Root
2016-03-29 17:46:45 UTC
Permalink
Is there a quick-n-easy way to reflect a NxM array that represents a
quadrant into a 2Nx2M array? Essentially, I am trying to reduce the size of
an expensive calculation by taking advantage of the fact that the first
part of the calculation is just computing gaussian weights, which is
radially symmetric.

It doesn't seem like np.tile() could support this (yet?). Maybe we could
allow negative repetitions to mean "reflected"? But I was hoping there was
some existing function or stride trick that could accomplish what I am
trying.

x = np.linspace(-5, 5, 20)
y = np.linspace(-5, 5, 24)
z = np.hypot(x[None, :], y[:, None])
zz = np.hypot(x[None, :int(len(x)//2)], y[:int(len(y)//2), None])
zz = some_mirroring_trick(zz)
assert np.all(z == zz)

What can be my "some_mirroring_trick()"? I am hoping for something a little
better than using hstack()/vstack().

Thanks,
Ben Root
Joseph Fox-Rabinovitz
2016-03-29 17:58:44 UTC
Permalink
Post by Benjamin Root
Is there a quick-n-easy way to reflect a NxM array that represents a
quadrant into a 2Nx2M array? Essentially, I am trying to reduce the size of
an expensive calculation by taking advantage of the fact that the first part
of the calculation is just computing gaussian weights, which is radially
symmetric.
It doesn't seem like np.tile() could support this (yet?). Maybe we could
allow negative repetitions to mean "reflected"? But I was hoping there was
some existing function or stride trick that could accomplish what I am
trying.
x = np.linspace(-5, 5, 20)
y = np.linspace(-5, 5, 24)
z = np.hypot(x[None, :], y[:, None])
zz = np.hypot(x[None, :int(len(x)//2)], y[:int(len(y)//2), None])
zz = some_mirroring_trick(zz)
Are you looking for something like this:

zz = np.hypot.outer(y[:len(y)//2], x[:len(x)//2])
zz = np.concatenate((zz[:, ::-1], zz), axis=1)
zz = np.concatenate((zz, zz[::-1, :]))
Post by Benjamin Root
assert np.all(z == zz)
What can be my "some_mirroring_trick()"? I am hoping for something a little
better than using hstack()/vstack().
Thanks,
Ben Root
_______________________________________________
NumPy-Discussion mailing list
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Benjamin Root
2016-03-29 18:02:07 UTC
Permalink
Along those lines, yes, but you have to be careful of even/odd dimension
lengths. Would be nice if it was some sort of stride trick so that I don't
have to allocate a new array twice as we do in the concatenation steps.

Cheers!

Ben Root

On Tue, Mar 29, 2016 at 1:58 PM, Joseph Fox-Rabinovitz <
Post by Joseph Fox-Rabinovitz
Post by Benjamin Root
Is there a quick-n-easy way to reflect a NxM array that represents a
quadrant into a 2Nx2M array? Essentially, I am trying to reduce the size
of
Post by Benjamin Root
an expensive calculation by taking advantage of the fact that the first
part
Post by Benjamin Root
of the calculation is just computing gaussian weights, which is radially
symmetric.
It doesn't seem like np.tile() could support this (yet?). Maybe we could
allow negative repetitions to mean "reflected"? But I was hoping there
was
Post by Benjamin Root
some existing function or stride trick that could accomplish what I am
trying.
x = np.linspace(-5, 5, 20)
y = np.linspace(-5, 5, 24)
z = np.hypot(x[None, :], y[:, None])
zz = np.hypot(x[None, :int(len(x)//2)], y[:int(len(y)//2), None])
zz = some_mirroring_trick(zz)
zz = np.hypot.outer(y[:len(y)//2], x[:len(x)//2])
zz = np.concatenate((zz[:, ::-1], zz), axis=1)
zz = np.concatenate((zz, zz[::-1, :]))
Post by Benjamin Root
assert np.all(z == zz)
What can be my "some_mirroring_trick()"? I am hoping for something a
little
Post by Benjamin Root
better than using hstack()/vstack().
Thanks,
Ben Root
_______________________________________________
NumPy-Discussion mailing list
https://mail.scipy.org/mailman/listinfo/numpy-discussion
_______________________________________________
NumPy-Discussion mailing list
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Joseph Fox-Rabinovitz
2016-03-29 18:17:01 UTC
Permalink
Post by Benjamin Root
Along those lines, yes, but you have to be careful of even/odd dimension
lengths. Would be nice if it was some sort of stride trick so that I don't
have to allocate a new array twice as we do in the concatenation steps.
Cheers!
Ben Root
On Tue, Mar 29, 2016 at 1:58 PM, Joseph Fox-Rabinovitz
Post by Joseph Fox-Rabinovitz
Post by Benjamin Root
Is there a quick-n-easy way to reflect a NxM array that represents a
quadrant into a 2Nx2M array? Essentially, I am trying to reduce the size of
an expensive calculation by taking advantage of the fact that the first part
of the calculation is just computing gaussian weights, which is radially
symmetric.
It doesn't seem like np.tile() could support this (yet?). Maybe we could
allow negative repetitions to mean "reflected"? But I was hoping there was
some existing function or stride trick that could accomplish what I am
trying.
x = np.linspace(-5, 5, 20)
y = np.linspace(-5, 5, 24)
z = np.hypot(x[None, :], y[:, None])
zz = np.hypot(x[None, :int(len(x)//2)], y[:int(len(y)//2), None])
zz = some_mirroring_trick(zz)
zz = np.hypot.outer(y[:len(y)//2], x[:len(x)//2])
zz = np.concatenate((zz[:, ::-1], zz), axis=1)
zz = np.concatenate((zz, zz[::-1, :]))
You can avoid the allocation with preallocation:

nx = len(x) // 2
ny = len(y) // 2
zz = np.zeros((len(y), len(x)))
zz[:ny,-nx:] = np.hypot.outer(y[:ny], x[:nx])
zz[:ny, :nx] = zz[:ny,:-nx-1:-1]
zz[-ny:, :] = zz[ny::-1, :]

if nx * 2 != len(x):
zz[:ny, nx] = y[::-1]
zz[-ny:, nx] = y
if ny * 2 != len(y):
zz[ny, :nx] = x[::-1]
zz[ny, -nx:] = x

All of the steps after the call to `hypot.outer` create views. This is
untested, so you may need to tweak the indices a little.
Post by Benjamin Root
Post by Joseph Fox-Rabinovitz
Post by Benjamin Root
assert np.all(z == zz)
What can be my "some_mirroring_trick()"? I am hoping for something a little
better than using hstack()/vstack().
Thanks,
Ben Root
_______________________________________________
NumPy-Discussion mailing list
https://mail.scipy.org/mailman/listinfo/numpy-discussion
_______________________________________________
NumPy-Discussion mailing list
https://mail.scipy.org/mailman/listinfo/numpy-discussion
_______________________________________________
NumPy-Discussion mailing list
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Peter Creasey
2016-03-29 18:48:02 UTC
Permalink
Post by Joseph Fox-Rabinovitz
Post by Benjamin Root
Is there a quick-n-easy way to reflect a NxM array that represents a
quadrant into a 2Nx2M array? Essentially, I am trying to reduce the size
of
an expensive calculation by taking advantage of the fact that the first
part
of the calculation is just computing gaussian weights, which is radially
symmetric.
It doesn't seem like np.tile() could support this (yet?). Maybe we could
allow negative repetitions to mean "reflected"? But I was hoping there
was
some existing function or stride trick that could accomplish what I am
trying.
x = np.linspace(-5, 5, 20)
y = np.linspace(-5, 5, 24)
z = np.hypot(x[None, :], y[:, None])
zz = np.hypot(x[None, :int(len(x)//2)], y[:int(len(y)//2), None])
zz = some_mirroring_trick(zz)
nx = len(x) // 2
ny = len(y) // 2
zz = np.zeros((len(y), len(x)))
zz[:ny,-nx:] = np.hypot.outer(y[:ny], x[:nx])
zz[:ny, :nx] = zz[:ny,:-nx-1:-1]
zz[-ny:, :] = zz[ny::-1, :]
zz[:ny, nx] = y[::-1]
zz[-ny:, nx] = y
zz[ny, :nx] = x[::-1]
zz[ny, -nx:] = x
All of the steps after the call to `hypot.outer` create views. This is
untested, so you may need to tweak the indices a little.
A couple of months ago I wrote a C-code with ctypes to do this sort of
mirroring trick on an (N,N,N) numpy array of fft weights (where you
can exploit the 48-fold symmetry of using interchangeable axes), which
was pretty useful since I had N^3 >> 1e9 and the weight function was
quite expensive. Obviously the (N,M) case doesn't allow quite so much
optimization but if it could be interesting then PM me.

Best,
Peter

Loading...