Hide coordinates in matplotlib - python

I am currently trying to hide the coordinates in a grid in matplotlib (see code below). Unfortunately no matter which way I try it only the bottom right position gets hidden. All other coordinates/axes are still being displayed. Would be wonderful if someone could help me with that since I do not know what else to try right now.
import matplotlib.pyplot as plt
from PIL import Image
fig,ax = plt.subplots(6,7)
plt.axis('off')
filenames=['gelb.png'.format(i) for i in range(42)]
for i in range(42):
#plt.axis('off')
with open(filenames[i],'rb') as f:
image=Image.open(f)
ax[i%6][i//6].imshow(image)
fig.show()

Related

Image hidden from a matplotlib plot when shifted

I lose my image from a subplot when I shift the image.
(The code is run in Jupyter Lab):
from mpl_toolkits.axes_grid1 import host_subplot
from mpl_toolkits import axisartist
hostImage = host_subplot(221, axes_class=axisartist.Axes)
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
import matplotlib.image as mpimg
test_image = mpimg.imread('testImage.png')
imagebox = OffsetImage(test_image, zoom=1)
ab = AnnotationBbox(imagebox, (-0.0014, 0), box_alignment=(1, 0))
hostImage.add_artist(ab)
The image can still be seen with the above configuration.
Next, when I change parameters the image vanishes:
Shifting the image to the left changing line 7
ab = AnnotationBbox(imagebox, (-0.0025, 0), box_alignment=(1, 0))
to
ab = AnnotationBbox(imagebox, (-0.5, 0), box_alignment=(1, 0))
Changing the matrix layout of the subplots changing line
hostImage = host_subplot(221, axes_class=axisartist.Axes)
to
hostImage = host_subplot(111, axes_class=axisartist.Axes)
-> How can I show everything I add to a subplot (more or less) regardless how far off it may be from the axes 'central part' (the area spanned by the two axes, 'axes' in the sense of a plot)?
Using the plt.tight_layout() method did not help.
Here is the test image I used (the red rhomboid).
%%%%%%%%%%%
To make it clearer what I really want to achieve (practical background of the question):
I have line plots showing measurement data of about 30 sensors which are positioned in the real world in a rather geometrically complex 3D measurement setup. The position of the sensors is essential for anybody trying to understand the chart. So the image serves as a kind of 3D legend for the chart. In a single plot I show data of about 5-6 sensors (more sensors in single chart would make it unreadable).
See this real example (work in progress where I stopped to post my question):
image of the real case
This example I established by creating a second subplot below the subplot with the curves. This second suplot has hidden axes (in the sense of plural of axis). It already is a workable solution and my current baseline.
By the way, for this reason I want the image to be rather below the plot in order not to 'waste' horizontal space for the chart where I plot curves.
So the '3D image legend' is integral part of the finally exported 'all-in-one' plot (.png)
The .pngs go into my written report which is my ultimate goal.
In the report I could also add each image corresponding to a plot by hand, but having all info (plot and image) included in one-in-all matplotlib figures makes it more convenient to establish the report and also less error-prone (pairing wrong images and plots, since I have many sensors and many configurations thus creating quite a number of such plots).
What triggered my question beyond my above solution already established:
I want to finally place labels (matplotlib annotations) as 'overlay' on the image with the sensor names on top of the image.
And then connect these labels via arrow lines with the corresponding curves of the plot. This would make it very clear and convenient to the reader to understand which plot curve corresponds to which sensor position in the image -> kind of '3D legend'.
I had found ConnectionPatch as a solution for drawing lines between subplots but I got an error message which I ultimately did not want to try to resolve but choose the approach:
Have the image as part of the very same subplot of the curves because connecting labels within a subplot is easy (actually you can see in the image I uploaded already such sensor name labels placed along the right y-axis).
Why do I use host_subplot?
I have up to five y-axes in my plot (I am aware that this high number of y-axis may be questionable but it is please not what I want to discuss in this post) and I understood having more than 2 additional y-axis is possible only with host_subplot using .twinx().
P.S.:
After all I think I should for now lower my high expectations and stick with my workable solution of two subplots and just renounce on the possibility of connecting labels in the second subplot with curves in the first subplot.
Matplotlib 3.5 (or presumably better)
If you are using Matplotlib 3.5 (or presumably better), this works for what you want, I think (or close):
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as axisartist
hostImage = host_subplot(221, axes_class=axisartist.Axes)
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
import matplotlib.image as mpimg
test_image = mpimg.imread('testImage.png')
imagebox = OffsetImage(test_image, zoom=1)
ab = AnnotationBbox(imagebox, (-0.0025, 0), box_alignment=(1, 0))
hostImage.add_artist(ab)
hostImage.figure.subplots_adjust(left=0.69) # based on https://matplotlib.org/stable/tutorials/intermediate/tight_layout_guide.html saying how to manually adjust
hostImage.figure.set_size_inches((18, 10)) # from https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/figure.py; also see drevicko's comment https://stackoverflow.com/a/638443/8508004
hostImage.figure.savefig("my_image_test.png") # fix for `hostImage.savefig("my_image_test.png")`, based on https://forum.freecodecamp.org/t/attribute-error-axessubplot-object-has-no-attribute-savefig/46025
This will show the same view of the produced plot in both the direct in JupyterLab output and in the image file produced. (The actual size will probably be slightly different, with the image file displaying better resolution.) **If you don't want to produce an image file, then you can remove the last two lines and just include the adjustment **,figure.subplots_adjust(left=0.69) , to account for the Annotation box being added.
I put pertinent sources in the comments for each line.
My test image was wide and short so you may need to adjust figure.subplots_adjust(left=0.69) to what works for you. (Now I don't like that I had to stumble around trying very high and low versions of the left value for figure.subplots_adjust(), and then hone in on a just-right setting but it worked. I will say that usually I set the figure size before making the subplots, such as here, and maybe doing it that way makes it seem less experimenting is necessary to get it working. But the fact the manual adjustment is mentioned in discussion of tight_layout in Matplotlib's documentation, in regards to elements going outside the figure area, makes me think it happens that you need to do some adjusting now and then.)
Here I use hostImage.figure.set_size_inches((18, 10)). Maybe you don't need yours as wide?
Code for checking Matplotlib version:
import matplotlib
print (matplotlib.__version__ )
Matplotlib versions prior to 3.5 (or maybe specifically 3.2.1?)
The code above wasn't working with Matplotlib 3.2.1 with all else the same. (In launches of Jupyter sessions served via MyBinder from here before running %pip install matplotlib --upgrade in a cell and restarting the kernel.) The image produced was good but the output directly in the Jupyter notebook was cutoff and only showing a fragment.
This code block below works for what you want, I think (or close), if using Matplotlib 3.2.1. Since I couldn't get the direct output in the Jupyter cell where I was using Matplotplib 3.2.1 to display correctly, this just displays the plot from the associated image file produced.
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as axisartist
hostImage = host_subplot(221, axes_class=axisartist.Axes)
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
import matplotlib.image as mpimg
test_image = mpimg.imread('testImage.png')
imagebox = OffsetImage(test_image, zoom=1)
ab = AnnotationBbox(imagebox, (-0.0025, 0), box_alignment=(1, 0))
hostImage.add_artist(ab)
hostImage.figure.subplots_adjust(left=0.69) # based on https://matplotlib.org/stable/tutorials/intermediate/tight_layout_guide.html saying how to manually adjust
hostImage.figure.set_size_inches((18, 10)) # from https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/figure.py; also see drevicko's comment https://stackoverflow.com/a/638443/8508004
hostImage.figure.savefig("my_image_test.png") # fix for `hostImage.savefig("my_image_test.png")`, based on https://forum.freecodecamp.org/t/attribute-error-axessubplot-object-has-no-attribute-savefig/460255
hostImage.figure.clf() # using this so, Jupyter won't display the Matplotlib plot object; instead we'll show the image file
from IPython.display import Image
Image(filename="my_image_test.png")
How things are working for the shared lines I added is covered above.
Optionally when using Matplotlib 3.2.1 with code like here, to not also show the matplotlib cruft, such as something like <Figure size 1296x720 with 0 Axes>, you can split running this between two cells.
First cell's code:
%%capture
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as axisartist
hostImage = host_subplot(221, axes_class=axisartist.Axes)
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
import matplotlib.image as mpimg
test_image = mpimg.imread('testImage.png')
imagebox = OffsetImage(test_image, zoom=1)
ab = AnnotationBbox(imagebox, (-0.0025, 0), box_alignment=(1, 0))
hostImage.add_artist(ab)
hostImage.figure.subplots_adjust(left=0.69) # based on https://matplotlib.org/stable/tutorials/intermediate/tight_layout_guide.html saying how to manually adjust
hostImage.figure.set_size_inches((18, 10)) # from https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/figure.py; also see drevicko's comment https://stackoverflow.com/a/638443/8508004
hostImage.figure.savefig("my_image_test.png") # fix for `hostImage.savefig("my_image_test.png")`, based on https://forum.freecodecamp.org/t/attribute-error-axessubplot-object-has-no-attribute-savefig/460255
hostImage.figure.clf() # using this so, Jupyter won't display the Matplotlib plot object; instead we'll show the image file
Second cell's code:
from IPython.display import Image
Image(filename="my_image_test.png")
The first cell will show no output of any kind now due to the %%capture cell magic.
UPDATE:
(code below only tested with Matplotlib 3.5.)
Some options based on addition of sample figure OP is using and additional information in comment here, I suggest starting over with simpler subplot use for arranging the two elements. (If it was much more complex, I'd suggest other methods for compositing the two elements. Options would include: If just for presenting in Jupyter, ipywidgets can be used for layout. Pillow and ReportLab can be useful if making a publication-quality figure is the goal.)
!curl -o testImage.png https://owncloud.tuwien.ac.at/index.php/s/3caJsb2PcwN7HdU/download
#based on https://matplotlib.org/stable/gallery/subplots_axes_and_figures/subplots_demo.html
# and https://www.moonbooks.org/Articles/How-to-insert-an-image-a-picture-or-a-photo-in-a-matplotlib-figure/
# and https://nbviewer.org/gist/fomightez/4c2116e50f080b1305c41b9ac70df124#Solution
# axis off for lower plot based on https://stackoverflow.com/a/10035974/8508004
import matplotlib.pyplot as plt
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
import matplotlib.image as mpimg
fig, axs = plt.subplots(2,1,figsize=(4, 8))
#fig.suptitle('Vertically stacked subplots')
axs[0].grid()
axs[1].grid()
test_image = mpimg.imread('testImage.png')
imagebox = OffsetImage(test_image, zoom=1)
ab = AnnotationBbox(imagebox, (0.5,0.5))
axs[1].add_artist(ab)
axs[1].axis('off');
Or:
!curl -o testImage.png https://owncloud.tuwien.ac.at/index.php/s/3caJsb2PcwN7HdU/download
#based on https://matplotlib.org/stable/gallery/subplots_axes_and_figures/subplots_demo.html
# and https://www.moonbooks.org/Articles/How-to-insert-an-image-a-picture-or-a-photo-in-a-matplotlib-figure/
# and https://nbviewer.org/gist/fomightez/4c2116e50f080b1305c41b9ac70df124#Solution
# axis turned off for lower plot based on https://stackoverflow.com/a/10035974/8508004
import matplotlib.pyplot as plt
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
import matplotlib.image as mpimg
# data to plot based on https://stackoverflow.com/a/17996099/8508004 and converting it
# to work with subplot method
fig, axs = plt.subplots(2,1)
plt.subplots_adjust(hspace=1.8) # to move the bottom plot down some so not covering the top small one
#fig.suptitle('Vertically stacked subplots')
axs[0].plot(range(15))
axs[0].set_xlim(-7, 7)
axs[0].set_ylim(-7, 7)
axs[0].set_aspect('equal')
axs[1].grid()
test_image = mpimg.imread('testImage.png')
imagebox = OffsetImage(test_image, zoom=1)
ab = AnnotationBbox(imagebox, (0.5,0.5))
axs[1].add_artist(ab)
axs[1].axis('off');
Or if want to save the figure something like:
!curl -o testImage.png https://owncloud.tuwien.ac.at/index.php/s/3caJsb2PcwN7HdU/download
#based on https://matplotlib.org/stable/gallery/subplots_axes_and_figures/subplots_demo.html
# and https://www.moonbooks.org/Articles/How-to-insert-an-image-a-picture-or-a-photo-in-a-matplotlib-figure/
# and https://nbviewer.org/gist/fomightez/4c2116e50f080b1305c41b9ac70df124#Solution
# axis turned off for lower plot based on https://stackoverflow.com/a/10035974/8508004
import matplotlib.pyplot as plt
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
import matplotlib.image as mpimg
# data to plot based on https://stackoverflow.com/a/17996099/8508004 and converting it
# to work with subplot method
fig, axs = plt.subplots(2,1)
plt.subplots_adjust(hspace=0.3) # to move the bottom plot down some so not covering the top small one
#fig.suptitle('Vertically stacked subplots')
axs[0].plot(range(15))
axs[0].set_xlim(-7, 7)
axs[0].set_ylim(-7, 7)
axs[0].set_aspect('equal')
axs[1].grid()
test_image = mpimg.imread('testImage.png')
imagebox = OffsetImage(test_image, zoom=1)
ab = AnnotationBbox(imagebox, (0.5,0.5))
axs[1].add_artist(ab)
axs[1].axis('off')
# to accomodate this adjustment in the figure that gets saved via `plt.savefig()`, increase figure size
fig.set_size_inches((4, 7)) # from https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/figure.py; also see drevicko's comment
plt.savefig("stacked.png");
I'm not sure while the size changes on the top plot if you set the size so you can accomodate them but there's some honing on the right numbers needed there.
Edit on 2022-09-28:
I have found a solution for my case by browsing the help/py-code of matplotlib.offsetbox.AnnotationBbox:
The desired effect can be achieved by modifying the argument xybox of AnnotationBbox like so, for example
ab = AnnotationBbox(imagebox, xy = (1, 0), xybox = (2.0, 1.0), box_alignment=(1, 0))
Setting xybox = (2.0, 1.0), hence the x-value to 2.0 shifts the image far to the right of the plot area.

How to change the edgecolor of an Histogram in plotly?

I'm trying to change from matplotlib to plotly and I have to relearn every basic move.
One of my habit was to change the edge color of every histogram I made to white so it is easier to see the bars.
On matplotlib, I would do it like that :
import matplotlib.pyplot as plt
import numpy as np
vals = np.random.rand(50)
plt.hist(vals, edgecolor='white');
Which gives me :
I suppose there is a way to do it with plotly but I searched in the doc and other stackoverflow questions and haven't found it yet.
Closest way (that make me believe it is somehow possible): setting the template of the figure to a template using white edgecolor
import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import numpy as np
vals = np.random.rand(50)
fig = px.histogram(x=vals, template="simple_white")
fig.show()
I also tried to examinate the template simple_white and to look for the param that was making the edges to be white but this didn't lead to anything (if you know what this param is, the answer interests me even more !)
There is function called fig.update_traces you can increase marker(edge) width and change color to 'White' like:
fig = px.histogram(x=vals)
fig.update_traces(marker_line_width=1,marker_line_color="white")
fig.show()
Reference: https://plotly.com/python/reference/histogram/
plotly.graph_objects.Histogram accepts a Marker as input argument. That means you can enable the borders and specify their color using a marker:
import plotly.graph_objects as go
fig.show()
go.Histogram(x=vals,
marker=dict(line=dict(width=0.8,
color="white")))
To see all other parameters of a marker, see the docs here.

Showing a picture in python

I'm trying to show a figure, in PyCharm, that is in my working directory, but it either doesn't work or only works with this code:
img = mpimg.imread('Figure_1.png')
plt.imshow(img)
plt.show()
with this result:
I just want the picture as it is, not inside another figure. This is the original picture for reference:
Some quick workarounds: to remove the axes, do plt.axes('off'). To make the picture fit the frame, set the aspect ratio to 'auto' and create a figure with the same aspect ratio as your original image (i'd say it's roughly 4:1?). Use tight_layoutto make sure all of your image is visible. I don't know if that's the official way, but that's how i do it, and it kinda works ;-)
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
img = mpimg.imread('Figure_1.png')
f, a = plt.subplots(figsize=(16, 4))
plt.tight_layout()
plt.axis('off')
a.imshow(img)
plt.show()

Matplotlib: Save exact figure of imshow() automatically [duplicate]

This displays the figure in a GUI:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [1, 4, 9])
plt.show()
But how do I instead save the figure to a file (e.g. foo.png)?
When using matplotlib.pyplot.savefig, the file format can be specified by the extension:
from matplotlib import pyplot as plt
plt.savefig('foo.png')
plt.savefig('foo.pdf')
That gives a rasterized or vectorized output respectively.
In addition, there is sometimes undesirable whitespace around the image, which can be removed with:
plt.savefig('foo.png', bbox_inches='tight')
Note that if showing the plot, plt.show() should follow plt.savefig(); otherwise, the file image will be blank.
As others have said, plt.savefig() or fig1.savefig() is indeed the way to save an image.
However I've found that in certain cases the figure is always shown. (eg. with Spyder having plt.ion(): interactive mode = On.) I work around this by
forcing the the figure window to close with:
plt.close(figure_object)
(see documentation). This way I don't have a million open figures during a large loop. Example usage:
import matplotlib.pyplot as plt
fig, ax = plt.subplots( nrows=1, ncols=1 ) # create figure & 1 axis
ax.plot([0,1,2], [10,20,3])
fig.savefig('path/to/save/image/to.png') # save the figure to file
plt.close(fig) # close the figure window
You should be able to re-open the figure later if needed to with fig.show() (didn't test myself).
The solution is:
pylab.savefig('foo.png')
Just found this link on the MatPlotLib documentation addressing exactly this issue:
http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear
They say that the easiest way to prevent the figure from popping up is to use a non-interactive backend (eg. Agg), via matplotib.use(<backend>), eg:
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('myfig')
I still personally prefer using plt.close( fig ), since then you have the option to hide certain figures (during a loop), but still display figures for post-loop data processing. It is probably slower than choosing a non-interactive backend though - would be interesting if someone tested that.
UPDATE: for Spyder, you usually can't set the backend in this way (Because Spyder usually loads matplotlib early, preventing you from using matplotlib.use()).
Instead, use plt.switch_backend('Agg'), or Turn off "enable support" in the Spyder prefs and run the matplotlib.use('Agg') command yourself.
From these two hints: one, two
If you don't like the concept of the "current" figure, do:
import matplotlib.image as mpimg
img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)
import datetime
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
# Create the PdfPages object to which we will save the pages:
# The with statement makes sure that the PdfPages object is closed properly at
# the end of the block, even if an Exception occurs.
with PdfPages('multipage_pdf.pdf') as pdf:
plt.figure(figsize=(3, 3))
plt.plot(range(7), [3, 1, 4, 1, 5, 9, 2], 'r-o')
plt.title('Page One')
pdf.savefig() # saves the current figure into a pdf page
plt.close()
plt.rc('text', usetex=True)
plt.figure(figsize=(8, 6))
x = np.arange(0, 5, 0.1)
plt.plot(x, np.sin(x), 'b-')
plt.title('Page Two')
pdf.savefig()
plt.close()
plt.rc('text', usetex=False)
fig = plt.figure(figsize=(4, 5))
plt.plot(x, x*x, 'ko')
plt.title('Page Three')
pdf.savefig(fig) # or you can pass a Figure object to pdf.savefig
plt.close()
# We can also set the file's metadata via the PdfPages object:
d = pdf.infodict()
d['Title'] = 'Multipage PDF Example'
d['Author'] = u'Jouni K. Sepp\xe4nen'
d['Subject'] = 'How to create a multipage pdf file and set its metadata'
d['Keywords'] = 'PdfPages multipage keywords author title subject'
d['CreationDate'] = datetime.datetime(2009, 11, 13)
d['ModDate'] = datetime.datetime.today()
I used the following:
import matplotlib.pyplot as plt
p1 = plt.plot(dates, temp, 'r-', label="Temperature (celsius)")
p2 = plt.plot(dates, psal, 'b-', label="Salinity (psu)")
plt.legend(loc='upper center', numpoints=1, bbox_to_anchor=(0.5, -0.05), ncol=2, fancybox=True, shadow=True)
plt.savefig('data.png')
plt.show()
plt.close()
I found very important to use plt.show after saving the figure, otherwise it won't work.figure exported in png
The other answers are correct. However, I sometimes find that I want to open the figure object later. For example, I might want to change the label sizes, add a grid, or do other processing. In a perfect world, I would simply rerun the code generating the plot, and adapt the settings. Alas, the world is not perfect. Therefore, in addition to saving to PDF or PNG, I add:
with open('some_file.pkl', "wb") as fp:
pickle.dump(fig, fp, protocol=4)
Like this, I can later load the figure object and manipulate the settings as I please.
I also write out the stack with the source-code and locals() dictionary for each function/method in the stack, so that I can later tell exactly what generated the figure.
NB: Be careful, as sometimes this method generates huge files.
After using the plot() and other functions to create the content you want, you could use a clause like this to select between plotting to the screen or to file:
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(4, 5)) # size in inches
# use plot(), etc. to create your plot.
# Pick one of the following lines to uncomment
# save_file = None
# save_file = os.path.join(your_directory, your_file_name)
if save_file:
plt.savefig(save_file)
plt.close(fig)
else:
plt.show()
If, like me, you use Spyder IDE, you have to disable the interactive mode with :
plt.ioff()
(this command is automatically launched with the scientific startup)
If you want to enable it again, use :
plt.ion()
You can either do:
plt.show(hold=False)
plt.savefig('name.pdf')
and remember to let savefig finish before closing the GUI plot. This way you can see the image beforehand.
Alternatively, you can look at it with plt.show()
Then close the GUI and run the script again, but this time replace plt.show() with plt.savefig().
Alternatively, you can use
fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')
According to question Matplotlib (pyplot) savefig outputs blank image.
One thing should note: if you use plt.show and it should after plt.savefig, or you will give a blank image.
A detailed example:
import numpy as np
import matplotlib.pyplot as plt
def draw_result(lst_iter, lst_loss, lst_acc, title):
plt.plot(lst_iter, lst_loss, '-b', label='loss')
plt.plot(lst_iter, lst_acc, '-r', label='accuracy')
plt.xlabel("n iteration")
plt.legend(loc='upper left')
plt.title(title)
plt.savefig(title+".png") # should before plt.show method
plt.show()
def test_draw():
lst_iter = range(100)
lst_loss = [0.01 * i + 0.01 * i ** 2 for i in xrange(100)]
# lst_loss = np.random.randn(1, 100).reshape((100, ))
lst_acc = [0.01 * i - 0.01 * i ** 2 for i in xrange(100)]
# lst_acc = np.random.randn(1, 100).reshape((100, ))
draw_result(lst_iter, lst_loss, lst_acc, "sgd_method")
if __name__ == '__main__':
test_draw()
The Solution :
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.style.use('ggplot')
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
plt.figure()
ts.plot()
plt.savefig("foo.png", bbox_inches='tight')
If you do want to display the image as well as saving the image use:
%matplotlib inline
after
import matplotlib
When using matplotlib.pyplot, you must first save your plot and then close it using these 2 lines:
fig.savefig('plot.png') # save the plot, place the path you want to save the figure in quotation
plt.close(fig) # close the figure window
import matplotlib.pyplot as plt
plt.savefig("image.png")
In Jupyter Notebook you have to remove plt.show() and add plt.savefig(), together with the rest of the plt-code in one cell.
The image will still show up in your notebook.
Additionally to those above, I added __file__ for the name so the picture and Python file get the same names. I also added few arguments to make It look better:
# Saves a PNG file of the current graph to the folder and updates it every time
# (nameOfimage, dpi=(sizeOfimage),Keeps_Labels_From_Disappearing)
plt.savefig(__file__+".png",dpi=(250), bbox_inches='tight')
# Hard coded name: './test.png'
Just a extra note because I can't comment on posts yet.
If you are using plt.savefig('myfig') or something along these lines make sure to add a plt.clf() after your image is saved. This is because savefig does not close the plot and if you add to the plot after without a plt.clf() you'll be adding to the previous plot.
You may not notice if your plots are similar as it will plot over the previous plot, but if you are in a loop saving your figures the plot will slowly become massive and make your script very slow.
Given that today (was not available when this question was made) lots of people use Jupyter Notebook as python console, there is an extremely easy way to save the plots as .png, just call the matplotlib's pylab class from Jupyter Notebook, plot the figure 'inline' jupyter cells, and then drag that figure/image to a local directory. Don't forget
%matplotlib inline in the first line!
As suggested before, you can either use:
import matplotlib.pyplot as plt
plt.savefig("myfig.png")
For saving whatever IPhython image that you are displaying. Or on a different note (looking from a different angle), if you ever get to work with open cv, or if you have open cv imported, you can go for:
import cv2
cv2.imwrite("myfig.png",image)
But this is just in case if you need to work with Open CV. Otherwise plt.savefig() should be sufficient.
well, I do recommend using wrappers to render or control the plotting. examples can be mpltex (https://github.com/liuyxpp/mpltex) or prettyplotlib (https://github.com/olgabot/prettyplotlib).
import mpltex
#mpltex.acs_decorator
def myplot():
plt.figure()
plt.plot(x,y,'b-',lable='xxx')
plt.tight_layout(pad=0.5)
plt.savefig('xxxx') # the figure format was controlled by the decorator, it can be either eps, or pdf or png....
plt.close()
I basically use this decorator a lot for publishing academic papers in various journals at American Chemical Society, American Physics Society, Opticcal Society American, Elsivier and so on.
An example can be found as following image (https://github.com/MarkMa1990/gradientDescent):
You can do it like this:
def plotAFig():
plt.figure()
plt.plot(x,y,'b-')
plt.savefig("figurename.png")
plt.close()
Nothing was working for me. The problem is that the saved imaged was very small and I could not find how the hell make it bigger.
This seems to make it bigger, but still not full screen.
https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.Figure.set_size_inches
fig.set_size_inches((w, h))
Hope that helps somebody.
You can save your image with any extension(png, jpg,etc.) and with the resolution you want. Here's a function to save your figure.
import os
def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
print("Saving figure", fig_id)
if tight_layout:
plt.tight_layout()
plt.savefig(path, format=fig_extension, dpi=resolution)
'fig_id' is the name by which you want to save your figure. Hope it helps:)
using 'agg' due to no gui on server.
Debugging on ubuntu 21.10 with gui and VSC.
In debug, trying to both display a plot and then saving to file for web UI.
Found out that saving before showing is required, otherwise saved plot is blank. I suppose that showing will clear the plot for some reason. Do this:
plt.savefig(imagePath)
plt.show()
plt.close(fig)
Instead of this:
plt.show()
plt.savefig(imagePath)
plt.close(fig)

Matplotlib-Imported PNG won't show in 3D plot

I'm trying to use matplotlib to generate 3D figures where the xy plane is an image, and then some 3D tracks are drawn on top (that part works just fine). The problem is, even though my imported PNG shows just fine with imshow, and even though I can plot an image on a 3D axis if I just use an example from the cookbook, my image just shows up as a featureless black box. I'm sure I'm missing something small- thanks in advance!
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D, art3d
from pylab import ogrid
import matplotlib.pyplot as plt
plt.ioff()
fig = plt.figure()
ay=fig.add_subplot(2,1,1)
rawim=plt.imread(r'G:\Path\myimage.png')
ay.imshow(rawim,cmap='gray')
ax=fig.add_subplot(2,1,2,projection='3d')
x,y= ogrid[0:rawim.shape[0],0:rawim.shape[1]]
ax.plot_surface(x,y,0,rstride=5,cstride=5,facecolors=rawim,cmap='gray')
ax.view_init(elev=45, azim=12)
plt.show()
The output comes out as this (edited to include image).
PS Running Matplotlib 1.2.1 in Spyder for Python 2.75
Edited to add- I was largely modeling my approach from this post, so if instead of
rawim=plt.imread(r'G:\Path\myimage.png')
I use
from matplotlib.cbook import get_sample_data
fn = get_sample_data("lena.png", asfileobj=False)
rawim=read_png(fn)
it works perfectly. I've tried several of my PNG outputs, produced a couple of different ways, and no love. And yes, they're greyscale between 0-1.
You should use an explicit color array for facecolors.
You want something having shape (Nx, Ny, 4) where the "4" dimension holds RGBA values.
Also, get rid of the cmap='gray' in the plot_surface invocation.

Categories