Margins in 2D image plot after adding scatterplot point in Matplotlib - python

I am trying to label points on the image, but whenever I do an extra marker on the plots by coordinate values and the margins becomes unnecessarily large. What is the issue here, and is there a way to fix this?
The image is fine. I even plotted it below and everything seems okay when I don't add the plotted point.
imp = plt.imshow(processed[::-1],cmap='gray_r',vmin=1000,vmax=2000)
plt.colorbar()
plt.figure()
imp = plt.imshow(processed[::-1],cmap='gray_r',vmin=1000,vmax=2000)
plt.plot(600,400,'*',color='r')
plt.colorbar()
Large Margin around image generated

Related

Prevent Matplotlib to stretch plot to only bbox of drawing area

Please see below image:
I set the figure size of plt equal to something like (4,6) and set axis to off and margin to zero.
Then continue to draw polyline using coordinate array by ax.plot(line[:,1],line[:,0])
after this I don’t use the plt.show()
But convert the plot to numpy array which has correct (4,6) size but surprisingly fill the plot by stretched to only bbox of the draw line
How can i see all the unused space of figure?
Is there any flag that i have to change in somewhere in matplotlib?
Any help appreciated
The plot of matplotlib will define the output based on shape and size of drawing not based on the pre-defined figure size,some kind of back-end and front-end, or simply it is a responsive-layout when you resize the window everything will scale else those are passed through linewidth= and ...
then i changed my workflow and problem solved ;)

Empty circles with errorbars

How can I make a python plot with empty circles and error bars? I see I can use facecolors='none' for a scatter plot, but it is not working for errorbar plot. I also found mfc='none' which makes the circles empty, but the error bars are still visible inside the circles. How can I make it such that the circles are completely empty, and the error bars come out only from outside of the circles (the errorbars are bigger than the size of the data points)?Thank you!
One option is to plot with mfc the same color with the background color, e.g. mfc='w':
y = [1,2,3,4]
yerr=[.1,.2,.3,.4]
plt.figure(figsize=(10,6))
plt.errorbar(x=y,y=y, yerr=yerr, ms=30, marker='o', mfc='w')
Output:
However, there is a risk as you can see above, when the marker size is larger than the error, you don't get to see the error bars.

Save colorbar for scatter plot separately

I've got scatter plot with colorbar which I save as PNG image. I need the plot to be of a certain figsize but adding colorbar scales original plot.
import pylab as plt
plt.figure(figsize=FIGSIZE)
plt.scatter(X, Y, c=Z, s=marker_size, norm=LogNorm(), vmin=VMIN, vmax=VMAX, cmap=CMAP,rasterized=True,lw=0,)
CB = plt.colorbar(ticks=TICKS, format=FORMAT)
How could I save original plot (with figsize set as above) and colorbar as two separate images?
The obvious answer is "plot your colorbar separately". You need to create a new figure window and plot your colorbar there, in order to prevent your first figure from being distorted. Small example:
import matplotlib.pyplot as plt
import numpy as np # only for dummy data
X,Y = np.mgrid[-2:3,-2:3]
Z = np.random.rand(*X.shape)
FIGSIZE = (2,3)
plt.figure(figsize=FIGSIZE)
mpb = plt.pcolormesh(X,Y,Z,cmap='viridis')
# plot the original without a colorbar
plt.savefig('plot_nocbar.png')
# plot a colorbar into the original to see distortion
plt.colorbar()
plt.savefig('plot_withcbar.png')
# draw a new figure and replot the colorbar there
fig,ax = plt.subplots(figsize=FIGSIZE)
plt.colorbar(mpb,ax=ax)
ax.remove()
plt.savefig('plot_onlycbar.png')
# save the same figure with some approximate autocropping
plt.savefig('plot_onlycbar_tight.png',bbox_inches='tight')
Consider the following four figures that were produced (click to view properly):
The first is a saved version of the figure without a call to colormap. This is fine, this is what you want to preserve. The second figure shows what happens if we call colorbar without any extra fuss: it takes some space from the original figure, and this is what you want to prevent.
You have to open a new figure (and axes) using plt.subplots, with the size of your original figure. This way you can be sure that the produced colorbar will be the same size as if it was drawn in your original figure. In the above setup I let matplotlib determine the size of the colorbar itself; but then afterward we need to delete the auxiliary axes that would pollute the resulting plot. (The other option would be to create a single axes in the new figure manually, with the expected size of the colorbar. I suspect this is not a feasible course of action.)
Now, as you can see in the third plot, the empty space left after the deleted axes is clearly visible in the resulting plot (but the size of the colorbar is perfect, correspondingly). You can either cut this white space off manually in post-production, or use something that autocrops your colorbar image.
I also included a version of the plot wherein matplotlib itself crops most of the figure: the bbox_inches='tight' keyword argument to savefig does exactly this. The upside is that the resulting image file only contains the colorbar (as seen above in the fourth image), but the size of the resulting colorbar will be slightly different from your original. Depending on your specific needs, you'll need to experiment with the available methods to come up with a solution that's most convenient for you.

uneven axis when using pl.imshow

I am having trouble when plotting an image using pylabs imshow. Well there is no problem while plotting but my data is uneven (approx. 32*850) so when I plot it, the y axis is very short compared to the x-axis and you can see an example here example image. I just want the image to be stretched out in the y-axis so it is easier to see.
The code I started with(excluded labels and so on) is:
pl.figure()
pl.imshow(fom_data, interpolation='nearest')
pl.show()
And after googling it I tried changing to
pl.figure(figsize=(6,10))
Which only made the white parts around it larger. I then tried to write it with pyplot instead since it was easier to find people discussing the same thing:
fig, ax = plt.imshow(fom_data,extent=[0,850,0,32],aspect='auto')
plt.show()
As I found in this example: Imshow: extent and aspect but then get the following error message : 'AxesImage' object is not iterable
I am obiusly no pro, but if you know where my brain is going wrong please explain.
Using pyplot:
plt.figure()
plt.imshow(my_image)
plt.axes().set_aspect(aspect="auto") # grab the current axes to set their aspect

Matplotlib - multiple surface plots, wrong overlapping

I am currently plotting two completely different datasets into one 3D surface plot. When I am plotting each one independently, everything works fine. However, as soon as I plot them in one, the visualization is strange. I do the plotting the following way:
fig = plt.figure(figsize=(20,10))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X,Y,Z, color=color, antialiased=True)
(get new X,Y, Z values)
ax.plot_surface(X,Y,Z, color=color, antialiased=True)
ax.view_init(30, 360)
The output is the following:
As you can see, the blue data is correct, but the green one is somehow in the backside and not correctly visualized. If I plot the green one alone, it works perfectly.
Changing the order of plotting (or playing around with zorder) does not change anything.
Hope someone can help!
Matplotlib is just a 2d plotting library. 3d plots are achieved by projecting the 3d surface onto the image plane.
If you have multiple 3d surfaces, it will turn each into a 2d shape, and then calculate a single height for each shape, and show then in that order.
As far as I'm aware, the zorder option doesn't work, and all it would is change the order of the surfaces anyway.
If you're really unlucky, the grey boxes that make up the axis grids can get plotted above your surface too. That's even more annoying.
Of you must use matplotlib, then i guess you could split up your surface into lots of smaller ones, but you're going to encounter a pretty big performance bit doing this, and you'll to override the values in the legend too.

Categories