What wizardry is being used to display Matplotlib color maps in an ipython console? - matplotlib

I am working with Matplotlib color maps, and I also happen to be working with the Spyder IDE, which has an ipython console.
As you can see from the screen shot, the ipython console showed me a graphical representation of the color map object. This was unexpected and very helpful.
Normally I expect to see a string representation of an object, as you might see from the print() function call. Function calls to print() and repr() are shown, and they produce text, as is more typical.
I would like my own code to output this graphical representation when it is generating output. I have been poking through the matplotlib.colors.Colormap internals, and so far I haven't been able to figure out how. What is ipython doing? How can I do the same?
Thanks!

This rather seems like a ipython/jupyter feature. ipython detects the object and produces automatically a plot to preview the colormap.
Here using jupyter:

IPython looks if an object has a _repr_html_; if so, it calls it and displays the output as HTML. Here's an example (I ran this in Jupyter but it works the same as long as you're running IPython):
class MyCoolObject:
def _repr_html_(self):
return ("<h1>hello!</h1> <p>this is some html </p>"
"I can even put images:"
"<img src='https://upload.wikimedia.org/wikipedia"
"/commons/thumb/3/38/Jupyter_logo.svg"
"/44px-Jupyter_logo.svg.png'></img>")
MyCoolObject()

To add on to Eduardo's answer, from everything I've read adding a _repr_html_ method should make iPython display the object when you type it into the console. I also use spyder though, and could not get it to work the way I expected. This simple wrapper class should allow you to display any html:
class displayedHTML:
def __init__(self, html):
self.html = html
def _repr_html_(self):
return self.html
But as you can see it does not work for me, instead showing the (implicitly defined) __repr__ of the class.
In [2]: obj = displayedHTML("<h1>" + "hello world" + "</h1>")
In [3]: obj
Out[3]: <__main__.displayedHTML at 0x1e8cda8f0d0>
I was not able to find the reason why this does not work, but I found a workaround if you just want to display a matplotlib colormap in the console from code (like I did).
Since know the matplotlib object works correctly, we can just give it to the ipython display function:
from IPython.display import display #Included without import since IPython 5.4 and 6.1
viridis = matplotlib.cm.get_cmap('viridis')
display(viridis)
And for me this works...
not_allowed_to_insert_pictures_yet.jpg
Hope this helps!

Related

save pyplot figure "as figure" (not as image)

How can I save a figure using PyPlot in Julia, so that the figure can be reloaded as a figure later in Julia? (not as an image)
You can use serialize to store any Julia object. This beautifully works for plots as well.
Let us start by generating a plot:
using Plots
pyplot()
p = plot(rand(10));
using Serialization
Serialization.serialize("myfile.jld", p);
Note that you need a semicolon after plot command so it does not appear on the screen.
Let us now read the plot (to have a full test I ended the previous Julia session and started a new one):
using Plots
pyplot();
using Serialization
p2 = Serialization.deserialize("myfile.jld");
In order to display it now it is enough to type in REPL:
julia> p2
You might want also want to use plain PyPlot (I strongly recommend Plots for flexibility). In that case your best bet is to follow rules described in object-oriented API of Matplotlib:
using PyPlot
ioff()
fig = subplot()
fig.plot(rand(10))
fig.set_title("Hello world")
using Serialization
serialize("pp.jld", fig)
In order to plot de-serialize back the object:
using PyPlot
ioff()
using Serialization
fig = deserialize("pp.jld")
show()
Finally, note that the serialization is good only for short term storage. If anything changes (e.g. you update Julia packages) you might not be able to de-serialize the plot.
Hence another good alternative for processable plots are saving them to LaTeX or SVG format - both is possible in Julia.

Julia: How to save a figure without plotting/displaying it in PyPlot?

I am using the PyPlot package in Julia to generate and save several figures. My current approach is to display the figure and then save it using savefig.
using PyPlot
a = rand(50,40)
imshow(a)
savefig("a.png")
Is there a way to save the figure without having to first display it?
Are you using the REPL or IJulia?
If you close the figure then it won't show you the plot. Is that what you want?
a = rand(50,40)
ioff() #turns off interactive plotting
fig = figure()
imshow(a)
close(fig)
If that doesn't work you might need to turn off interactive plotting using ioff() or change the matplotlib backend (pygui(:Agg)) (see here: Calling pylab.savefig without display in ipython)
Remember that most questions about plotting using PyPlot can be worked out by reading answers from the python community. And also using the docs at https://github.com/JuliaPy/PyPlot.jl to translate between the two :)
close() doesn't require any arguments so you can just call close() after saving the figure and create a new figure
using PyPlot
a = rand(50,40)
imshow(a)
savefig("a.png")
# call close
close()

PyPlot Error in Julia: type PyObject has no field set_yscale

