Resizing imshow heatmap into a given image size in matplotlib - python

I'm using matplotlib for plotting, and I have the following matrix, Mat which I would like to plot into a heatmap.
Mat.shape
which yields (20,20).
I use the following code to plot it into a heatmap, following the this.
plt.imshow(Mat, cmap='Reds', interpolation='nearest')
plt.show()
But I have to resize this heatmap into 1600 x 1200(x,y) size, since, I want it to be overlapped with the image, img. The code is as follows.
plt.imshow(img, alpha=.5) # for image
plt.xlim(0, 1600)
plt.ylim(1200, 0)
plt.axis('off')
plt.imshow(Mat, cmap='Reds', interpolation='nearest', alpha=.5) # for heatmap to overlap
plt.show()
For some reason I would not like to change the size of img.
My try
I tried to resize at the level of plt.imshow(Mat), which I found hard. The only option I see at present is to resize Mat into 1600 x 1200 matrix with redundancy. Anyone to give me some efficient solution?

Use the extent= parameter of imshow to scale your matrix to the image's scale (more information here as well).
plt.figure()
img = plt.imread('stinkbug.png')
plt.imshow(img, alpha=1) # for image
#plt.axis('off')
xmin, xmax = plt.xlim()
ymin, ymax = plt.ylim()
Mat = np.random.normal(size=(20,20))
plt.imshow(Mat, cmap='Reds', interpolation='nearest', alpha=.5, extent=(xmin,xmax,ymin,ymax)) # for heatmap to overlap
plt.show()

Related

Matplotlib: How to imshow an image using semilog y axis without stretching the underlying image?

I have an image which already has semilogarithmic scale in the y axis:
I would like to imshow this in matplotlib such that I can plot stuff over it. Here's the approach I took:
image = Image.open("cropped.jpg")
fig = plt.figure()
ax = plt.gca()
ax.imshow(image, extent=(0, 6, 1, 400), aspect="auto")
ax.set_yscale('log')
Unfortunately, this stretches my data and I end up with the following:
How can I preserve the underlying data but still readjust the scale to semilog?

Plotting 2d histogram of data with very different ranges in Python

I try to plot a 2d histogram of data with very different ranges using the following code. However, because of the different data ranges, the x data overlaps like the following figure. Is there any solution that plots x and y data with the same axis length?
import numpy as np
from matplotlib import pyplot as plt
plt.clf()
x = np.random.randint(low=0, high=10, size=8873)
y = np.random.randint(low=100000,high=600000, size=8873)
heatmap, xedges, yedges = np.histogram2d(x, y, bins=50)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
plt.imshow(heatmap.T, extent=extent, origin='lower')
plt.show()
Note that imshow() sets the aspect to 1 by default, changing it to auto should solve your problem. You can also calculate your own aspect based on extent to get for example a square image.
aspect = (extent[1] - extent[0]) / (extent[3] - extent[2])
plt.imshow(heatmap.T, extent=extent, origin='lower', aspect=aspect)
# plt.imshow(heatmap.T, extent=extent, origin='lower', aspect='auto')

Make a heatmap whit 2d points and 2 images

Good day to all,
I am trying to create a heatmap, given a set of x, y coordinate pairs extracted from a CSV file. I am using numpy.histogram2d to plot it, the heatmap gives me correct, but I need to overlay it on another image. I share my code
Here is the CSV
csv = pd.read_csv("../test2.csv")
#Gets the centroid of the coords
csv["x"] = (combined_csv["x_min"]+(combined_csv["x_max"]-combined_csv["x_min"])/2).astype(int)
csv["y"] = (combined_csv["y_min"]+(combined_csv["y_max"]-combined_csv["y_min"])/2).astype(int)
am = csv[(csv["tracking_id"] != 7) &(csv["tracking_id"] != 28)] #Some filters
#Taken from another question
def myplot(x, y, s, bins=1000):
heatmap, xedges, yedges = np.histogram2d(x, y, bins=bins, range=[[0, 960], [0, 480]])
heatmap = gaussian_filter(heatmap, sigma=s)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
return heatmap.T, extent
img, extent = myplot(am["x"], am["y_max"], 16,200)
plt.imshow(img, extent=extent, origin='upper', cmap=cm.jet)
The previous code gives me this image
I put the range between 0 and 480 for x and 0 and 960 for y, because the target image has that size, but doing this, histogram2d returns me the histogram matrix h, which is 200x200, then I use matplotlib to plot it and This graphs me correctly in the range 0-480 for x and 0-960 for y, what I need is to save said image, preserving as much information as possible in the 480x960 pixel size, and then add it with the target image using this tutorial how to superimpose heatmap on a base image?
final_img = cv2.addWeighted (heatmap_img, 0.5, image, 0.5, 0)
For creating something like this
But the image and the histogram doesnt match in the sizes that i wanted.
This is the target image
Ok, so i fix the error by the next code, printing the two images at the same plot
base_image = image
sigma = 8
fig, ax = plt.subplots(1, 1, figsize = (20, 16))
heatmap, xedges, yedges = np.histogram2d(am["x"], am["y"], bins=200, range=[[0,960],[0,480]])
heatmap = gaussian_filter(heatmap, sigma=sigma)
extent = [xedges[0], xedges[-1], yedges[-1], yedges[0]]
img = heatmap.T
ax.imshow(img, extent=extent, cmap=cm.jet)
ax.imshow(base_image, alpha = 0.5)
ax.set_xlim(0, 960)
ax.set_ylim(480,0)
ax.axes.get_yaxis().set_visible(False)
ax.axes.get_xaxis().set_visible(False)
plt.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
plt.savefig("heatmap_final.png", bbox_inches='tight')
plt.show()
plt.close(fig)

