Portable method to generate matplotlib interactive figures in Windows, Linux, Spyder, command line
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I'm looking for a a method to generate interactive figures that works in Windows and Linux, commandline or Spyder. For example, the following script:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, tight_layout=True)
#plt.ion() # doesn't seem to do much
ax.plot([0,1,2],[0,3,2])
fig.show()
#plt.show(block=False) # similar behavior as fig.show()
#plt.pause(1)
input('Press enter to quit.')
Behavior for different environments:
Linux command line: plot window shows up and is responsive while the script waits for user input. The window stays even if the program continues running (not in this short example), although the zoom buttons don't work anymore. This is desired behavior.
Windows command line: an empty nonresponsive plot window shows up, which disappears when the program ends. Adding
plt.pause()
results in an interactive plot, but it is only responsive for the specified number of seconds.Linux/Windows Spyder with iPython, configured for automatic plots: figures show up and are responsive, but only after the script finishes.
Linux/Windows Spyder, configured for inline plots: plots show up after the script finishes, but with warnings due to the
tight_layout=True
parameter: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect. and matplotlib is currently using a non-GUI backend.
(Note that I needtight_layout
because otherwise often axis labels are clipped or figures with multiple subplots have bad margins.)Linux/Windows Spyder, inline plots: with
plt.plot(...); plt.show()
(rather than thefig.plot(...); fig.show()
object-oriented way), the inline plots show up during program execution.
How can I write code that generates interactive plots during program execution (possibly while waiting for a keypress) that will run correctly from the Windows command line, Linux command line, and Spyder?
Edit: plt.show()
instead of fig.show()
will result in a plot being shown correctly, but outside IPython, it blocks execution of the script until I click the close button of the figure window. This is rather cumbersome when there are multiple figures or when the calculation is not yet finished. And plt.show(block=False)
has the same behavior as fig.show()
.
I'm using an noncustomized Anaconda 5.1 environment with Python 3.6.4, matplotlib 2.1.2, spyder 3.2.6. In Spyder: Tools > Preferences > IPython > Backend, set to 'inline' or 'automatic' (and restarting kernel after changing this setting.)
python matplotlib spyder
add a comment |
I'm looking for a a method to generate interactive figures that works in Windows and Linux, commandline or Spyder. For example, the following script:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, tight_layout=True)
#plt.ion() # doesn't seem to do much
ax.plot([0,1,2],[0,3,2])
fig.show()
#plt.show(block=False) # similar behavior as fig.show()
#plt.pause(1)
input('Press enter to quit.')
Behavior for different environments:
Linux command line: plot window shows up and is responsive while the script waits for user input. The window stays even if the program continues running (not in this short example), although the zoom buttons don't work anymore. This is desired behavior.
Windows command line: an empty nonresponsive plot window shows up, which disappears when the program ends. Adding
plt.pause()
results in an interactive plot, but it is only responsive for the specified number of seconds.Linux/Windows Spyder with iPython, configured for automatic plots: figures show up and are responsive, but only after the script finishes.
Linux/Windows Spyder, configured for inline plots: plots show up after the script finishes, but with warnings due to the
tight_layout=True
parameter: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect. and matplotlib is currently using a non-GUI backend.
(Note that I needtight_layout
because otherwise often axis labels are clipped or figures with multiple subplots have bad margins.)Linux/Windows Spyder, inline plots: with
plt.plot(...); plt.show()
(rather than thefig.plot(...); fig.show()
object-oriented way), the inline plots show up during program execution.
How can I write code that generates interactive plots during program execution (possibly while waiting for a keypress) that will run correctly from the Windows command line, Linux command line, and Spyder?
Edit: plt.show()
instead of fig.show()
will result in a plot being shown correctly, but outside IPython, it blocks execution of the script until I click the close button of the figure window. This is rather cumbersome when there are multiple figures or when the calculation is not yet finished. And plt.show(block=False)
has the same behavior as fig.show()
.
I'm using an noncustomized Anaconda 5.1 environment with Python 3.6.4, matplotlib 2.1.2, spyder 3.2.6. In Spyder: Tools > Preferences > IPython > Backend, set to 'inline' or 'automatic' (and restarting kernel after changing this setting.)
python matplotlib spyder
There are explanation of (almost) all observed behaviour. However, what is the problem you want to solve? Why not simply useplt.show()
to generate the figure window?
– ImportanceOfBeingErnest
Nov 16 '18 at 14:39
@ImportanceOfBeingErnest I'd like to keep figure windows in view while program execution continues.plt.show()
is blocking the program until the window is closed andplt.show(block=False)
suffers from the same problems asfig.show()
.
– Han-Kwang Nienhuys
Nov 19 '18 at 10:04
How about checking in your code which platform you're running on and given this condition running a specific part of code? For Spyder, you can check the environmental variables and check if the Spyder's ones exist.
– arudzinska
Nov 19 '18 at 10:10
@arudzinska I experimented a bit with solutions that at least work for one environment, but I've not found something that allows interactive figures to persist in Windows after interaction. Withplt.pause(1)
in a loop that runs until a keypress, the figure window steals the focus every second (in Linux, not in Windows 7). I guess that I'll have to live with plots becoming interactive in Spyder after program termination and no solution for Windows command line.
– Han-Kwang Nienhuys
Nov 19 '18 at 13:09
Update: I wrote my own solution with environment detection. Does not work well in all cases, though.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:22
add a comment |
I'm looking for a a method to generate interactive figures that works in Windows and Linux, commandline or Spyder. For example, the following script:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, tight_layout=True)
#plt.ion() # doesn't seem to do much
ax.plot([0,1,2],[0,3,2])
fig.show()
#plt.show(block=False) # similar behavior as fig.show()
#plt.pause(1)
input('Press enter to quit.')
Behavior for different environments:
Linux command line: plot window shows up and is responsive while the script waits for user input. The window stays even if the program continues running (not in this short example), although the zoom buttons don't work anymore. This is desired behavior.
Windows command line: an empty nonresponsive plot window shows up, which disappears when the program ends. Adding
plt.pause()
results in an interactive plot, but it is only responsive for the specified number of seconds.Linux/Windows Spyder with iPython, configured for automatic plots: figures show up and are responsive, but only after the script finishes.
Linux/Windows Spyder, configured for inline plots: plots show up after the script finishes, but with warnings due to the
tight_layout=True
parameter: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect. and matplotlib is currently using a non-GUI backend.
(Note that I needtight_layout
because otherwise often axis labels are clipped or figures with multiple subplots have bad margins.)Linux/Windows Spyder, inline plots: with
plt.plot(...); plt.show()
(rather than thefig.plot(...); fig.show()
object-oriented way), the inline plots show up during program execution.
How can I write code that generates interactive plots during program execution (possibly while waiting for a keypress) that will run correctly from the Windows command line, Linux command line, and Spyder?
Edit: plt.show()
instead of fig.show()
will result in a plot being shown correctly, but outside IPython, it blocks execution of the script until I click the close button of the figure window. This is rather cumbersome when there are multiple figures or when the calculation is not yet finished. And plt.show(block=False)
has the same behavior as fig.show()
.
I'm using an noncustomized Anaconda 5.1 environment with Python 3.6.4, matplotlib 2.1.2, spyder 3.2.6. In Spyder: Tools > Preferences > IPython > Backend, set to 'inline' or 'automatic' (and restarting kernel after changing this setting.)
python matplotlib spyder
I'm looking for a a method to generate interactive figures that works in Windows and Linux, commandline or Spyder. For example, the following script:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, tight_layout=True)
#plt.ion() # doesn't seem to do much
ax.plot([0,1,2],[0,3,2])
fig.show()
#plt.show(block=False) # similar behavior as fig.show()
#plt.pause(1)
input('Press enter to quit.')
Behavior for different environments:
Linux command line: plot window shows up and is responsive while the script waits for user input. The window stays even if the program continues running (not in this short example), although the zoom buttons don't work anymore. This is desired behavior.
Windows command line: an empty nonresponsive plot window shows up, which disappears when the program ends. Adding
plt.pause()
results in an interactive plot, but it is only responsive for the specified number of seconds.Linux/Windows Spyder with iPython, configured for automatic plots: figures show up and are responsive, but only after the script finishes.
Linux/Windows Spyder, configured for inline plots: plots show up after the script finishes, but with warnings due to the
tight_layout=True
parameter: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect. and matplotlib is currently using a non-GUI backend.
(Note that I needtight_layout
because otherwise often axis labels are clipped or figures with multiple subplots have bad margins.)Linux/Windows Spyder, inline plots: with
plt.plot(...); plt.show()
(rather than thefig.plot(...); fig.show()
object-oriented way), the inline plots show up during program execution.
How can I write code that generates interactive plots during program execution (possibly while waiting for a keypress) that will run correctly from the Windows command line, Linux command line, and Spyder?
Edit: plt.show()
instead of fig.show()
will result in a plot being shown correctly, but outside IPython, it blocks execution of the script until I click the close button of the figure window. This is rather cumbersome when there are multiple figures or when the calculation is not yet finished. And plt.show(block=False)
has the same behavior as fig.show()
.
I'm using an noncustomized Anaconda 5.1 environment with Python 3.6.4, matplotlib 2.1.2, spyder 3.2.6. In Spyder: Tools > Preferences > IPython > Backend, set to 'inline' or 'automatic' (and restarting kernel after changing this setting.)
python matplotlib spyder
python matplotlib spyder
edited Nov 19 '18 at 10:03
Han-Kwang Nienhuys
asked Nov 16 '18 at 14:21
Han-Kwang NienhuysHan-Kwang Nienhuys
475310
475310
There are explanation of (almost) all observed behaviour. However, what is the problem you want to solve? Why not simply useplt.show()
to generate the figure window?
– ImportanceOfBeingErnest
Nov 16 '18 at 14:39
@ImportanceOfBeingErnest I'd like to keep figure windows in view while program execution continues.plt.show()
is blocking the program until the window is closed andplt.show(block=False)
suffers from the same problems asfig.show()
.
– Han-Kwang Nienhuys
Nov 19 '18 at 10:04
How about checking in your code which platform you're running on and given this condition running a specific part of code? For Spyder, you can check the environmental variables and check if the Spyder's ones exist.
– arudzinska
Nov 19 '18 at 10:10
@arudzinska I experimented a bit with solutions that at least work for one environment, but I've not found something that allows interactive figures to persist in Windows after interaction. Withplt.pause(1)
in a loop that runs until a keypress, the figure window steals the focus every second (in Linux, not in Windows 7). I guess that I'll have to live with plots becoming interactive in Spyder after program termination and no solution for Windows command line.
– Han-Kwang Nienhuys
Nov 19 '18 at 13:09
Update: I wrote my own solution with environment detection. Does not work well in all cases, though.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:22
add a comment |
There are explanation of (almost) all observed behaviour. However, what is the problem you want to solve? Why not simply useplt.show()
to generate the figure window?
– ImportanceOfBeingErnest
Nov 16 '18 at 14:39
@ImportanceOfBeingErnest I'd like to keep figure windows in view while program execution continues.plt.show()
is blocking the program until the window is closed andplt.show(block=False)
suffers from the same problems asfig.show()
.
– Han-Kwang Nienhuys
Nov 19 '18 at 10:04
How about checking in your code which platform you're running on and given this condition running a specific part of code? For Spyder, you can check the environmental variables and check if the Spyder's ones exist.
– arudzinska
Nov 19 '18 at 10:10
@arudzinska I experimented a bit with solutions that at least work for one environment, but I've not found something that allows interactive figures to persist in Windows after interaction. Withplt.pause(1)
in a loop that runs until a keypress, the figure window steals the focus every second (in Linux, not in Windows 7). I guess that I'll have to live with plots becoming interactive in Spyder after program termination and no solution for Windows command line.
– Han-Kwang Nienhuys
Nov 19 '18 at 13:09
Update: I wrote my own solution with environment detection. Does not work well in all cases, though.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:22
There are explanation of (almost) all observed behaviour. However, what is the problem you want to solve? Why not simply use
plt.show()
to generate the figure window?– ImportanceOfBeingErnest
Nov 16 '18 at 14:39
There are explanation of (almost) all observed behaviour. However, what is the problem you want to solve? Why not simply use
plt.show()
to generate the figure window?– ImportanceOfBeingErnest
Nov 16 '18 at 14:39
@ImportanceOfBeingErnest I'd like to keep figure windows in view while program execution continues.
plt.show()
is blocking the program until the window is closed and plt.show(block=False)
suffers from the same problems as fig.show()
.– Han-Kwang Nienhuys
Nov 19 '18 at 10:04
@ImportanceOfBeingErnest I'd like to keep figure windows in view while program execution continues.
plt.show()
is blocking the program until the window is closed and plt.show(block=False)
suffers from the same problems as fig.show()
.– Han-Kwang Nienhuys
Nov 19 '18 at 10:04
How about checking in your code which platform you're running on and given this condition running a specific part of code? For Spyder, you can check the environmental variables and check if the Spyder's ones exist.
– arudzinska
Nov 19 '18 at 10:10
How about checking in your code which platform you're running on and given this condition running a specific part of code? For Spyder, you can check the environmental variables and check if the Spyder's ones exist.
– arudzinska
Nov 19 '18 at 10:10
@arudzinska I experimented a bit with solutions that at least work for one environment, but I've not found something that allows interactive figures to persist in Windows after interaction. With
plt.pause(1)
in a loop that runs until a keypress, the figure window steals the focus every second (in Linux, not in Windows 7). I guess that I'll have to live with plots becoming interactive in Spyder after program termination and no solution for Windows command line.– Han-Kwang Nienhuys
Nov 19 '18 at 13:09
@arudzinska I experimented a bit with solutions that at least work for one environment, but I've not found something that allows interactive figures to persist in Windows after interaction. With
plt.pause(1)
in a loop that runs until a keypress, the figure window steals the focus every second (in Linux, not in Windows 7). I guess that I'll have to live with plots becoming interactive in Spyder after program termination and no solution for Windows command line.– Han-Kwang Nienhuys
Nov 19 '18 at 13:09
Update: I wrote my own solution with environment detection. Does not work well in all cases, though.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:22
Update: I wrote my own solution with environment detection. Does not work well in all cases, though.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:22
add a comment |
2 Answers
2
active
oldest
votes
It seems the following is what you're after:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, tight_layout=True)
plt.ion()
ax.plot([0,1,2],[0,3,2])
plt.show()
plt.pause(0.1)
input('Press enter to quit.')
plt.close()
In general, a python program is evaluated linearly. This contradicts the desire to have a blocking command line (input
) but a non-blocking GUI.
What happens in the above is that a GUI is created, but without any propper event-loop started. Therefore the code can continue to be executed even after the GUI being shown. The drawback of this is clearly that without event-loop, you cannot interact with the GUI.
In case a plotting window needs to be shown and some user input is required, or further code is to be executed after showing the fully interactive figure, one can run such code within the GUI event loop.
import matplotlib.pyplot as plt
def run_after(callback, pause=10, figure=None):
figure = figure or plt.gcf()
timer = figure.canvas.new_timer(interval=pause)
timer.single_shot = True
timer.add_callback(callback)
timer.start()
return timer
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
# This function contains the code to be executed within the GUI event loop
def mycallback():
import tkinter
from tkinter import simpledialog
root = tkinter.Tk()
root.withdraw()
w = simpledialog.askinteger("Title", "How many numbers do you want to print")
for i in range(w):
print(i)
cb = run_after(mycallback)
plt.show()
If I run this code from Spyder in Linux, I get an empty plot window and a dialog; after dismissing the dialog, the plot gets updated. If the program continues afterplt.show()
, e.g.import time; time.sleep(5)
, then the dialog shows up after the program finishes.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:15
Maybe 10 milliseconds is too fast. Trycb = run_after(mycallback, 500)
instead.
– ImportanceOfBeingErnest
Nov 19 '18 at 14:46
The extra pause helps in the original script - although it would require me to estimate the time needed to plot (depending on computer speed and data size). But if the program continues afterplt.show()
, the dialog and plot do not show up until the program finishes, which I can also achieve withplt.show(block=False)
without a callback.
– Han-Kwang Nienhuys
Nov 19 '18 at 15:38
I'm not sure I understand what you mean by "if the program continues afterplt.show()
". Themycallback
is the continuation of the program afterplt.show()
; you cannot combine this withplt.ion()
.
– ImportanceOfBeingErnest
Nov 19 '18 at 15:46
I want to look at preliminary data before a calculation is fully converged. For example, addimport time; time.sleep(5)
after the last line of the script. Then I don't see a plot until the script is finished.
– Han-Kwang Nienhuys
Nov 19 '18 at 16:33
|
show 1 more comment
Here is an approach that sort of works, but not very well for all environments:
import matplotlib.pyplot as plt
import sys
import matplotlib
def plt_show_interactive():
"""Show plot windows, with interaction if possible; prompt to continue."""
in_ipython = ('get_ipython' in globals())
inline_backend = ('inline' in matplotlib.get_backend())
in_linux = (sys.platform == 'linux')
if inline_backend:
plt.show()
elif not in_linux and in_ipython:
print("Press Ctrl-C to continue.")
try:
while True:
plt.pause(0.5)
except KeyboardInterrupt:
print("Continuing.")
elif in_linux and not in_ipython:
# Command line: plots are interactive during wait for input.
plt.show(block=False)
input("Press ENTER to continue.")
elif in_linux and in_ipython:
# Loop with plt.pause(1) causes repeated focus stealing.
plt.pause(1)
print("Sorry, plots are not interactive until program has finished.")
elif not in_linux and not in_ipython:
# Ctrl-C is handled differently here.
plt.pause(1)
input("Sorry, not interactive. Press ENTER to continue.")
def prompt_if_not_ipython(verb="end"):
"""Ask user to press ENTER if not we're not inside IPython."""
if ('get_ipython' not in globals()):
input("Press ENTER to %s." % verb)
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
plt_show_interactive()
prompt_if_not_ipython()
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53339667%2fportable-method-to-generate-matplotlib-interactive-figures-in-windows-linux-sp%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
It seems the following is what you're after:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, tight_layout=True)
plt.ion()
ax.plot([0,1,2],[0,3,2])
plt.show()
plt.pause(0.1)
input('Press enter to quit.')
plt.close()
In general, a python program is evaluated linearly. This contradicts the desire to have a blocking command line (input
) but a non-blocking GUI.
What happens in the above is that a GUI is created, but without any propper event-loop started. Therefore the code can continue to be executed even after the GUI being shown. The drawback of this is clearly that without event-loop, you cannot interact with the GUI.
In case a plotting window needs to be shown and some user input is required, or further code is to be executed after showing the fully interactive figure, one can run such code within the GUI event loop.
import matplotlib.pyplot as plt
def run_after(callback, pause=10, figure=None):
figure = figure or plt.gcf()
timer = figure.canvas.new_timer(interval=pause)
timer.single_shot = True
timer.add_callback(callback)
timer.start()
return timer
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
# This function contains the code to be executed within the GUI event loop
def mycallback():
import tkinter
from tkinter import simpledialog
root = tkinter.Tk()
root.withdraw()
w = simpledialog.askinteger("Title", "How many numbers do you want to print")
for i in range(w):
print(i)
cb = run_after(mycallback)
plt.show()
If I run this code from Spyder in Linux, I get an empty plot window and a dialog; after dismissing the dialog, the plot gets updated. If the program continues afterplt.show()
, e.g.import time; time.sleep(5)
, then the dialog shows up after the program finishes.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:15
Maybe 10 milliseconds is too fast. Trycb = run_after(mycallback, 500)
instead.
– ImportanceOfBeingErnest
Nov 19 '18 at 14:46
The extra pause helps in the original script - although it would require me to estimate the time needed to plot (depending on computer speed and data size). But if the program continues afterplt.show()
, the dialog and plot do not show up until the program finishes, which I can also achieve withplt.show(block=False)
without a callback.
– Han-Kwang Nienhuys
Nov 19 '18 at 15:38
I'm not sure I understand what you mean by "if the program continues afterplt.show()
". Themycallback
is the continuation of the program afterplt.show()
; you cannot combine this withplt.ion()
.
– ImportanceOfBeingErnest
Nov 19 '18 at 15:46
I want to look at preliminary data before a calculation is fully converged. For example, addimport time; time.sleep(5)
after the last line of the script. Then I don't see a plot until the script is finished.
– Han-Kwang Nienhuys
Nov 19 '18 at 16:33
|
show 1 more comment
It seems the following is what you're after:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, tight_layout=True)
plt.ion()
ax.plot([0,1,2],[0,3,2])
plt.show()
plt.pause(0.1)
input('Press enter to quit.')
plt.close()
In general, a python program is evaluated linearly. This contradicts the desire to have a blocking command line (input
) but a non-blocking GUI.
What happens in the above is that a GUI is created, but without any propper event-loop started. Therefore the code can continue to be executed even after the GUI being shown. The drawback of this is clearly that without event-loop, you cannot interact with the GUI.
In case a plotting window needs to be shown and some user input is required, or further code is to be executed after showing the fully interactive figure, one can run such code within the GUI event loop.
import matplotlib.pyplot as plt
def run_after(callback, pause=10, figure=None):
figure = figure or plt.gcf()
timer = figure.canvas.new_timer(interval=pause)
timer.single_shot = True
timer.add_callback(callback)
timer.start()
return timer
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
# This function contains the code to be executed within the GUI event loop
def mycallback():
import tkinter
from tkinter import simpledialog
root = tkinter.Tk()
root.withdraw()
w = simpledialog.askinteger("Title", "How many numbers do you want to print")
for i in range(w):
print(i)
cb = run_after(mycallback)
plt.show()
If I run this code from Spyder in Linux, I get an empty plot window and a dialog; after dismissing the dialog, the plot gets updated. If the program continues afterplt.show()
, e.g.import time; time.sleep(5)
, then the dialog shows up after the program finishes.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:15
Maybe 10 milliseconds is too fast. Trycb = run_after(mycallback, 500)
instead.
– ImportanceOfBeingErnest
Nov 19 '18 at 14:46
The extra pause helps in the original script - although it would require me to estimate the time needed to plot (depending on computer speed and data size). But if the program continues afterplt.show()
, the dialog and plot do not show up until the program finishes, which I can also achieve withplt.show(block=False)
without a callback.
– Han-Kwang Nienhuys
Nov 19 '18 at 15:38
I'm not sure I understand what you mean by "if the program continues afterplt.show()
". Themycallback
is the continuation of the program afterplt.show()
; you cannot combine this withplt.ion()
.
– ImportanceOfBeingErnest
Nov 19 '18 at 15:46
I want to look at preliminary data before a calculation is fully converged. For example, addimport time; time.sleep(5)
after the last line of the script. Then I don't see a plot until the script is finished.
– Han-Kwang Nienhuys
Nov 19 '18 at 16:33
|
show 1 more comment
It seems the following is what you're after:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, tight_layout=True)
plt.ion()
ax.plot([0,1,2],[0,3,2])
plt.show()
plt.pause(0.1)
input('Press enter to quit.')
plt.close()
In general, a python program is evaluated linearly. This contradicts the desire to have a blocking command line (input
) but a non-blocking GUI.
What happens in the above is that a GUI is created, but without any propper event-loop started. Therefore the code can continue to be executed even after the GUI being shown. The drawback of this is clearly that without event-loop, you cannot interact with the GUI.
In case a plotting window needs to be shown and some user input is required, or further code is to be executed after showing the fully interactive figure, one can run such code within the GUI event loop.
import matplotlib.pyplot as plt
def run_after(callback, pause=10, figure=None):
figure = figure or plt.gcf()
timer = figure.canvas.new_timer(interval=pause)
timer.single_shot = True
timer.add_callback(callback)
timer.start()
return timer
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
# This function contains the code to be executed within the GUI event loop
def mycallback():
import tkinter
from tkinter import simpledialog
root = tkinter.Tk()
root.withdraw()
w = simpledialog.askinteger("Title", "How many numbers do you want to print")
for i in range(w):
print(i)
cb = run_after(mycallback)
plt.show()
It seems the following is what you're after:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, tight_layout=True)
plt.ion()
ax.plot([0,1,2],[0,3,2])
plt.show()
plt.pause(0.1)
input('Press enter to quit.')
plt.close()
In general, a python program is evaluated linearly. This contradicts the desire to have a blocking command line (input
) but a non-blocking GUI.
What happens in the above is that a GUI is created, but without any propper event-loop started. Therefore the code can continue to be executed even after the GUI being shown. The drawback of this is clearly that without event-loop, you cannot interact with the GUI.
In case a plotting window needs to be shown and some user input is required, or further code is to be executed after showing the fully interactive figure, one can run such code within the GUI event loop.
import matplotlib.pyplot as plt
def run_after(callback, pause=10, figure=None):
figure = figure or plt.gcf()
timer = figure.canvas.new_timer(interval=pause)
timer.single_shot = True
timer.add_callback(callback)
timer.start()
return timer
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
# This function contains the code to be executed within the GUI event loop
def mycallback():
import tkinter
from tkinter import simpledialog
root = tkinter.Tk()
root.withdraw()
w = simpledialog.askinteger("Title", "How many numbers do you want to print")
for i in range(w):
print(i)
cb = run_after(mycallback)
plt.show()
answered Nov 19 '18 at 13:32
ImportanceOfBeingErnestImportanceOfBeingErnest
142k13167245
142k13167245
If I run this code from Spyder in Linux, I get an empty plot window and a dialog; after dismissing the dialog, the plot gets updated. If the program continues afterplt.show()
, e.g.import time; time.sleep(5)
, then the dialog shows up after the program finishes.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:15
Maybe 10 milliseconds is too fast. Trycb = run_after(mycallback, 500)
instead.
– ImportanceOfBeingErnest
Nov 19 '18 at 14:46
The extra pause helps in the original script - although it would require me to estimate the time needed to plot (depending on computer speed and data size). But if the program continues afterplt.show()
, the dialog and plot do not show up until the program finishes, which I can also achieve withplt.show(block=False)
without a callback.
– Han-Kwang Nienhuys
Nov 19 '18 at 15:38
I'm not sure I understand what you mean by "if the program continues afterplt.show()
". Themycallback
is the continuation of the program afterplt.show()
; you cannot combine this withplt.ion()
.
– ImportanceOfBeingErnest
Nov 19 '18 at 15:46
I want to look at preliminary data before a calculation is fully converged. For example, addimport time; time.sleep(5)
after the last line of the script. Then I don't see a plot until the script is finished.
– Han-Kwang Nienhuys
Nov 19 '18 at 16:33
|
show 1 more comment
If I run this code from Spyder in Linux, I get an empty plot window and a dialog; after dismissing the dialog, the plot gets updated. If the program continues afterplt.show()
, e.g.import time; time.sleep(5)
, then the dialog shows up after the program finishes.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:15
Maybe 10 milliseconds is too fast. Trycb = run_after(mycallback, 500)
instead.
– ImportanceOfBeingErnest
Nov 19 '18 at 14:46
The extra pause helps in the original script - although it would require me to estimate the time needed to plot (depending on computer speed and data size). But if the program continues afterplt.show()
, the dialog and plot do not show up until the program finishes, which I can also achieve withplt.show(block=False)
without a callback.
– Han-Kwang Nienhuys
Nov 19 '18 at 15:38
I'm not sure I understand what you mean by "if the program continues afterplt.show()
". Themycallback
is the continuation of the program afterplt.show()
; you cannot combine this withplt.ion()
.
– ImportanceOfBeingErnest
Nov 19 '18 at 15:46
I want to look at preliminary data before a calculation is fully converged. For example, addimport time; time.sleep(5)
after the last line of the script. Then I don't see a plot until the script is finished.
– Han-Kwang Nienhuys
Nov 19 '18 at 16:33
If I run this code from Spyder in Linux, I get an empty plot window and a dialog; after dismissing the dialog, the plot gets updated. If the program continues after
plt.show()
, e.g. import time; time.sleep(5)
, then the dialog shows up after the program finishes.– Han-Kwang Nienhuys
Nov 19 '18 at 14:15
If I run this code from Spyder in Linux, I get an empty plot window and a dialog; after dismissing the dialog, the plot gets updated. If the program continues after
plt.show()
, e.g. import time; time.sleep(5)
, then the dialog shows up after the program finishes.– Han-Kwang Nienhuys
Nov 19 '18 at 14:15
Maybe 10 milliseconds is too fast. Try
cb = run_after(mycallback, 500)
instead.– ImportanceOfBeingErnest
Nov 19 '18 at 14:46
Maybe 10 milliseconds is too fast. Try
cb = run_after(mycallback, 500)
instead.– ImportanceOfBeingErnest
Nov 19 '18 at 14:46
The extra pause helps in the original script - although it would require me to estimate the time needed to plot (depending on computer speed and data size). But if the program continues after
plt.show()
, the dialog and plot do not show up until the program finishes, which I can also achieve with plt.show(block=False)
without a callback.– Han-Kwang Nienhuys
Nov 19 '18 at 15:38
The extra pause helps in the original script - although it would require me to estimate the time needed to plot (depending on computer speed and data size). But if the program continues after
plt.show()
, the dialog and plot do not show up until the program finishes, which I can also achieve with plt.show(block=False)
without a callback.– Han-Kwang Nienhuys
Nov 19 '18 at 15:38
I'm not sure I understand what you mean by "if the program continues after
plt.show()
". The mycallback
is the continuation of the program after plt.show()
; you cannot combine this with plt.ion()
.– ImportanceOfBeingErnest
Nov 19 '18 at 15:46
I'm not sure I understand what you mean by "if the program continues after
plt.show()
". The mycallback
is the continuation of the program after plt.show()
; you cannot combine this with plt.ion()
.– ImportanceOfBeingErnest
Nov 19 '18 at 15:46
I want to look at preliminary data before a calculation is fully converged. For example, add
import time; time.sleep(5)
after the last line of the script. Then I don't see a plot until the script is finished.– Han-Kwang Nienhuys
Nov 19 '18 at 16:33
I want to look at preliminary data before a calculation is fully converged. For example, add
import time; time.sleep(5)
after the last line of the script. Then I don't see a plot until the script is finished.– Han-Kwang Nienhuys
Nov 19 '18 at 16:33
|
show 1 more comment
Here is an approach that sort of works, but not very well for all environments:
import matplotlib.pyplot as plt
import sys
import matplotlib
def plt_show_interactive():
"""Show plot windows, with interaction if possible; prompt to continue."""
in_ipython = ('get_ipython' in globals())
inline_backend = ('inline' in matplotlib.get_backend())
in_linux = (sys.platform == 'linux')
if inline_backend:
plt.show()
elif not in_linux and in_ipython:
print("Press Ctrl-C to continue.")
try:
while True:
plt.pause(0.5)
except KeyboardInterrupt:
print("Continuing.")
elif in_linux and not in_ipython:
# Command line: plots are interactive during wait for input.
plt.show(block=False)
input("Press ENTER to continue.")
elif in_linux and in_ipython:
# Loop with plt.pause(1) causes repeated focus stealing.
plt.pause(1)
print("Sorry, plots are not interactive until program has finished.")
elif not in_linux and not in_ipython:
# Ctrl-C is handled differently here.
plt.pause(1)
input("Sorry, not interactive. Press ENTER to continue.")
def prompt_if_not_ipython(verb="end"):
"""Ask user to press ENTER if not we're not inside IPython."""
if ('get_ipython' not in globals()):
input("Press ENTER to %s." % verb)
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
plt_show_interactive()
prompt_if_not_ipython()
add a comment |
Here is an approach that sort of works, but not very well for all environments:
import matplotlib.pyplot as plt
import sys
import matplotlib
def plt_show_interactive():
"""Show plot windows, with interaction if possible; prompt to continue."""
in_ipython = ('get_ipython' in globals())
inline_backend = ('inline' in matplotlib.get_backend())
in_linux = (sys.platform == 'linux')
if inline_backend:
plt.show()
elif not in_linux and in_ipython:
print("Press Ctrl-C to continue.")
try:
while True:
plt.pause(0.5)
except KeyboardInterrupt:
print("Continuing.")
elif in_linux and not in_ipython:
# Command line: plots are interactive during wait for input.
plt.show(block=False)
input("Press ENTER to continue.")
elif in_linux and in_ipython:
# Loop with plt.pause(1) causes repeated focus stealing.
plt.pause(1)
print("Sorry, plots are not interactive until program has finished.")
elif not in_linux and not in_ipython:
# Ctrl-C is handled differently here.
plt.pause(1)
input("Sorry, not interactive. Press ENTER to continue.")
def prompt_if_not_ipython(verb="end"):
"""Ask user to press ENTER if not we're not inside IPython."""
if ('get_ipython' not in globals()):
input("Press ENTER to %s." % verb)
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
plt_show_interactive()
prompt_if_not_ipython()
add a comment |
Here is an approach that sort of works, but not very well for all environments:
import matplotlib.pyplot as plt
import sys
import matplotlib
def plt_show_interactive():
"""Show plot windows, with interaction if possible; prompt to continue."""
in_ipython = ('get_ipython' in globals())
inline_backend = ('inline' in matplotlib.get_backend())
in_linux = (sys.platform == 'linux')
if inline_backend:
plt.show()
elif not in_linux and in_ipython:
print("Press Ctrl-C to continue.")
try:
while True:
plt.pause(0.5)
except KeyboardInterrupt:
print("Continuing.")
elif in_linux and not in_ipython:
# Command line: plots are interactive during wait for input.
plt.show(block=False)
input("Press ENTER to continue.")
elif in_linux and in_ipython:
# Loop with plt.pause(1) causes repeated focus stealing.
plt.pause(1)
print("Sorry, plots are not interactive until program has finished.")
elif not in_linux and not in_ipython:
# Ctrl-C is handled differently here.
plt.pause(1)
input("Sorry, not interactive. Press ENTER to continue.")
def prompt_if_not_ipython(verb="end"):
"""Ask user to press ENTER if not we're not inside IPython."""
if ('get_ipython' not in globals()):
input("Press ENTER to %s." % verb)
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
plt_show_interactive()
prompt_if_not_ipython()
Here is an approach that sort of works, but not very well for all environments:
import matplotlib.pyplot as plt
import sys
import matplotlib
def plt_show_interactive():
"""Show plot windows, with interaction if possible; prompt to continue."""
in_ipython = ('get_ipython' in globals())
inline_backend = ('inline' in matplotlib.get_backend())
in_linux = (sys.platform == 'linux')
if inline_backend:
plt.show()
elif not in_linux and in_ipython:
print("Press Ctrl-C to continue.")
try:
while True:
plt.pause(0.5)
except KeyboardInterrupt:
print("Continuing.")
elif in_linux and not in_ipython:
# Command line: plots are interactive during wait for input.
plt.show(block=False)
input("Press ENTER to continue.")
elif in_linux and in_ipython:
# Loop with plt.pause(1) causes repeated focus stealing.
plt.pause(1)
print("Sorry, plots are not interactive until program has finished.")
elif not in_linux and not in_ipython:
# Ctrl-C is handled differently here.
plt.pause(1)
input("Sorry, not interactive. Press ENTER to continue.")
def prompt_if_not_ipython(verb="end"):
"""Ask user to press ENTER if not we're not inside IPython."""
if ('get_ipython' not in globals()):
input("Press ENTER to %s." % verb)
fig, ax = plt.subplots(1, 1, tight_layout=True)
ax.plot([0,1,2],[0,3,2])
plt_show_interactive()
prompt_if_not_ipython()
edited Nov 19 '18 at 15:38
answered Nov 19 '18 at 14:18
Han-Kwang NienhuysHan-Kwang Nienhuys
475310
475310
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53339667%2fportable-method-to-generate-matplotlib-interactive-figures-in-windows-linux-sp%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
There are explanation of (almost) all observed behaviour. However, what is the problem you want to solve? Why not simply use
plt.show()
to generate the figure window?– ImportanceOfBeingErnest
Nov 16 '18 at 14:39
@ImportanceOfBeingErnest I'd like to keep figure windows in view while program execution continues.
plt.show()
is blocking the program until the window is closed andplt.show(block=False)
suffers from the same problems asfig.show()
.– Han-Kwang Nienhuys
Nov 19 '18 at 10:04
How about checking in your code which platform you're running on and given this condition running a specific part of code? For Spyder, you can check the environmental variables and check if the Spyder's ones exist.
– arudzinska
Nov 19 '18 at 10:10
@arudzinska I experimented a bit with solutions that at least work for one environment, but I've not found something that allows interactive figures to persist in Windows after interaction. With
plt.pause(1)
in a loop that runs until a keypress, the figure window steals the focus every second (in Linux, not in Windows 7). I guess that I'll have to live with plots becoming interactive in Spyder after program termination and no solution for Windows command line.– Han-Kwang Nienhuys
Nov 19 '18 at 13:09
Update: I wrote my own solution with environment detection. Does not work well in all cases, though.
– Han-Kwang Nienhuys
Nov 19 '18 at 14:22