How do I get interactive plots again in Spyder/IPython/matplotlib? - python

I upgraded from Python(x,y) 2.7.2.3 to 2.7.6.0 in Windows 7 (and was happy to see that I can finally type function_name? and see the docstring in the Object Inspector again) but now the plotting doesn't work as it used to.
Previously (Spyder 2.1.9, IPython 0.10.2, matplotlib 1.2.1), when I plotted this script, for instance, it would plot the subplots side-by-side in an interactive window:
Now (Spyder 2.2.5, IPython 1.2.0, Matplotlib 1.3.1) when I try to plot things, it does the subplots as tiny inline PNGs, which is a change in IPython:
So I went into options and found this:
which seems to say that I can get the old interactive plots back, with the 4 subplots displayed side-by-side, but when I switch to "Automatic", and try to plot something, it does nothing. No plots at all.
If I switch this drop-down to Qt, or uncheck "Activate support", it only plots the first subplot, or part of it, and then stops:
How do I get the old behavior of 4 side-by-side subplots in a single figure that I can interact with?

Change the backend to automatic:
Tools > preferences > IPython console > Graphics > Graphics backend > Backend: Automatic
Then close and open Spyder.

You can quickly control this by typing built-in magic commands in Spyder's IPython console, which I find faster than picking these from the preferences menu. Changes take immediate effect, without needing to restart Spyder or the kernel.
To switch to "automatic" (i.e. interactive) plots, type:
%matplotlib auto
then if you want to switch back to "inline", type this:
%matplotlib inline
(Note: these commands don't work in non-IPython consoles)
See more background on this topic: Purpose of "%matplotlib inline"

After applying : Tools > preferences > Graphics > Backend > Automatic Just restart the kernel
And you will get Interactive Plot.

As said in the comments, the problem lies in your script. Actually, there are 2 problems:
There is a matplotlib error, I guess that you're passing an argument as None somewhere. Maybe due to the defaultdict ?
You call show() after each subplot. show() should be called once at the end of your script. The alternative is to use interactive mode, look for ion in matplotlib's documentation.

This is actually pretty easy to fix and doesn't take any coding:
1.Click on the Plots tab above the console.
2.Then at the top right corner of the plots screen click on the options button.
3.Lastly uncheck the "Mute inline plotting" button
Now re-run your script and your graphs should show up in the console.

For most mathematical coding, I use this website and their services as they offer examples for every subject and their support is super helpful:
https://labdeck.com/application-examples-screenshots/
If your want you graph to change by a variable amount then the code you want to use is
import matplotlib.pyplot as plt
import time
vec1=[1, 2, 3, 4, 5]
vec2py=[10, 12, 9, 11, 13]
plt.show()
axes = plt.gca()
axes.set_xlim(0, 6)
axes.set_ylim(5, 50)
plt.xlabel('x - axis')
plt.ylabel('y - axis')
plt.title('Example 1')
plt.grid()
line,= axes.plot(vec1,vec2py,color='red',lw=1)
for x in range(0,10):
vec2py = [x + 2 for x in vec2py]
line.set_ydata(vec2py)
plt.draw()
plt.pause(1e-17)
time.sleep(0.5)
plt.show()
You will have to change x for how many iterations of the graph you want and how long you want it to run for and also the +2 in the vec2py line for what variable amount you want to change it by. Naturally the code is a template and you can make any aesthetical changes. This code file is found under displaying dynamic graphs which is under python programming in the link above.
If you want to display a constant rely of information from a source, I'm not to sure how to do that but the website mention before does have an example, however it isn't in python but in a simplified form of C++.If you do want to see it then the link is https://labdeck.com/examples/dsp-ecg-processing/ecg-9-leads-graphs.pdf?01a96f&01a96f and its under ECG 9 Leads graphs in ECG on the link at the start.
The graph can be shown as in a document or independently from the document.
PS this is for people who have the same question but not necessarily the same scenario as I think this will help more.

Related

When is plt.show() required to show a plot and when is it not?

Since the following code will show a plot without plt.show(), what is the point of plt.show()?
Please tell me when plt.show() is required as this would allow me to appreciate the intricacy of matplotlib better.
N.B.: I'm using this in Spyder (Anaconda)
import matplotlib.pyplot as plt
plt.subplot(211) # the first subplot in the first figure
plt.plot([1, 2, 3])
To require or not required depending on where your script is.
There are 2 contexts.
Matplotlib is used in a terminal or scripts, plt.show() is a must.
Matplotlib is used in a IPython shell or a notebook (ex: Kaggle), plt.show() is unnecessary.
It seems either you are in an interactive mode or are using a JuPyter notebook, in both the cases plt.show() being rendered redundant (check the bold highlighted doc below)
From the official docs
Display a figure. When running in ipython with its pylab mode, display all figures and return to the ipython prompt.
In non-interactive mode, display all figures and block until the figures have been closed; in interactive mode it has no effect unless figures were created prior to a change from non-interactive to interactive mode (not recommended). In that case it displays the figures but does not block.
A single experimental keyword argument, block, may be set to True or False to override the blocking behavior described above.

Pycharm jupyter cell background

I'm using PyCharm with Darcula theme and Jupyter notebook from anaconda package.
I faced a problem that Darcula theme is inconvinient to use with Jupyter notebook
For example, pandas plot's axis is not readable.
I tried to find out, how to change notebook cell background, but looks like that there is no possibility to do that.
Of course, I can change PyCharm theme to another, but I used to work under this theme.
And of course, I can change background of plot in code, but it is inconvinient to change background for each plots (for example, if I work with ready notebook)
Can I change cells background or the only way is to change theme to another?
Probably a bit too late, but here is a solution for future reference:
1 - Go to PyCharm > Preferences and type in the search bar "Invert image outputs for dark themes"
2 - Go to Language & Frameworks > Jupyter and uncheck the "Invert image outputs for dark themes" box.
3 - Restart PyCharm for option to take effect.
Per https://stackoverflow.com/a/40371037/2529760, you can use
fig = plt.figure()
fig.patch.set_facecolor('white')
or
plt.gca().patch.set_facecolor('white')
to force a white background beneath the axis labels on a per-plot basis. You can use
plt.rcParams['figure.facecolor'] = 'white'
to achieve this on a per-notebook basis.
To change this setting globally, normally you can edit the matplotlibrc file, but it appears Jupyter overrides this to some degree. Following https://nbviewer.jupyter.org/github/mgeier/python-audio/blob/master/plotting/matplotlib-inline-defaults.ipynb, you can create a file ipython_kernel_config.py at the correct location (~/.ipython/profile_default by default) containing the line
c.InlineBackend.rc = {'figure.facecolor': 'white'}
Any of these options will ensure the plot has a white background so the text is legible.
You can try the seaborn package:
import seaborn as sns
sns.set_context('notebook')
sns.set_style('white')
It will change the output plot background to white.
The temporary workaround for me is to explicitly call plt.show() at the end of cell.
I am also looking for a better solution.

Why is matplotlib plot produced from ipython notebook slightly different from terminal version?

I have a strange issue. Using IPython Notebook, I created a quite extensive script using pandas and matplotlib to create a number of charts.
When my tinkering was finished, I copied (and cleaned) the code into a standalone python script (so that I can push it into the svn and my paper co-authors can create the charts as well).
For convenience, I import the standalone python script into the notebook again and create a number of charts:
import create_charts as cc
df = cc.read_csv_files("./data")
cc.chart_1(df, 'fig_chart1.pdf')
...
Strange enough, the .pdf file I get using the above method is slightly different from the .pdf file I get when I run my standalone python script from my Windows 7 terminal. The most notable difference is that in a particular chart the legend is located in the upper corner instead of the lower corner. But there are other small diferences as well (bounding box size, font seems slightly different)
What could be the cause of this. And how can I troubleshoot it?
(I already shut down my notebook and restarted it, to reimport my create_charts script and rule out any unsaved changes)
My terminal reports I am using Python 2.7.2, and pip freeze | grep ipython reports ipython 0.13.1
To complete Joe answer, the inlinebackend (IPython/kernel/zmq/pylab/backend_inline.py) have some default matplotlib parameters :
# The typical default figure size is too large for inline use,
# so we shrink the figure size to 6x4, and tweak fonts to
# make that fit.
rc = Dict({'figure.figsize': (6.0,4.0),
# play nicely with white background in the Qt and notebook frontend
'figure.facecolor': 'white',
'figure.edgecolor': 'white',
# 12pt labels get cutoff on 6x4 logplots, so use 10pt.
'font.size': 10,
# 72 dpi matches SVG/qtconsole
# this only affects PNG export, as SVG has no dpi setting
'savefig.dpi': 72,
# 10pt still needs a little more room on the xlabel:
'figure.subplot.bottom' : .125
}, config=True,
help="""Subset of matplotlib rcParams that should be different for the
inline backend."""
)
As this is not obvious to everyone, you can set it in config through c.InlineBackend.rc.
[Edit] precise info about configurability.
IPython have the particularity that most of the classes have properties which default values can be configured. Those are often refered as Configurable (uppercase C), those property can easily be recognize in the code as they are declared like so before __init__:
property = A_Type( <default_value>, config=True , help="a string")
You can overwrite those properties in IPython configuration files (which one depends on what you want to do) by doing
c.ClassName.propertie_name = value
Here as it is a dict you could do
#put your favorite matplotlib config here.
c.InlineBackend.rc = {'figure.facecolor': 'black'}
I guess an empty dict would allow inline backend to use matplotlib defaults.
Extending Matt's answer (lots of credit to him, but I think the answers can be less complex), this is how I eventually solved it.
(a) I looked up ipython's default matplotlib settings in C:\Python27\Lib\site-packages\IPython\zmq\pylab\backend_inline.py (see Matt's answer).
(b) and overwrote them with the values as set in the terminal version (I used print mpl.rcParams['figure.figsize'] etc. to find out) by inserting the following code in my script:
import matplotlib as mpl
#To make sure we have always the same matplotlib settings
#(the ones in comments are the ipython notebook settings)
mpl.rcParams['figure.figsize']=(8.0,6.0) #(6.0,4.0)
mpl.rcParams['font.size']=12 #10
mpl.rcParams['savefig.dpi']=100 #72
mpl.rcParams['figure.subplot.bottom']=.1 #.125
The font size issues are due to differences in the dpi. I'd guess the slightly different size of the figure (in pixels) changes the "best" location for the legend, as well.
The default dpi a figure is displayed at is 80, while savefig defaults to 100. This means that by default, matplotlib figures will look slightly different when saved compared to what's displayed on the screen.
I don't know for sure, but I'm guessing that ipython notebooks set the dpi to something other than 100 (most likely 80) and use that when saving figures.
Try doing savefig('filename.pdf', dpi=80) in your standalone script.

