if I work on a matplotlib inline plot in an ipython notebook like this:
figure = plt.figure()
ax = figure.gca(projection="3d")
graph = np.empty([len(thetaYield),3])
for g, tY in zip(graph, thetaYield):
sample = HWtoPS(xiYield, rhoYield, tY)
g[...] = sample[:]
ax.plot(graph[:,0],graph[:,1], graph[:,2])
plt.show()
the plot is drawn inline in my notebook as it intended.
Now I want to add to add some data to this plot:
principalStress, vectors = eig(sigma)
ax.scatter(principalStress[0], principalStress[1], principalStress[2])
plt.show()
no error, but also no plot is drawn.
I expected to get an "updated" version of my plot with the additional data.
How can this be done?
A: This can be done at a cost of changed matplotlib Renderer
Currently, this cannot be done for the IPython "inline" graphs, however, if you opt to change a Renderer part of the matplotlib framework, to another one, the limitation of a singleton call of the .show() method does not hurt and you can ex post modify the object's content and it gets re-processed by the Renderer.
Simply:
add a directive ( IPython magic) %matplotlib qt
&
use additional matplotlib calls as you expect 'em to modify/update the figure object
( I love using this both during prototyping phases & for interactive 3D-viewing of complex data visualisations (which I heavily miss in notebook's "inline"s) )
BTW: do you have about any methodology, which would allow to store a matplotlib 3D-view plot, as a complete, state-full container, that can be sent to some other user for her/his "load" and UI-interactive review? Would be great to hear about any such working :o)
Related
At the moment I am working with Spyder and doing my plotting with matplotlib. I have two monitors, one for development and another for (data) browsing and other stuff. Since I am doing some calculations and my code often changes, I often (re)execute the code and have a look at the plots to check if the results are valid.
Is there any way to place my matplotlib plots on a second monitor and refresh them from the main monitor?
I have already searched for a solution but could not find anything. It would be really helpful for me!
Here's some additional information:
OS: Ubuntu 14.04 (64 Bit)
Spyder-Version: 2.3.2
Matplotlib-Version: 1.3.1.-1.4.2.
I know it's an old question but I came across a similar problem and found this question. I managed to move my plots to a second display using the QT4Agg backend.
import matplotlib.pyplot as plt
plt.switch_backend('QT4Agg')
# a little hack to get screen size; from here [1]
mgr = plt.get_current_fig_manager()
mgr.full_screen_toggle()
py = mgr.canvas.height()
px = mgr.canvas.width()
mgr.window.close()
# hack end
x = [i for i in range(0,10)]
plt.figure()
plt.plot(x)
figManager = plt.get_current_fig_manager()
# if px=0, plot will display on 1st screen
figManager.window.move(px, 0)
figManager.window.showMaximized()
figManager.window.setFocus()
plt.show()
[1] answer from #divenex: How do you set the absolute position of figure windows with matplotlib?
This has to do with matplotlib, not Spyder. Placing the location of a figure explicitly appears to be one of those things for which there's really just workarounds ... see the answers to the question here. That's an old question, but I'm not sure there's been change since then (any matplotlib devs, feel free to correct me!).
The second monitor shouldn't make any difference, it sounds like the issue is just that the figure is being replaced with a new one.
Fortunately you can update figures you've moved to where you want them pretty easily, by using the object interface specifically, and updating the Axes object without creating a new figure. An example is below:
import matplotlib.pyplot as plt
import numpy as np
# Create the figure and axes, keeping the object references
fig = plt.figure()
ax = fig.add_subplot(111)
p, = ax.plot(np.linspace(0,1))
# First display
plt.show()
# Some time to let you look at the result and move/resize the figure
plt.pause(3)
# Replace the contents of the Axes without making a new window
ax.cla()
p, = ax.plot(2*np.linspace(0,1)**2)
# Since the figure is shown already, use draw() to update the display
plt.draw()
plt.pause(3)
# Or you can get really fancy and simply replace the data in the plot
p.set_data(np.linspace(-1,1), 10*np.linspace(-1,1)**3)
ax.set_xlim(-1,1)
ax.set_ylim(-1,1)
plt.draw()
I am using iPython notebook wo do some visualization. Figures are inline (the profile defaults to interactive, as this supports a number of users who prefer interactive more frequently):
%pylab inline
Using the inline plot, I often set the fig size manually:
figsize(10,5)
I find that I need to run cells twice to realize a change in the fig size. For example, if I define cell [1] as figsize(10,5) and run it, the output is the correct size. If I then run cell [2] with `fig size(5,10)1 I get output that is of size (10,5). A second run of cell [2] draws correctly.
Any insight into why this is occurring? Is it due to the inline backend and I just need to live with it?
Thanks.
Definition: figsize(sizex, sizey)
Docstring:
Set the default figure size to be [sizex, sizey].
This is just an easy to remember, convenience wrapper that sets::
matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
This seem correct to me, if you run the following, whatever value of X, Y I always get the right plot
figsize(10,5)
plot(range(10))
if you run it after your plot, then you set the default for next plot... but without exact example, hard to say..
How can I prevent a specific plot to be shown in Jupyter notebook? I have several plots in a notebook but I want a subset of them to be saved to a file and not shown on the notebook as this slows considerably.
A minimal working example for a Jupyter notebook is:
%matplotlib inline
from numpy.random import randn
from matplotlib.pyplot import plot, figure
a=randn(3)
b=randn(3)
for i in range(10):
fig=figure()
plot(b)
fname='s%03d.png'%i
fig.savefig(fname)
if(i%5==0):
figure()
plot(a)
As you can see I have two types of plots, a and b. I want a's to be plotted and shown and I don't want the b plots to be shown, I just want them them to be saved in a file. Hopefully this will speed things a bit and won't pollute my notebook with figures I don't need to see.
Thank you for your time
Perhaps just clear the axis, for example:
fig= plt.figure()
plt.plot(range(10))
fig.savefig("save_file_name.pdf")
plt.close()
will not plot the output in inline mode. I can't work out if is really clearing the data though.
I was able to prevent my figures from displaying by turning interactive mode off using the function
plt.ioff()
To prevent any output from a jupyter notebook cell you may start the cell with
%%capture
This might be usefull in cases all other methods shown here fail.
From IPython 6.0 on, there is another option to turn the inline output off (temporarily or persistently). This has been introduced in this pull request.
You would use the "agg" backend to not show any inline output.
%matplotlib agg
It seems though that if you had activated the inline backend first, this needs to be called twice to take effect.
%matplotlib agg
%matplotlib agg
Here is how it would look in action
I'm a beginner though,off the inline mode when you don't want to see the output in your notebook by:
%matplotlib auto
or:
%matplotlib
to use it back:
%matplotlib inline
more better solution would be to use:
plt.ioff()
which says inline mode off.
hope it helps.
On Jupyter 6.0, I use the following snippet to selectively not display the matplot lib figures.
import matplotlib as mpl
...
backend_ = mpl.get_backend()
mpl.use("Agg") # Prevent showing stuff
# Your code
mpl.use(backend_) # Reset backend
Building off #importanceofbeingernest's answer, one may call some function in a loop, and at each iteration, want to render a plot. However, between the each plot, you may want to render additional stuff.
Concretely:
Iterate a list of IDs
Call a function so a plot is rendered for each "ID"
Between each plot, render some markdown
# <cell begins>
def render(id):
fig, axes = plt.subplots(2, 1)
plt.suptitle(f'Metrics for {id}')
df.ColA.plot.bar(ax=axes[0])
df.ColB.plot.bar(ax=axes[1])
return fig
# <cell ends>
# -------------------------------------
# <cell begins>
%matplotlib agg
for id in df.ID.value_counts().index:
fig = render(id)
display(fig)
display(Markdown('---'))
# <cell ends>
I've kept a set of references to figures in a dictionary so that I could save them later if desired. I am troubled that the saved figures are blank if invoke a show() command and look at them first. Since the show() command blocks and I am not using a spyder-like interpreter, I have to close the figures before I get to savefig()
figures['myfig_1'] = figure()
...
figures['myfig_n'] = figure()
...
#show() #disabling this makes the problem go away
print "Saving:"
for fig in figures:
figure(figures[fig].number)
savefig(fig)
print "Figure " + str(figures[fig].number) + ": " + fig
The print statement here has given me the indication that the dictionary is still intact, which I think means that I have not lost the figure references (they are still returning meaningful numbers in their .number attribute.)
Another twist I have noticed is that when I have done a similar thing in a class, storing the dictionary as a member and dividing the store and save functions into their own methods, this does not happen. Is there something about the way I am closing the figures or storing the data which is making the figures loose their data?
Generally speaking, in cases like this don't use the interactive matlab-ish state machine interface to matplotlib. It's meant for interactive use.
You're trying to make a figure "active", and creating a new figure instead. It doesn't matter which figure is active, if you just retain the returned figure and/or axis objects and use them directly. (Also, don't use wildcard imports! You will regret it at some later point when you're maintaining your code!)
Just do something like this:
import matplotlib.pyplot as plt
figures = {}
figures['a'] = plt.figure()
ax = figures['a'].add_subplot(111)
ax.plot(range(10), 'ro-')
figures['b'] = plt.figure()
ax = figures['b'].add_subplot(111)
ax.plot(range(10), 'bo-')
plt.show()
for name, fig in figures.iteritems():
fig.savefig('figure-%s.png' % name)
From the documentation, whether or not the drawing elements are destroyed from show() depends on the backend, and the version of matplotlib. Not having the figures destroyed seems to be available with version 1.1.0. To figure out which backend is in use, use the get_backend() function. In my case, I was using the Qt4Agg backend. By invoking the TkAgg backend, with the call matplotlib.use('TkAgg') the figures were not destroyed before the save. Now to find out how to change the behavior of the Qt4Agg...
I am using scipy-cluster to generate a hierarchical clustering on some data. As a final step of the application, I call the dendrogram function to plot the clustering. I am running on Mac OS X Snow Leopard using the built-in Python 2.6.1 and this matplotlib package. The program runs fine, but at the end the Rocket Ship icon (as I understand, this is the launcher for GUI applications in python) shows up and vanishes immediately without doing anything. Nothing is shown. If I add a 'raw_input' after the call, it just bounces up and down in the dock forever. If I run a simple sample application for matplotlib from the terminal it runs fine. Does anyone have any experiences on this?
I had the same issue on Ubuntu 10.04.
In order to get graphics to display from ipython interactive console, start it with "-pylab" switch, which enables the interactive use of matplotlib:
ipython -pylab
To get your graphics to display during the execution of a standalone script, use matplotlib.pyplot.show call. Here's an example from hcluster homepage, the first and last line are the significant bits here:
from matplotlib.pyplot import show
from hcluster import pdist, linkage, dendrogram
import numpy
from numpy.random import rand
X = rand(10,100)
X[0:5,:] *= 2
Y = pdist(X)
Z = linkage(Y)
dendrogram(Z)
show()
Invoking ipython with "-pylab" switch didn't make a difference for me.
(System: Fedora 13)
Though not ideal, my solution was to explicitly write the resulting figure as a file.
For example:
...
dendrogram(Z)
pylab.savefig( "temp.png" )
Hope this helps anyone who is running into the same issue.
Amendment: Be careful about simply using copy-and-paste with the hcluster package's brief tutorial, notably in that if you call pylab.savefig() after several types of dendrogram drawing shown in the tutorial, i.e.
distMat = # whatever distance matrix you have
dendrogram( linkage( distMat ) )
pylab.savefig( "exampleDendrogram.png" )
dendrogram( linkage( distMat, method="complete" ) ) #instead of default "single"
pylab.savefig( "exampleDendrogram.png" )
Then exampleDendrogram.png will contain both the single-linkage dendrogram and the complete-linkage dendrogram in the same figure, and they will likely cross-cross and look like a mess.
If you're as stupid as me, you'll spend 30-180 minutes in confusion about how to properly use hcluster, when it's actually just a matter of resetting matplotlib between dendrogram calls:
distMat = # whatever distance matrix you have
dendrogram( linkage( distMat ) )
pylab.savefig( "exampleDendrogram1.png" )
pylab.cla()
dendrogram( linkage( distMat, method="complete" ) ) #instead of default "single"
pylab.savefig( "exampleDendrogram2.png" )
Now, the resulting dendrogram image files will look like what you expected them to look like.
I have been facing the same problem. You can use one of the below methods
Use plt.show() :
use plt.show() after dedogram, this will show the plot
using plt.show
Use %matplotlib inline intially in jupyter notebook. this will show the plot after execution.
Using matplotlib inline