I am programming in Julia but using PyPloy library. I want to plot an histogram with log y-axis. But when I use the following code:
using PyPlot
List = [rand() for i = 1:100]
plt.hist(List)
plt.gca().set_yscale("log")
I get the following error:
type PyObject has no field set_yscale
while loading In[45], in expression starting on line 3
in getindex at /home/rm/.julia/v0.4/PyCall/src/PyCall.jl:642
in pysequence_query at /home/rm/.julia/v0.4/PyCall/src/conversions.jl:743
in pytype_query at /home/rm/.julia/v0.4/PyCall/src/conversions.jl:759
in convert at /home/rm/.julia/v0.4/PyCall/src/conversions.jl:808
in pycall at /home/rm/.julia/v0.4/PyCall/src/PyCall.jl:812
in fn at /home/rm/.julia/v0.4/PyCall/src/conversions.jl:181
in close_queued_figs at /home/rm/.julia/v0.4/PyPlot/src/PyPlot.jl:295
Is this a path error? If so, is there a simpler way to do a log-log plot with a different command?
Thanks in advance.
I feel like this should be more prominently explained in the documentation, but if you scroll down to the bottom of the Readme for PyCall (which PyPlot uses) it says:
Important: The biggest difference from Python is that object attributes/members are accessed with o[:attribute] rather than o.attribute, so that o.method(...) in Python is replaced by o[:method](...)
So, as #jverzani mentioned, after you call any module-level function from PyPlot that returns an object, that object is a PyObject and all of the attributes and methods have to be called using the bracket notation with a symbol.

PathPatch object in julia with PyPlot

I was trying to reproduce this example from the matplotlib website using the PyPlot package for Julia. As far as I know, the PyPlot is essentialy the matplotlib.pyplot module, so I imported the other modules of matplotlib that I needed (with the #pyimport macro):
using PyCall
#pyimport matplotlib.path as mpath
#pyimport matplotlib.patches as mpatches
Then I proceed to define the path object:
Path = mpath.Path
but then I get:
fn (generic function with 1 method) .
As if I had defined a function. Moreover, when I assign the path_data I get the following error:
ERROR: type Function has no field MOVETO
Of course, that's due to Path, which Julia tries as a function and not as a type or something like that. As you might guess the same happens when I try to define the variable patch .
So, there are incompatibilities of modules from matplotlib different to pyplot for Julia since the expected objects (types) are taken as functions. This behaviour can be expected if it were different the PyPlot.jl file wouldn't be needed.
My questions are:
-Am I doing something wrong?
-Is there a simple way to make it works?
-Do you know another package for Julia in which I can define patches and work in a similar way to matplotlib?
I have in mind to do this kind of animations.
Thanks for your ideas.
You need to get the "raw" Python object for Path. By default, PyCall converts Python type objects into functions (which call the corresponding constructor), but then you cannot access static members of the class.
Instead, do e.g. Path = mpath.pymember("Path") to get the "raw" PyObject, and then you can do Path["MOVETO"] or Path[:MOVETO] to access the MOVETO member.
(This difficulty will hopefully go away in Julia 0.4 once something like https://github.com/JuliaLang/julia/pull/8008 gets merged (so that we can make PyObjects callable directly.)

IPython plotting inline not showing

I have the following code in IPython running IPython QT Console on Linux.
%pylab inline
Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].
For more information, type 'help(pylab)'.
fig = figure()
ax = fig.add_axes()
ax = fig.add_axes([0,500, 0, 5000])
ax.plot([1,2,3,44], [4,4,55,55])
Out[5]: [<matplotlib.lines.Line2D at 0x3d8e7d0>]
fig
Out[6]: <matplotlib.figure.Figure at 0x3d25fd0>
fig.show()
/usr/lib/pymodules/python2.7/matplotlib/figure.py:362: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure
"matplotlib is currently using a non-GUI backend, "
I've been struggling to make this work for some time, I've tried changing the backend manually with matplotlib.use() to Qt4Agg, GTK etc with no luck. This also happens in IPython notebook even when I call display().
Any ideas how to get the inline plotting working?
Marked Jakob's answer as the answer, but both are true actually. I had to replace the matploblibrc file with a new copy, started IPython QT Console with --pylab=None then manually entered %pylab inline in the console. Somehow this fixed the problem.
The axis object is defined incorrectly, this prevents matplotlib from rendering.
Remove the first ax = fig.add_axes(), and replace the second line with
ax = fig.add_axes([0, 0, 1, 1]).
The add_axes method requests the size of the axis in relative coordinates, in the form left, bottom, width, height with values between 0 and 1, see e.g. matplotlib tutorial.
You may also try fig.add_subplot(111) instead of fig.add_axes() or fig,ax = subplots() to create your figure and axis objects. The latter assumes that you have populated the interactive namespace matplotlib (%pylab) call in IPython.
It looks like your matplotlib build was compiled without a gui backend.
This is done when either a) it's explicitly specified (handy for webservers), or b) the required libraries for at least one gui backend aren't present (e.g. no Tk, Gtk, Qt, etc).
How did you install matplotlib?
If you compiled it from source, make sure that you have the development libraries for at least Tk installed and that your python install was compiled with Tk support (it is by default). If you installed it from your distro's repositories, whoever built the package built it without gui support, and you'll need to install it from another source.