Remeshes 2D data to a larger 2D mesh at a given coordinate in Python
I have a square two-dimensional array
data
, and I want to add it to a larger two-dimensional array frame
, in a given set of non-integer coordinates coords
. The idea is that data
will be interpolated onto the frame
, with its center at the new coordinates.
Some toy data:
# A gaussian to add to the frame
x, y = np.meshgrid(np.linspace(-1,1,10), np.linspace(-1,1,10))
data = 50*np.exp(-np.sqrt(x**2+y**2)**2)
# The frame to add the gaussian to
frame = np.random.normal(size=(100,50))
# The desired (x,y) location of the gaussian center on the new frame
coords = 23.4, 22.6
It’s an idea. I would like to add this :
To this end:
Get this:
If the coordinates are integers (indexes), I can of course simply add them like this :
frame[23:33,22:32] += data
But I would like to be able to specify non-integer coordinates so that data
is remeshed and added to the frame
.
I have studied PIL. Image
method, but my use case only applies to 2D data, not images. Is there a way to do this with just scipy
? Can this be done with interp2d
or something similar? Any guidance would be appreciated!
Solution
Scipy’s The
function in shift scipy.ndimage.interpolation
is what you’re looking for, as long as the
grid spacing between data and frame
overlaps. If not, check out the other answers. The shift
function can take float as input and spline interpolate. First, I put the data into an array as large as a frame, then shift, then add. Make sure to reverse the coordinate list because x
is the rightmost dimension in the numpy
array. A nice feature of shift is that it sets those values that are out of range to zero.
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage.interpolation import shift
# A gaussian to add to the frame.
x, y = np.meshgrid(np.linspace(-1,1,10), np.linspace(-1,1,10))
data = 50*np.exp(-np.sqrt(x**2+y**2)**2)
# The frame to add the gaussian to
frame = np.random.normal(size=(100,50))
x_frame = np.arange(50)
y_frame = np.arange(100)
# The desired (x,y) location of the gaussian center on the new frame.
coords = np.array([23.4, 22.6])
# First, create a frame as large as the frame.
data_large = np.zeros(frame.shape)
data_large[:data.shape[0], :data.shape[1]] = data[:,:]
# Subtract half the distance as the bottom left is at 0,0 instead of the center.
# The shift of 4.5 is because data is 10 points wide.
# Reverse the coords array as x is the last coordinate.
coords_shift = -4.5
data_large = shift(data_large, coords[::-1] + coords_shift)
frame += data_large
# Plot the result and add lines to indicate to coordinates
plt.figure()
plt.pcolormesh(x_frame, y_frame, frame, cmap=plt.cm.jet)
plt.axhline(coords[1], color='w')
plt.axvline(coords[0], color='w')
plt.colorbar()
plt.gca().invert_yaxis()
plt.show()
The script gives you the following image with the desired coordinates indicated by a white dashed line.