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;
}







0















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 need tight_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 the fig.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.)










share|improve this question

























  • 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











  • 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


















0















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 need tight_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 the fig.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.)










share|improve this question

























  • 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











  • 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














0












0








0








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 need tight_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 the fig.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.)










share|improve this question
















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 need tight_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 the fig.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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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











  • 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



















  • 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











  • 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

















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












2 Answers
2






active

oldest

votes


















0














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()





share|improve this answer
























  • 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











  • 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 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





















0














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()





share|improve this answer


























    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
    });


    }
    });














    draft saved

    draft discarded


















    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









    0














    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()





    share|improve this answer
























    • 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











    • 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 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


















    0














    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()





    share|improve this answer
























    • 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











    • 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 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
















    0












    0








    0







    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()





    share|improve this answer













    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()






    share|improve this answer












    share|improve this answer



    share|improve this answer










    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 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











    • 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 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





















    • 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











    • 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 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



















    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















    0














    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()





    share|improve this answer






























      0














      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()





      share|improve this answer




























        0












        0








        0







        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()





        share|improve this answer















        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()






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 19 '18 at 15:38

























        answered Nov 19 '18 at 14:18









        Han-Kwang NienhuysHan-Kwang Nienhuys

        475310




        475310






























            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            Florida Star v. B. J. F.

            Danny Elfman

            Lugert, Oklahoma