Attach matplotlib figure.Figure to pyplot - python

I have a function that returns a matplotlib.figure.Figure object given some parameters and I want to add it to the pyplot object (so that pyplot.show() shows the image).
Is there any way to do this?
Thanks!
Background:
My question may seem counterintuitive, this is why I need to do so. I'm developing a Python package that uses matplotlib to generate plots, so I'm using the OO matplotlib interface.
I'm writing tests (using matplotlib.testing, which lets me compare images with a decorator) to be sure that the functions return the correct plots. The problem is that such package uses the MATLAB-like interface and looks for plots in the pyplot object (using plt.get_fignums()) and then compares with images in files.
I could modify the matplotlib.testing code to suit my needs but using the code as is seems a better option, even though attaching a figure to pyplot seems hacky.

I ended up using another approach to solve my testing problem. Instead of using the matplotlib.testing built-in decorator, I'm using the function that compares the images:
from matplotlib.testing.compare import compare_images
compare_images(expected='expected.png', actual='actual.png', tol=13, in_decorator=True)
That returns None if the test was successful or a Dictionary with some data in case the images differed more than the threshold. I'm going to build a wrapper around that function to make it more testing friendly.

Related

How can I test if matplotlib has produced the correct plot?

I would like to write tests for code that produces matplotlib plots. Ideally the tests would be able to decide if the output was appropriate without my input.
I have decoupled the data setup into easily testable functions, but I'm unsure how I could decouple the plotting or test the outcome without visual inspection. Is this something anyone has dealt with before?
Is there an established practice for testing in situations like this?
Ideally I would like something like this:
fig, ax = plt.subplot()
ax.plot(x_data, y_data)
ax.set_xlabel('x')
ax.set_ylabel('y')
assertTrue(fig == expected_fig)
Yes, the Matplotlib developers have dealt with that. And the practice they've established is this:
Write a test that produces a plot figure.
Save that figure as an image file in a temporary folder.
Assert that output image and corresponding "baseline" image are the same.
The test will fail the first time it is run. You then inspect the image, that one time, and use it as the reference for future tests simply by copying the file to the folder holding baseline images.
You may be able to re-use the Matplotlib test fixtures (source code, API documentation) and look at the Matplotlib tests to see how they are used in practice. Essentially, the comparison mechanism loads both image files via PIL, converts them to NumPy arrays, and tests that the two arrays are equal. Though there is also a way to specify a tolerance and allow minor deviations.

Save figure parameters after interactive tweaking

I often find myself using matplotlib to quickly display data, then later going back and tweaking my plotting code to make pretty figures. In this process, I often use the interactive plot window to adjust things like spacing, zooming, cropping, etc. While I can easily save the resulting figure to an image file, what I really want is to save the sequence of function calls/parameters that produced it.
Note that I don't particularly care to open the same figure again (as in Saving interactive Matplotlib figures). Even something as simple as being able to print the various properties of the figure and axes would be useful.
While I don't have the answer to your specific question, I'd generally suggest using the Ipython Notebook for these things (and much more!)
Make sure you have %pylab inline in one cell.
When you plot, it will display it in the notebook itself. Then within your cell, just keep experimenting until you have it right (use Ctrl-Enter in the cell). Now the cell will have all the statements you need (and no more!)
The difference between the command line interpreter and the notebook is that the former all statements you typed which leads to a lot of clutter. With the notebook you can edit the line in place.
A similar question here
has an answer I just posted here.
The gist: use MatPlotLib's picklable figure object to save the figure object to a file. See the aforementioned answer for a full example.
Here's a shortened example:
fig, ax = matplotlib.pyplot.subplots()
# plot some stuff
import pickle
pickle.dump( fig, open('SaveToFile.pickle', 'wb') )
This does indeed save all plotting tweaks, even those made by the GUI subplot-adjuster. Unpickling via pickle.load() still allows you to interact via CLI or GUI.

understanding (and finding) matplotlib source code

