I would like to plot some coordinates on top of an image.
I want to invert the axis for the said coordinates but not for the image.
But with my code, the axis gets inverted for both the image and the coordinates.
This is my code:
import numpy as np
from matplotlib import pyplot as plt
plt.rcParams["figure.figsize"] = [10, 10]
plt.rcParams["figure.autolayout"] = True
im = plt.imread("bird.png")
fig, ax = plt.subplots()
im = ax.imshow(im, extent=[0, 720, 0, 576])
x = np.array(range(300))
fig.gca().invert_xaxis()
fig.gca().invert_yaxis()
ax.scatter(x_coords_true, y_coords_true, color='red')
ax.scatter(x_coords_pred, y_coords_pred, color='yellow')
plt.show()
Can you help me modify the code to get the result I am expecting, please?
Related
I'm trying to center yaxis tick marks on an imshow image similar to the one here. In the image, each row is a separate "profile" that I've stacked together. I want the tick location to be at the center of each horizontal section, like this (made in Powerpoint).
Here's some working code to make the images above:
import numpy as np
import matplotlib.pyplot as plt
td = [0,1,2,5,10,15,25,66]
N = len(td)
profiles = np.random.randn(N, 501).cumsum(axis=1)
fig, ax = plt.subplots(1,1)
ax.imshow(profiles, interpolation='none', aspect='auto', extent=[0, 500, N-1, 0])
ax.set_yticks(range(N))
plt.show()
Is there an easy way to do this? Let me know how I can clarify my question. If possible, I'd like to learn how to do this with matplotlib.axes (i.e., fig, ax = plt.subplots(1,1)...). Thanks!
You can manually set y ticks and tick labels at 0.5, 1.5 etc. (matplotlib 3.5.0 or above to do this in one call to set_ylabel):
import numpy as np
import matplotlib.pyplot as plt
td = [0,1,2,5,10,15,25,66]
N = len(td)
profiles = np.random.randn(N, 501).cumsum(axis=1)
fig, ax = plt.subplots()
ax.imshow(profiles, interpolation='none', aspect='auto', extent=[0, 500, N, 0])
ax.set_yticks(np.arange(N) + 0.5, [f'{y}' for y in td])
I know I can change the color using fig.patch.set_facecolor("#ccdece") but how do I have an image instead of a solid color? Like using img = plt.imread() and ax.imshow(img) but for the outer border.
Any help is welcome.
You can create a dummy ax for the full size of the surrounding figure and add an image to that ax. Giving the ax a low enough zorder makes sure it appears behind the actual plots.
For an additional effect, the facecolor of the actual plots can be made semi-transparent.
Here is an example starting from a stock image.
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import numpy as np
imageFile = cbook.get_sample_data('ada.png')
image = plt.imread(imageFile)
fig, ax = plt.subplots(figsize=(6, 8))
bg_ax = fig.add_axes([0, 0, 1, 1], zorder=-1)
bg_ax.axis('off')
bg_ax.imshow(image)
t = np.linspace(0, 4 * np.pi, 200)
x = 2 * np.cos(t / 2)
y = np.sin(t)
ax.plot(x, y)
ax.set_facecolor('#FFFFFFEE')
plt.show()
Consider the following:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
y = np.array([1, 4, 3, 2, 7, 11])
colors = cm.hsv(y / float(max(y)))
plot = plt.scatter(y, y, c = y, cmap = 'hsv')
plt.clf()
plt.colorbar(plot)
plt.bar(range(len(y)), y, color = colors)
plt.show()
I want to colormap legend to appear on the top right of the graph (much smaller of course). My image at the moment looks rather clunky as the colormap is clashing somewhat with the actual bars.
Thanks.
Following this answer:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
y = np.array([1, 4, 3, 2, 7, 11])
colors = cm.hsv(y / float(max(y)))
fig, ax = plt.subplots()
plot = ax.scatter(y, y, c = y, cmap = 'hsv')
plt.cla()
ax.bar(range(len(y)), y, color = colors)
cbaxes = inset_axes(ax, width="30%", height="3%", loc=2)
plt.colorbar(plot, cax=cbaxes, orientation='horizontal', ticks=[0,2,4,6,8,10])
I use plt.subplots to easily reference the Axes (ax). You can move the color bar and change its size by editing the last 2 lines (for instance changing loc can set which corner you want the colorbar to be in).
I'm plotting histograms below the images using a Matplotlib.GridSpec as we can see on code below:
import imageio
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec
plt.close('all')
plt.style.use('ggplot')
img = imageio.imread('imageio:page.png')
y = np.bincount(img.ravel(), minlength=256)
y = y/np.sum(y)
x = np.arange(len(y))
fig = plt.figure(figsize=(6,8))
gs = gridspec.GridSpec(2, 1, height_ratios=[6,1], width_ratios=[1])
ax0 = plt.subplot(gs[0])
ax0.imshow(img, cmap='gray')
ax0.xaxis.set_visible(False)
ax0.yaxis.set_visible(False)
ax1 = plt.subplot(gs[1])
ax1.fill_between(x, y)
ax1.yaxis.set_visible(False)
ax1.set_xlim([0,255])
fig.tight_layout()
plt.show()
When we pick the correct figure size the image is nicely aligned as in
But if the figure size isn't correctly chosen the histogram is shown too large for image size or too far away as we can see below
or
Is there any way to tell matplotlib to align correctly, that is, put the histogram a fixed amount of pixels below the image and never stretch the histogram larger than image width.
The following code generates a matrix plot that every square of it indexed in the middle with a number from 1 to 39:
import numpy as np
from matplotlib import pyplot as plt
a=np.random.uniform(0,1,1600).reshape((40,40))
fig, ax = plt.subplots(1,1)
ax.matshow(a, vmin = 0, vmax = 1, interpolation = 'none')
label_list=np.arange(0,40,5)
label_list=np.append(label_list,39)
ax.set_xticks(label_list)
ax.set_yticks(label_list)
plt.show()
When I want to change the numbers to be between 0 and 1.95 or basically [0,39]*0.05 the labels shrink to the beginning of axes. If I try to use extent in matshow then the labels don't point to the middle of squares! How can I make this float indices to point to the middle of squares?
import numpy as np
from matplotlib import pyplot as plt
a=np.random.uniform(0,1,1600).reshape((40,40))
fig, ax = plt.subplots(1,1)
ax.matshow(a, vmin = 0, vmax = 1, interpolation = 'none')
tick_list = np.append(np.arange(0,40,5), 39)
label_list=map(lambda x: str(0.05*x), tick_list)
ax.set_xticks(tick_list)
ax.set_xticklabels(label_list)
ax.set_yticks(tick_list)
ax.set_yticklabels(label_list)
plt.show()