jupyter matplotlib interactive exit - python

I have plotted an interactive figure, run the cell, and now all my keyboard presses are being captured by the interactive plot. How do I exist this without the mouse?
Shift-enter sort of works, but it seems to require there be a cell below the plot.
I think matplotlib recommends ctrl-w but as I am in a web browser (Jupyter) that would just close my tab.
The plot is within the cell.
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
fig,ax = plt.subplots(1,1)
x = np.linspace(0, 1, 100)
y = np.random.random(size=(100, 1))
ax.plot(x, y)
If you run this, you can't then use j,k to move up and down cells until you exit the interactive plot.
This is just a code snippet, in the actual code I am updating the plot from within a loop which is why I'm using interactive mode.

You can add another short-key to close the plot. This can be accomplished via the rcParams.
So let's say you want to close the plot by pressing q.
%matplotlib notebook
import matplotlib.pyplot as plt
plt.rcParams["keymap.quit"] = "ctrl+w", "cmd+w", "q"
plt.plot([1,3,2])
Now pressing q will exit the interactive plot, such that you can navigate as usual through the notebook. E.g. to then get to the next cell, which would already be active, just press Enter.
Eventually you would probably want to change your matplotlib rc file with this option not to have to type it in every time you start a notebook.

Related

Cursor location and pixel value in a Jupyter notebook inline image

I am using Python 2.7.x with a Jupyter Notebook, matplotlib and %pylab backend with the inline flag
%pylab inline
to print images below active cells. I would like to be able to move my cursor over an image and know it's location and pixel value An example could be:
(x,y,val) = (123,285,230)
but I am not particular about any of the specifics of this example.
The %matplotlib inline backend displays the plot outputs as png images. It may be possible to write some JavaScript for the Jupyter notebook to obtain the color and pixel on mouse over an image in the cell output.
However it may be much easier to just use the %matplotlib notebook backend, which keeps the matplotlib figure alive when plotting it to the output and therefore the usual built-in mouseover functionality is readily available.
Note the picker in the lower right corner of the image, which displays x,y and the value of the current pixel.
To expand on ImportanceOfBeingErnest's answer, you can use mpl_connect to provide a callback on your clicks and ipywidgets to show an output of your callback. If needed, you can break up the code in different cells.
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
import ipywidgets as wdg # Using the ipython notebook widgets
# Create a random image
a = np.random.poisson(size=(12,15))
fig = plt.figure()
plt.imshow(a)
# Create and display textarea widget
txt = wdg.Textarea(
value='',
placeholder='',
description='event:',
disabled=False
)
display(txt)
# Define a callback function that will update the textarea
def onclick(event):
txt.value = str(event) # Dynamically update the text box above
# Create an hard reference to the callback not to be cleared by the garbage collector
ka = fig.canvas.mpl_connect('button_press_event', onclick)

Why is Jupyter Notebook creating duplicate plots when making updating plots

I'm trying to make plots in a Jupyter Notebook that update every second or so. Right now, I just have a simple code which is working:
%matplotlib inline
import time
import pylab as plt
import numpy as np
from IPython import display
for i in range(10):
plt.close()
a = np.random.randint(100,size=100)
b = np.random.randint(100,size=100)
fig, ax = plt.subplots(2,1)
ax[0].plot(a)
ax[0].set_title('A')
ax[1].plot(b)
ax[1].set_title('B')
display.clear_output(wait=True)
display.display(plt.gcf())
time.sleep(1.0)
Which updated the plots I have created every second. However, at the end, there is an extra copy of the plots:
Why is it doing this? And how can I make this not happen? Thank you in advance.
The inline backend is set-up so that when each cell is finished executing, any matplotlib plot created in the cell will be displayed.
You are displaying your figure once using the display function, and then the figure is being displayed again automatically by the inline backend.
The easiest way to prevent this is to add plt.close() at the end of the code in your cell.
Another alternative would be to add ; at the end of the line! I am experiencing the same issue with statsmodels methods to plot the autocorrelation of a time series (statsmodels.graphics.tsaplot.plot_acf()):
from statsmodels.graphics.tsaplots import plot_acf
plot_acf(daily_outflow["count"]);
Despite using %matplotlib inline, it's not working for some libraries, such as statsmodels. I recommend always use plt.show() at the end of your code.

Jupyter (IPython) notebook: plot in the qt mode + prompt raw_input()