Here it appears that matplotlib's specgram returns 4 variables including the last which is a plot:
http://matplotlib.org/examples/pylab_examples/specgram_demo.html
But here it seems there is only 3 variables returned in the tuple:
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/mlab.py#L478
Where is the missing code to generate the specgram plot? Perhaps I am just confused on the difference between pylab and matplotlib. Either way, I can't find the source.
You're confusing the function that computes the data to be plotted with the function that plots the data.
mlab.specgram just computes the data, while the axes method specgram plots it.
Have a look at: https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes/_axes.py#L5786
ipython is very useful for things like this. method_name? will display the relevant documentation and the location of the source file, while method_name?? will display the relevant code, as well.
Understanding where the source for a matplotlib function is can be a bit confusing. Basically, anything in matplotlib.pyplot is auto-generated. Essentially all of the plotting methods are actually methods of the Axes object.
Hopefully that gets you started. If no one else gives a better answer, I'll elaborate more in a bit, when I have more time.

Matplotlib figure changes for publication after making the figure

I have been running into the problem of generating publication 'perfect' images in Matplotlib (i.e changing the fontsize, marker size, figuresize, number of ticks etc...).
Essentially, I want to do what is described here: http://www.scipy.org/Cookbook/Matplotlib/LaTeX_Examples except after the figure has already been made. i.e I want to make a function that accepts the Figure object, and makes all the necessary changes, some of which are available as input arguments. That way I don't have to always modify my scripts when I decide to use a figure in a paper.
Is there an efficient way to achieve this?
Note I'm usually using Ipython.
Well, we are doing this all the time to create good figures. In our case we wanted something that would automatically choose the linestyle and marker because we always have to plot many lines in the same figure, and this would avoid manually specifying these things.
We programmed some functions so that at the end you need a plot.py script, which is very simple, and an input.txt with all the info. In the input file you can also use any parameter like linewidth, label, and so forth.... but by default it will follow the pre-defined order for linestyles, markers and so on.
Also, you need a good matplotlibrc file. You can have many different matplotlibrc files since the highest priority is given to the one at the local directory, as explained here. This will allow you to customize keeping your plotting code cleaner.
The functions commented above (with examples) are available in this link, maybe they can give you some insights.
They solved one problem I had with subplots, described here.
Maybe you can make use of matplotlib pickling available in vs 1.2.1.
As said in the above link:
Philip Elson added an experimental feature to make figures picklable
for quick and easy short-term storage of plots. Pickle files are not
designed for long term storage, are unsupported when restoring a
pickle saved in another matplotlib version and are insecure when
restoring a pickle from an untrusted source. Having said this, they
are useful for short term storage for later modification inside
matplotlib.
No personal experience, however

What is the `imrect` equivalent in Python?

I'm looking for a simple Python utility or module that:
I can give it an image, and it pops up a GUI window for the user to draw a box inside the image
after drawing the box, it returns the coordinates of the box
MATLAB users will realize that I am asking for imrect equivalent in Python.
Is there a simple utility out there to do this?
A quick implementation, for any future searchers: https://raw.github.com/cvondrick/pyvision/master/vision/drawer.py
You can try PIL - Python Imaging Library.
For GUI there's a module named tkinter, though there may be some better options too.
Since most people coming to Python from MATLAB will be making use of lots of SciPy, NumPy, and Matplotlib functions, I would think that the RectangleSelector function of Matplotlib would be the closest equivalent to the imrect function in MATLAB. It is probably a little easier to implement than the other examples if you are already making your plots using Matplotlib.
See this example: Widgets example code: rectangle_selector.py
And this page: class matplotlib.widgets.RectangleSelector
Note: Mac users will need to switch renderers to get this example to work, by including the following code:
import matplotlib
matplotlib.use('TkAgg')
Here is that example in action:
Unlike the imrect function in MATLAB, the default behavior is for the box to only stay in place while you are drawing it.
You may use OpenCV's Python implementation! It is fast and is integrated with PyQt 4!
OpenCV Homepage

Categories