I have a large number of diagrams (all of the same size) which I want to display in a single file.
So I used something like
fig, ax = plt.subplots(100)
for i in range (0,99):
ax[i] = draw_my_diagram(i)
The problem that I have, is that the plotted diagrams get really small if i do it in this way. But I want to keep their original size.
I tried to set their figsize manually to the value what I thought I needed them to be, but this messed up the plot. In particular, I drew some patches in the plot, which were not in the desired position and shape anymore.
So what would be the best way to solve this? Maybe there is even a flag that I can set to just keep the original size of the subplots?
Related
I have been using Cartopy to plot data using 'equal' aspect, resulting in all manner of non-square Axes sizes. These usually look OK in Jupyter notebooks, but when saving the images (or when doing more complicated operations like adding colorbars), the resulting Figures are often huge, with a lot of blank space around the Axes plotting area. They also look bad when using %matplotlib widget. An example is provided below.
It seems that the figure in this case is too big in at least one dimension. I would like to remove that extra space in the final output figure, without shrinking the size of the plotting area itself.
I know that I can adjust the figure size itself with .set_figwidth and .set_figheight, as well as setting figsize= upon creation. But I don't know how to figure out the correct dimensions to shrink the figure without shrinking the axes, and I haven't seen any way to do this automatically. What's the correct solution? I would like to avoid manually editing my images after creating them!
Is there any way to decrease the density of data labels in Matplotlib? Right now, it looks like this.
This is my code :
countries_list.insert(0, "(0,0)")
arrowprops = dict(arrowstyle='<-', color='blue', linewidth=1, mutation_scale=10)
for i, txt in enumerate(countries_list):
ax.annotate(string.capwords(txt), (x_list[i], y_list[i]), arrowprops = arrowprops)
Thanks.
Edit: I'm thinking more on the side of like is there maybe an automatic option to automatically rearrange the arrows the point to different locations around the plot to make the labels more readable?
so I don't think there is really much you can do as far as adjusting the text size, since you would need to make it a tiny unreadable font to have each word be separate. I think what you are going to want to do is change the scale of your y axis. Right now you have a linear scale on your y axis with a very nonlinear distribution of your data, hence why you have a ton of data points squished near the bottom.
For your x axis set it with something like the following:
ax.set_yscale('log')
check out more about axes and scaling on their website:
enter link description here
Also just found this, which will probably produce a much nicer looking plot than log scaling, especially since I dont know what kind of distribution we are looking at with your data.
enter link description here
You can use that to scale your y axis relative to your dataset and extreme values.
My program can generate up to 2000000 points within 5 seconds, so I don't have a problem with speed. Right now I am using matplotlib.pyplot.scatter to scatter all my points on my graph. For s=1, it gives me small circles, but not small enough, because it does not show the intricate patterns. When I use s=0.1, it gives me this weird marker shape:
Which makes the marker larger despite me making the size smaller. I have searched all over the internet including stack overflow, but they do not tell how to minimize the size further. Unfortunately, I have to show all the points, and cannot just show a random sample of them.
I have come to the conclusion that matplotlib is made for a small sample of points and not meant for plotting millions of points. However, if it is possible to make the size smaller please let me know.
Anyway, for my points, I have all the x values in order in one array, and all the y values in order in another array. Could someone suggest a graphing package in python I could use to graph all the points in a way that the size would be very small since when I plot the points now it just becomes one big block of color instead of intricate designs forming in the shape as they should be.
Thanks for any help in advance!
EDIT: My code that I am using to scatter the points is:
plt.savefig(rootDir+"b"+str(Nvertices)+"_"+str(xscale)+"_"+str(yscale)+"_"+str(phi)+"_"+str(psi)+"_"+CurrentRun+"_color.png", dpi =600)
EDIT: I got my answer, I added linewidths = 0 and that significantly reduced the size of the points, giving me what I needed.
Perhaps you can try making the linewidths as 0 i.e., the line width of the marker edges. Notice the difference in the two plots below
fig, ax = plt.subplots(figsize=(6, 4))
plt.scatter(np.random.rand(100000), np.random.rand(100000), s=0.1)
fig, ax = plt.subplots(figsize=(6, 4))
plt.scatter(np.random.rand(100000), np.random.rand(100000), s=0.1, linewidths=0)
you can set the marker to a single pixel using marker=',' in your call to scatter.
See the markers documentation here
I have a set of PDF that I need to plot for a certain section of the PDF domain. However, when I plot my lines on a 3d plot I get tails for each PDF,
Is there a clean way to not plot the tails that happen outside my plot limits? I know I can change the data to NaNs to achieve the same effect but I want to do this in matplotlib. Here is my current workaround code,
`# trim the data
y = np.ones(PDF_x.shape)*PDF_x
y[y>95]= np.nan
y[y<75]= np.nan
# plot the data
fig = plt.figure()
ax = fig.gca(projection='3d')
for i in range(PDF_capacity.shape[1]):
ax.plot(life[i]*np.ones((PDF_x.shape)),y,PDF_capacity[:,i], label='parametric curve')
# set the axis limits
ax.set_ylim(75,95)
# add axis labels
ax.set_xlabel('charge cycles to failure point of 75% capacity')
ax.set_ylabel('capacity at 100 charge cycles')
ax.set_zlabel('probability')`
After trimming I can make the following plot,
Masking the data with nan in the way you're doing it is a good and practical solution.
Since matplotlib 3D plots are projections into 2D space, it would be hard to implement automatic clipping. While I do think it would be possible, I'm not convinced that it's worth the effort. First, because you would need to treat different kinds of plots differently, second, because at least in some cases it would probably turn out that masking the data is still the best choice. Now, doing a complex subclassing of the plotting objects just to do the same thing that can be manually done in one or two lines is probably overkill.
My clear recommendation would therefore be to use the solution you already have. Especially since it does not seem to have any drawbacks so far.
How can I save Python plots at very high quality?
That is, when I keep zooming in on the object saved in a PDF file, why isn't there any blurring?
Also, what would be the best mode to save it in?
png, eps? Or some other? I can't do pdf, because there is a hidden number that happens that mess with Latexmk compilation.
If you are using Matplotlib and are trying to get good figures in a LaTeX document, save as an EPS. Specifically, try something like this after running the commands to plot the image:
plt.savefig('destination_path.eps', format='eps')
I have found that EPS files work best and the dpi parameter is what really makes them look good in a document.
To specify the orientation of the figure before saving, simply call the following before the plt.savefig call, but after creating the plot (assuming you have plotted using an axes with the name ax):
ax.view_init(elev=elevation_angle, azim=azimuthal_angle)
Where elevation_angle is a number (in degrees) specifying the polar angle (down from vertical z axis) and the azimuthal_angle specifies the azimuthal angle (around the z axis).
I find that it is easiest to determine these values by first plotting the image and then rotating it and watching the current values of the angles appear towards the bottom of the window just below the actual plot. Keep in mind that the x, y, z, positions appear by default, but they are replaced with the two angles when you start to click+drag+rotate the image.
Just to add my results, also using Matplotlib.
.eps made all my text bold and removed transparency. .svg gave me high-resolution pictures that actually looked like my graph.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
# Do the plot code
fig.savefig('myimage.svg', format='svg', dpi=1200)
I used 1200 dpi because a lot of scientific journals require images in 1200 / 600 / 300 dpi, depending on what the image is of. Convert to desired dpi and format in GIMP or Inkscape.
Obviously the dpi doesn't matter since .svg are vector graphics and have "infinite resolution".
You can save to a figure that is 1920x1080 (or 1080p) using:
fig = plt.figure(figsize=(19.20,10.80))
You can also go much higher or lower. The above solutions work well for printing, but these days you want the created image to go into a PNG/JPG or appear in a wide screen format.
Okay, I found spencerlyon2's answer working. However, in case anybody would find himself/herself not knowing what to do with that one line, I had to do it this way:
beingsaved = plt.figure()
# Some scatter plots
plt.scatter(X_1_x, X_1_y)
plt.scatter(X_2_x, X_2_y)
beingsaved.savefig('destination_path.eps', format='eps', dpi=1000)
In case you are working with seaborn plots, instead of Matplotlib, you can save a .png image like this:
Let's suppose you have a matrix object (either Pandas or NumPy), and you want to take a heatmap:
import seaborn as sb
image = sb.heatmap(matrix) # This gets you the heatmap
image.figure.savefig("C:/Your/Path/ ... /your_image.png") # This saves it
This code is compatible with the latest version of Seaborn. Other code around Stack Overflow worked only for previous versions.
Another way I like is this. I set the size of the next image as follows:
plt.subplots(figsize=(15,15))
And then later I plot the output in the console, from which I can copy-paste it where I want. (Since Seaborn is built on top of Matplotlib, there will not be any problem.)