Does the backend matter for savefig - python-3.x

I have a script which plots some pandas data, and then either shows the plot interactively with plt.show(), or saves it to a file with plt.savefig(args.out).
import matplotlib.pyplot as plt
# set up the dataframe here
ax = df.plot.line(x=0, title=args.title, figsize=(12,8), grid=True, **kwargs)
if (args.out):
vprint("Saving figure to ", args.out, "...")
plt.savefig(args.out)
else:
vprint("Showing interactive plot...")
plt.show()
The question is, does the default matplotlib backend matter for the scenario where I save to a file with savefig? It definitely matters in the other case since it's used to display the interactive plot, but if I call savefig is another backend used entirely?

When showing a figure, the backend obviously matters, because it provides two things:
The renderer to draw the image
The GUI within which the image is shown.
When saving a figure, only the former matters. However, matplotlib provides a multitude of export formats. At the end, the chosen backend will determine what to do when a figure is saved, and in most cases, will use one of the existing non-interactive backends to produce the output file.
Some examples:
TkAgg will use the tkinter GUI to show a figure. For saving a png figure, it will fall back to the basic Agg backend to produce the png file. For saving an svg file, it will fall back to the svg backend, for saving a pdf it will fallback to the pdf backend, etc.
TkCairo, will use the tkinter GUI to show a figure. For saving a png figure, it will fall back to the basic Cairo backend to produce the png file. For the rest, same as above.
Qt5Agg will use the PyQt GUI to show a figure. For png will fall back to Agg. For others same as above.
similar for other backends.

Related

showing PIL ImageGrab as numpy Array in Kivy Window

I am trying to capture a part of my screen with PIL.ImageGrab and then converting it to an numpy.array as you can see below.
np.array(ImageGrab.grab(bbox=(0, 0, 720, 480)))
What I can't figure out is, how to get this data into a Kivy window or a widget?
All my Widgets are in separate classes so I would like to have one Screen class with all the code necessary for this part of my Window.
I have already tried methods like this one, but I don't know how to implement it since Kivy confuses me a lot sometimes.
If my idea just isn't realizable, I guess you could save each captured frame as .jpg format and then load it into Kivy. But I imagine this is not the most efficient way.
Thanks a lot in advance! Dominik

Is it possible to update inline plots in Python (Spyder)?

Setup: Anaconda 3 (Win10 64), Spyder 4 and Python 3.7. The IPython Graphics setting is default (Inline).I'm still a new to Python but I've looked around and have not found an answer that solves my problem so far. Thanks everyone in advance.
So in this setup, whenever I create a plot using matplotlib, it appears in the plot pane of Spyder. e.g.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
df = pd.DataFrame(np.random.randint(0,100,size=(100, 1)), columns=list('A'))
bp = df.boxplot(column = 'A')
creates a boxplot. Now, if I want to add a title to the plot, the code would be
bp.set_title("This Title")
This is where I'm getting some problems. If I run the entire block together
df = pd.DataFrame(np.random.randint(0,100,size=(100, 1)), columns=list('A'))
bp = df.boxplot(column = 'A')
bp.set_title("This Title")
then I get a box plot with "This Title" as the title, showing up in the plot pane,
which is what I want.
However, if I run the above code line by line in the IPython console, the 2nd line will produce a boxplot as expected, but the 3rd line will not have an effect on the image in the plot pane, so the image in the plot pane still do not have a title
Now,if i go to Tools > Preference >IPython Console > Graphics and set the graphics backend to Automatic instead of the default Inline, then when I run the code in the Console line by line, I get an image that pops up in another window, and that it does update/refreshes based on new lines entered into the console. I understand that the inline plots are supposed to be static, but I thought I saw another post where someone said that it is possible to update inline plots? So now my questions are:
Do plots only update/refresh by line codes in the IPython console if the Graphics Backend is not static like inline?
Why do I get different result when I run code blocks vs line by line?
If it is possible to update the inline plots (preferably in the plot pane of Spyder), how do you do it? I've tried various methods to redraw the plots,for example
plt.show()
plt.draw()
bp.get_figure().canvas.draw()
but none of these updates the image in the plot pane. I figured that even if I can't update the image, I should at least be able to redraw it (i.e a 2nd image appears in the plot pane with the update characteristics). But nothing I've tried worked so far. Please advise and thanks again.
(Spyder maintainer here) About your questions:
Do plots only update/refresh by line codes in the IPython console if the Graphics Backend is not static like inline?
Correct.
Why do I get different result when I run code blocks vs line by line?
Because when you run code cells (which is what I think you mean by "code blocks") your plot is shown at the end of that code and hence it takes all modifications you've done to it in intermediate lines.
If it is possible to update the inline plots (preferably in the plot pane of Spyder), how do you do it?
No, it's not possible. As you correctly mentioned above, inline plots are static images, so they can't be modified.