Over-plot an equation curve over a png image

enter image description hereI'm having trouble overplotting a relation between radial velocity and offset(position). I've looked at various solutions, but it doesn't seem to work. I've converted the equation into numbers, with only one variable.It also doesn't display the picture to the required dimensions.
x = np.linspace(-0.8 ,0.8 , 1000)
y = 0.5*((1.334e+20/x)**0.5)
img = plt.imread('Pictures/PVdiagram1casaviewer.png')
fig, ax = plt.subplots(figsize=(16, 16), tight_layout=True)
ax.set_xlabel('Offset(arcsec)', fontsize=14)
ax.set_ylabel('Radial Velocity (Km/S)', fontsize=14)
ax.imshow(img, extent=[-0.8, 0.8, -5, 15])
ax.plot(x, y, linewidth=5, color='white')
plt.title('PV Diagram')
plt.show()
enter image description here
If I plot your image, you can see that the axis of the image and matplotlib don't match, because the image contains space between the plot and border of the pictures (axis titles, and so on...)
So, first you need to crop the image, so that it contains just the plot area.
Next, you can plot the image with the argument aspect=auto to scale it to your figsize:
ax.imshow(img, extent=[-0.8,0.8,-5,15], aspect='auto')
If you try to plot your y function over the image, you will see that the values of y are much larger, so the curve is above the image (notice the tiny image is at the bottom).
I don't know what the physical background of y is, but if you divide it by 10e9 it fits inside the image-range.
Full code:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-0.8 ,0.8 , 1000)
y = 0.5*((1.334e+20/x)**0.5)/10e9 # Scale it here... but how?
img = plt.imread('hNMw82.png')
fig, ax = plt.subplots(figsize=(16, 16), tight_layout=True)
ax.set_xlabel('Offset(arcsec)', fontsize=14)
ax.set_ylabel('Radial Velocity (Km/S)', fontsize=14)
ax.imshow(img, extent=[-0.8,0.8,-5,15], aspect='auto')
ax.plot(x, y, linewidth=5, color='white')
ax.set_ylim([-5,15])
ax.set_xlim([-0.8,0.8])
plt.title('PV Diagram')
plt.show()
Result:
(I also set the axis limits.)

Add image behind scatter subplot independent of scatter points axes

I am trying to add an image behind each subplot of my scatter plot figure. I want my image to take up all the subplot space. But I do not want to map my scatter points onto the image: That is, I want the axes of my scatter points to be independent to that of the image.
When I simply use imread() and implot() while making a subplot to insert the image, like so:
im = plt.imread("/Users/mac/Desktop/image.jpeg")
two = plt.subplot(222)
implot = plt.imshow(im)
plt.title('4-8 Hz')
plt.scatter(X,Y, s=100, marker ='o', c=AveragedHursts4to8, cmap = cm.plasma)
plt.colorbar()
two.axis('off')
I get the right-most image down below, where, clearly, the image axes and scatter points axes are shared.
I tried to use the twiny() function to make a new set of axes for the image, with the image set as the first axes and the second axes set to the scatter points, like so:
onetwin = plt.subplot(221)
plt.title('1-4 Hz')
implot = plt.imshow(im, zorder=1)
onetwin.axis('off')
one = onetwin.twiny()
plt.scatter(X,Y, s=100, marker ='o', c=AveragedHursts1to4, cmap = cm.plasma, zorder = 2)
plt.colorbar()
one.axis('off')
There I get the leftmost image, where the scatter points are squished on the y axis and the image, for some reason, has been shrunk.
And when I switch the ordering of the creation of the axes for twiny, the image takes up the whole subplot and the scatter points do not show at all.
Suggestions?
My suggestion would be to leave the points' positions untouched and scale the background image accordingly. One can use the extent keyword to imshow for that purpose.
In the example below I plot some random points on four different scales. Each time the image is scaled to the scatterplot's dimensions using the extent keyword.
import matplotlib.pyplot as plt
import numpy as np
x = np.random.rand(8*8).reshape((8,8))
image = plt.imread("https://upload.wikimedia.org/wikipedia/en/2/27/EU_flag_square.PNG")
fig, ax = plt.subplots(ncols=4, figsize=(11,3.8))
for i in range(len(ax)):
ax[i].scatter(x[2*i,:]*10**(i-1), x[2*i+1,:]*10**(i-1), c="#ffcc00", marker="*", s=280, edgecolors='none')
xlim = ax[i].get_xlim()
ylim = ax[i].get_ylim()
mini = min(xlim[0],ylim[0])
maxi = max(xlim[1],ylim[1])
ax[i].imshow(image, extent=[mini, maxi, mini, maxi])
plt.tight_layout()
plt.show()
The simplest, fastest solution I came up with is to solve for x and y in:
largest_x_coodinate_value(x) = x_dimension of image_in_pixels
largest_y_coordinate_value(y) = y_dimension_of_image_in_pixels
And then do vectorized multiplication over the numpy arrays containing the X and Y coordinates with those calculated x,y values, effectively scaling the coordinates to the size of the image.

Categories

Resources