I am trying to plot in Jupyter notebook (Python 2.7), then prompt user for input, save it and then change the plot (this is a crucial point: I don't want to create a new plot, I need to modify the old one after user input). This completely fails to work. Instead of showing the figure and then prompting for input, it opens the figure window, but freezes (doesn't display anything) until I respond to the raw_input() prompt. Only then it plots.
Simple version of the code to show the error:
import matplotlib.pyplot as plt
%matplotlib qt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1,2,3],[1,2,3])
plt.show(block=False)
my_input = raw_input()
This bug only appears when I use %matplotlib qt, but I have to use it, because with %matplotlib inline I am unable to modify the plot after it was displayed (at least as far as I am aware).
In fact, I noticed that it freezes until the end of the cell execution, even if it is just time.sleep().
Am I missing something? Some settings of how matplotlib displays figures?
Since I am using Python3 I had to change raw_input() to input() and removed the block=False because IPython told me that this is an unknown attribute.
This should work nice:
import matplotlib.pyplot as plt
%matplotlib inline
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1,2,3], [1,2,3])
plt.show()
my_input = input()
Fur sure, you need to adapt this back to Python2 to fit your needs.

Prints value when clicked on but line isn't created?

I'm currently learning the matplotlib library on python 3.4. I'm practicing on a code where the user is supposed to interact with the plot only by clicking on it. When the click happens somewhere on the plot two things are supposed to happen: print out the y value and create a horizontal line in the plot where the click happened.
What I'm getting when I click somewhere on the plot is that the print happens as desired but the horizontal line shows up only if I press F (which fulls screen the plot). In other words, the line is created when I click on the plot but it doesn't appear untill I press F. Any ideas why it's happening?
The code:
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(np.random.rand(10))
def pick(event):
plt.hlines(event.ydata,event.xdata-
0.2,event.xdata+0.2,colors='r',linestyle='solid')
print('Y coord = %f'%event.ydata)
fig.canvas.mpl_connect('button_press_event',pick)
plt.show()
You need to use interactive mode to update the plot after each click. Use plt.ion() before plt.show().

Matplotlib figure window disappears when in interactive mode [duplicate]

This question already has answers here:
Interactive(?) plotting in Spyder with matplotlib
(2 answers)
Closed 3 months ago.
I need to use interactive mode when plotting with matplotlib (it should be a script, not python or ipython console). But setting plt.ion() causes a strange bug (?). When I try to plot my figure (I don't think it really matters, what I do exactly, because in non-interactive mode it works perfectly fine) I don't see it - I get a blank grey window for split-second, which momentarily disappears and the programme exits.
If I explicitly add plt.draw() (and plt.pause(1) to see the result), I see that the figure appears as expected. If I do the same after modifications I want to do to the figure when it is visible, the figure changes. But the window still disappears after the pause is over.
I run it in Spyder with Qt4Agg as a backend under Ubuntu. Tried running the script from terminal as python my_script.py, the result is identical.
What could be the problem? How do I stop the figure from disappearing when in interactive mode?
UPDATE
Working example:
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
x = np.linspace(1, 10)
y = np.sin(x)
plt.plot(x, y)
plt.draw()
plt.pause(1)
If I run this code I see the sine plot for 1 second, then the window disappears.
UPDATE 2
I found a solution here: https://stackoverflow.com/a/10724654/1304161
If I set the run options in Spyder correctly, it works perfectly fine. Although running it in gnome-terminal doesn't work, I don't really need it. Hopefully, there won't be a problem with this when it becomes a part of a GUI app...
I found a solution here: https://stackoverflow.com/a/10724654/1304161
If I set the run options in Spyder correctly, it works perfectly fine. Although running it in gnome-terminal doesn't work, I don't really need it. Hopefully, there won't be a problem with this when it becomes a part of a GUI app. I will be back, if it will be a problem then :)
You can make it work by adding these two lines at the end:
plt.ioff()
plt.show()
So this program works fine:
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
x = np.linspace(1, 10)
y = np.sin(x)
plt.plot(x, y)
plt.draw()
plt.ioff()
plt.show()
To display multiple figures at different times, you can use code.interact(local=locals()), after plt.show() to pause the Python interpreter until a Ctrl-Z is pressed in the Python Shell:
import code
import matplotlib.pyplot as plt
import numpy as np
# Start pyplot's "interactive mode" which lets you run plt.show multiple times
plt.ion()
x = np.linspace(1, 10)
y = np.sin(x)
# PLOT #1 - displayed
plt.plot(x, y)
plt.draw()
plt.show()
# Wait for figure to be closed AND Ctrl-Z pressed in Python Shell
code.interact(local=locals())
print("Some more code can go here...")
# PLOT #2 - displayed
plt.plot(x, y)
plt.show()
# Wait for figure to be closed AND Ctrl-Z pressed in Python Shell
code.interact(local=locals())

Categories