Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #79411 > unrolled thread
| Started by | Peter Pearson <pkpearson@nowhere.invalid> |
|---|---|
| First post | 2014-10-22 04:57 +0000 |
| Last post | 2014-10-22 16:38 +0000 |
| Articles | 3 — 2 participants |
Back to article view | Back to comp.lang.python
Matplotlib: getting a figure to show without plt.show() Peter Pearson <pkpearson@nowhere.invalid> - 2014-10-22 04:57 +0000
Re: Matplotlib: getting a figure to show without plt.show() Peter Otten <__peter__@web.de> - 2014-10-22 12:38 +0200
Re: Matplotlib: getting a figure to show without plt.show() Peter Pearson <pkpearson@nowhere.invalid> - 2014-10-22 16:38 +0000
| From | Peter Pearson <pkpearson@nowhere.invalid> |
|---|---|
| Date | 2014-10-22 04:57 +0000 |
| Subject | Matplotlib: getting a figure to show without plt.show() |
| Message-ID | <caorpjFo1amU1@mid.individual.net> |
I'm using Matplotlib to present a "control" window with clickable
buttons, and to plot things in another window when you click buttons,
in the style of the code below. I'm ashamed of the stinky way I
use "first" to call plt.show the first time data are plotted but then
to call fig.canvas.draw for subsequent data plots. Can someone tell
me the right way?
If I call plt.show every time, then after about 40 plots I get
"RuntimeError: maximum recursion depth exceeded while calling a Python
object", which makes sense because I'm getting one layer deeper in
callbacks with every plot (plt.show doesn't return). But if I call
fig.canvas.draw every time, the window for the data plot never appears
on my screen.
Thanks for any suggestions.
##############################
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
def callback(event):
global n, first
fig = plt.figure(2)
fig.clear()
plt.plot([0,1],[0,n])
n += 1 # (Pretending something changes from one plot to the next.)
if first:
first = False
plt.show()
else:
fig.canvas.draw()
global n, first
n = 0
first = True
fig = plt.figure(1)
quit_button = Button(plt.axes([.1,.3,.4,.2]), "Quit")
quit_button.on_clicked(lambda x: plt.close("all"))
plot_button = Button(plt.axes([.1,.1,.4,.2]), "Plot")
plot_button.on_clicked(callback)
plt.show()
##############################
--
To email me, substitute nowhere->runbox, invalid->com.
[toc] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2014-10-22 12:38 +0200 |
| Message-ID | <mailman.15064.1413974302.18130.python-list@python.org> |
| In reply to | #79411 |
Peter Pearson wrote:
> I'm using Matplotlib to present a "control" window with clickable
> buttons, and to plot things in another window when you click buttons,
> in the style of the code below. I'm ashamed of the stinky way I
> use "first" to call plt.show the first time data are plotted but then
> to call fig.canvas.draw for subsequent data plots.
> def callback(event):
> global n, first
> fig = plt.figure(2)
> fig.clear()
> plt.plot([0,1],[0,n])
> n += 1 # (Pretending something changes from one plot to the next.)
> if first:
> first = False
> plt.show()
> else:
> fig.canvas.draw()
> Can someone tell me the right way?
I don't see what's wrong with doing something different the first time
around.
> If I call plt.show every time, then after about 40 plots I get
> "RuntimeError: maximum recursion depth exceeded while calling a Python
> object", which makes sense because I'm getting one layer deeper in
> callbacks with every plot (plt.show doesn't return). But if I call
> fig.canvas.draw every time, the window for the data plot never appears
> on my screen.
If your backend uses tkinter, then the problem may be that plt.show() starts
a new mainloop. Over here this causes the script to hang on termination.
Through try-and-error I came up with
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
def callback(event):
global n, fig2
if fig2 is None:
fig2 = plt.figure(2)
fig2.clear()
fig2.gca().plot([0, .5, 1], [0, 1/n, 1])
fig2.show()
n += 1
n = 1
fig2 = None
plt.figure(1)
quit_button = Button(plt.axes([.1, .3, .4, .2]), "Quit")
quit_button.on_clicked(lambda x: plt.close("all"))
plot_button = Button(plt.axes([.1, .1, .4, .2]), "Plot")
plot_button.on_clicked(callback)
plt.show()
If you don't mind that the second window shows up immediately you can modify
that to
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
def callback(event):
global n
fig2.clear()
fig2.gca().plot([0, .5, 1], [0, 1/n, 1])
fig2.show()
n += 1
n = 1
plt.figure(1)
quit_button = Button(plt.axes([.1, .3, .4, .2]), "Quit")
quit_button.on_clicked(lambda x: plt.close("all"))
plot_button = Button(plt.axes([.1, .1, .4, .2]), "Plot")
plot_button.on_clicked(callback)
fig2 = plt.figure(2)
plt.show()
and thus avoid the special case.
As I'm not an expert for matplotlib you might also post your question on the
matplotlib mailing list.
[toc] | [prev] | [next] | [standalone]
| From | Peter Pearson <pkpearson@nowhere.invalid> |
|---|---|
| Date | 2014-10-22 16:38 +0000 |
| Message-ID | <caq4rpF3vveU1@mid.individual.net> |
| In reply to | #79427 |
On Wed, 22 Oct 2014 12:38:02 +0200, Peter Otten wrote:
> Peter Pearson wrote:
[snip]
>> def callback(event):
>> global n, first
>> fig = plt.figure(2)
>> fig.clear()
>> plt.plot([0,1],[0,n])
>> n += 1 # (Pretending something changes from one plot to the next.)
>> if first:
>> first = False
>> plt.show()
>> else:
>> fig.canvas.draw()
>>
>> Can someone tell me the right way?
[snip]
> def callback(event):
> global n, fig2
>
> if fig2 is None:
> fig2 = plt.figure(2)
>
> fig2.clear()
> fig2.gca().plot([0, .5, 1], [0, 1/n, 1])
> fig2.show()
Thank you for pointing out two useful things:
* I like fig2.gca().plot better than plt.plot, since it makes it
clear that I'm talking about fig2 and not some other part of the
vast and inscrutable plt kingdom.
* fig2.show is different from plt.show, and in fact this solves my
problem exactly, since fig2.show returns immediately.
By the way, I will dispense with your "if fig2 is None" test. In real
life, I say something like fig2 = plt.figure("Packet Sizes"). If a
figure named "Packet Sizes" doesn't exist, plt.figure creates it,
otherwise it returns a pointer to the existing figure -- *and* it titles
the figure's window with "Packet Sizes" rather than "2".
[snip]
> As I'm not an expert for matplotlib you might also post your question on the
> matplotlib mailing list.
Sound advice. Next time. Thanks again.
--
To email me, substitute nowhere->runbox, invalid->com.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web