matplotlib draw showing nothing

I'm using python's matplotlib to do some contours using contour and contourf functions. They all work fine when using show, but when I try to use draw() inside a method, I get the matplotlib window but not graph. The show() call will be done much later on the code and in a different method, and I would like to show one graph at the moment when it's done with draw(), not having to wait until the much later show(). What I'm doing wrong?
Thanks.
Have you turned interactive mode on using ion()? The following works for me on OSX, using the Tk backend and running from the shell's command line:
import matplotlib.pyplot as plt
plt.ion()
plt.figure()
for i in range(10):
plt.plot([i], [i], 'o')
plt.draw()
raw_input("done >>")
That is, as it does each loop, you see the plot change (i.e., it gets redrawn) as each point is added. Here, btw, if I instead call plt.ioff(), I don't see the figure or any updates.
IIRC ,You should be able call fig.show() multiple times. Also, check out using ipython (ipython -pylab) and http://matplotlib.sourceforge.net/users/shell.html

Unable to specify matplotlib backend in Anaconda Spyder [duplicate]

I upgraded from Python(x,y) 2.7.2.3 to 2.7.6.0 in Windows 7 (and was happy to see that I can finally type function_name? and see the docstring in the Object Inspector again) but now the plotting doesn't work as it used to.
Previously (Spyder 2.1.9, IPython 0.10.2, matplotlib 1.2.1), when I plotted this script, for instance, it would plot the subplots side-by-side in an interactive window:
Now (Spyder 2.2.5, IPython 1.2.0, Matplotlib 1.3.1) when I try to plot things, it does the subplots as tiny inline PNGs, which is a change in IPython:
So I went into options and found this:
which seems to say that I can get the old interactive plots back, with the 4 subplots displayed side-by-side, but when I switch to "Automatic", and try to plot something, it does nothing. No plots at all.
If I switch this drop-down to Qt, or uncheck "Activate support", it only plots the first subplot, or part of it, and then stops:
How do I get the old behavior of 4 side-by-side subplots in a single figure that I can interact with?
Change the backend to automatic:
Tools > preferences > IPython console > Graphics > Graphics backend > Backend: Automatic
Then close and open Spyder.
You can quickly control this by typing built-in magic commands in Spyder's IPython console, which I find faster than picking these from the preferences menu. Changes take immediate effect, without needing to restart Spyder or the kernel.
To switch to "automatic" (i.e. interactive) plots, type:
%matplotlib auto
then if you want to switch back to "inline", type this:
%matplotlib inline
(Note: these commands don't work in non-IPython consoles)
See more background on this topic: Purpose of "%matplotlib inline"
After applying : Tools > preferences > Graphics > Backend > Automatic Just restart the kernel
And you will get Interactive Plot.
As said in the comments, the problem lies in your script. Actually, there are 2 problems:
There is a matplotlib error, I guess that you're passing an argument as None somewhere. Maybe due to the defaultdict ?
You call show() after each subplot. show() should be called once at the end of your script. The alternative is to use interactive mode, look for ion in matplotlib's documentation.
This is actually pretty easy to fix and doesn't take any coding:
1.Click on the Plots tab above the console.
2.Then at the top right corner of the plots screen click on the options button.
3.Lastly uncheck the "Mute inline plotting" button
Now re-run your script and your graphs should show up in the console.
For most mathematical coding, I use this website and their services as they offer examples for every subject and their support is super helpful:
https://labdeck.com/application-examples-screenshots/
If your want you graph to change by a variable amount then the code you want to use is
import matplotlib.pyplot as plt
import time
vec1=[1, 2, 3, 4, 5]
vec2py=[10, 12, 9, 11, 13]
plt.show()
axes = plt.gca()
axes.set_xlim(0, 6)
axes.set_ylim(5, 50)
plt.xlabel('x - axis')
plt.ylabel('y - axis')
plt.title('Example 1')
plt.grid()
line,= axes.plot(vec1,vec2py,color='red',lw=1)
for x in range(0,10):
vec2py = [x + 2 for x in vec2py]
line.set_ydata(vec2py)
plt.draw()
plt.pause(1e-17)
time.sleep(0.5)
plt.show()
You will have to change x for how many iterations of the graph you want and how long you want it to run for and also the +2 in the vec2py line for what variable amount you want to change it by. Naturally the code is a template and you can make any aesthetical changes. This code file is found under displaying dynamic graphs which is under python programming in the link above.
If you want to display a constant rely of information from a source, I'm not to sure how to do that but the website mention before does have an example, however it isn't in python but in a simplified form of C++.If you do want to see it then the link is https://labdeck.com/examples/dsp-ecg-processing/ecg-9-leads-graphs.pdf?01a96f&01a96f and its under ECG 9 Leads graphs in ECG on the link at the start.
The graph can be shown as in a document or independently from the document.
PS this is for people who have the same question but not necessarily the same scenario as I think this will help more.

Categories