Show multiple images in interactive mode python

I'm in an interactive program which marks specific part of an images through clicking the points around it. I want to show the segmented parts in a different image. it seems that plt.imshow(image) doesn't work well in an interactive environment and i cant turn it off cause then i cant work on the main image. Is there a better command to show an specific array in an interactive mode separately.
Thanks
Have you turned matplotlib's interactive mode on?
import matplotlib.pyplot as plt
plt.ion() # turning on interactive mode

How to get Numpy array of Canvas data?

I am building an application with Tkinter, where one is able to draw e.g. lines in a Canvas. This works well. However, I'm unable to find a method for getting the current Canvas data. Preferably I would like to get a numpy array out of the current Canvas data, since my post-processing steps are mostly using numpy.
Is there any way to build numpy arrays out of the Canvas data? In some color format like RGB, by preference?
I know that I can get the information e.g. of lines (like coordinates) out of the Canvas, but I do not need this information. I need a rasterized image data of the whole Canvas scene. Like a numpy array or a (rasterized) image (jpg, png, tiff, bitmap, ...).
Like #Bryan Oakley said: there is no way to get a rasterized version of a Tkinter Canvas drawing.
However, I figured out this workaround:
import skimage.io as ski_io
(...)
# draw your canvas
(...)
# save canvas to .eps (postscript) file
canvas.postscript(file="tmp_canvas.eps",
colormode="color",
width=CANVAS_WIDTH,
height=CANVAS_HEIGHT,
pagewidth=CANVAS_WIDTH-1,
pageheight=CANVAS_HEIGHT-1)
# read the postscript data
data = ski_io.imread("tmp_canvas.eps")
# write a rasterized png file
ski_io.imsave("canvas_image.png", data)
I do not really like workarounds, but skimage seems to be the fastest solution for reading postscript files and writing pngs.
Scikit-image is developed as a toolkit for SciPy, therefore it is working with scipy.ndimage internally, which is exactly what I want and can be used to create np.ndarray very easily.
Additionally scikit-learn is a powerful and fast image processing software itself, which can manipulate, read, and save various image formats.
Now you have the full choice: get a NumPy np.ndarray out of Canvas data for further computations, manipulate the scipy.ndimage with SciPy/scikit-image or save the data, e.g. as a rasterized png, to disk.

Using reportlab to build PDF with vector-based graphs generated by matplotlib

I'm trying to build PDF-documents on the server-side in a Django-Installation using reportlab. These documents should contain several graphs which are to be created with matplotlib.
I already figured out how to make reportlab use matplotlib's images without dumping them to the filesystem temporarily by passing PIL-Image objects directly to the Image()-flowable. This works surprisingly well for rasterized images formats like PNG.
Now, the icing on the cake would be able to embed vector based graphics (like SVG).
I used svglib to convert SVGs generated by matplotlib to reportlab graphic objects but unfortunately svglib does omit the tickmarks and axis labels. On some graphs it fails in general.
Do you have any ideas?
This page has a solution that I haven't had a chance to test myself yet: https://web.archive.org/web/20120725125858/http://lateral.netmanagers.com.ar/weblog/posts/BB753.html
You can generate matplotlib graphics as pdf and use pdfrw to embed it in reportlab canvas as described in this answer

Resources