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
Related
I have begun using matplotlib and I am somewhat confused as to why figures exist. Sometimes I see code where a figure is declared and then a plot is made, and sometimes I see things like this:
import numpy as np
import matplotlib.pyplot as plt
data = np.loadtxt('initial.dat','float')
plt.plot(data[:,0], data[:,1])
plt.xlabel("x (Angstroms)")
plt.ylabel("V (eV)")
plt.savefig('v.png',bbox_inches='tight')
plt.clf()
I read the documentation on figure and plot, but I don't get it. Why do figures exist?
A figure will always exist once you create some plot with matplotlib.
The introductory matplotlib page may help here:
The whole figure. The figure keeps track of all the child Axes, a smattering of ‘special’ artists (titles, figure legends, etc), and the canvas. (Don’t worry too much about the canvas, it is crucial as it is the object that actually does the drawing to get you your plot, but as the user it is more-or-less invisible to you). A figure can have any number of Axes, but to be useful should have at least one.
You can imagine the figure to be the white sheet of paper you draw a plot on. A figure has some size, maybe a background and most importantly it is the container for everything you draw into it. In most cases this will be one or more axes. If there wasn't any figure, there wouldn't be any sheet of paper to draw your plot to (you cannot draw a line in the air).
Even if you haven't explicitely created the figure, it is automatically created in the background.
import matplotlib.pyplot as plt
plt.plot([1,2,3])
# at this point we already have a figure, because the plot needs to live somewhere
# we can get a handle to the figure via
figure = plt.gcf()
Examples of when you explicitely need a figure:
If you want to create a second figure.
plt.plot([1,2,3])
plt.figure(2)
plt.plot([2,4,6])
If you want to set the figure size or other figure parameters.
plt.figure(figsize=(5,4), dpi=72)
If you want to change the padding of the subplot(s).
fig, ax=plt.subplots()
fig.subplots_adjust(bottom=0.2)
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.
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
I want to make a figure which has similar axis to the example below. I know I could use loglog plot. But in this example, the step-size (x-axis) decreases when you go farther to the right.
How could I do this in python (using matplotlib)
Possibly the invert_xaxis call is what you are looking for. As follows:
fig = plt.figure()
ax = fig.add_axes()
ax.invert_xaxis()
Link: http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes
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.