From: Perry G. <pe...@st...> - 2004-12-11 17:07:28
|
John Hunter Wrote:> > Aside from the aforementioned "run" mode of ipython, which does just > this, the basic incantation is > > >>> from matplotlib import interactive, is_interactive > >>> b = is_interactive() # store the current interactive state > >>> plot(blah, blah) # make some plots > >>> interactive(False) # turn interactive off > >>> for i in arange(1e4096): plot(arange(i), arange(i)**2) # > don't try this at home > >>> interactive(b) # restore previous interactive state > > Basically, this is what ipython does. This is wrapped into a single > function "run", called like > > >>> x = 1 # some fluff > >>> run ~/myexamples/simple_demo.py # turn interactive off for run > >>> x = 2 # interactive setting is restored > > But of course, you can use the interactive / is_interactive functions > in any script or interactive session. > > To make this more accessible, perhaps we should add an interactive (or > update) kwarg to plot and friends, in the same vein that we discussed > a kwarg for hold, so you can easily do things like > > plot(x, y, hold=False) # add plot, clearing previous > plot(x, y, update=False) # add plot but do not update > > But the question arises, does the additional complexity in the > matplotlib internals required to support this justify the savings for > the occasional user who would otherwise have to type a couple of extra > lines? > In this case I don't think so. the function interactive() is what I was looking for, not a keyword argument. Unlike overplotting, I think interactive() is likely to be used almost entirely in scripts and functions and that is by far the better approach. So it's already good enough as far as I'm concerned. Perry > > > ------------------------------------------------------- > SF email is sponsored by - The IT Product Guide > Read honest & candid reviews on hundreds of IT Products from real users. > Discover which products truly live up to the hype. Start reading now. > http://productguide.itmanagersjournal.com/ > _______________________________________________ > Matplotlib-users mailing list > Mat...@li... > https://lists.sourceforge.net/lists/listinfo/matplotlib-users > |
From: John H. <jdh...@ac...> - 2004-12-11 17:28:21
|
>>>>> "Perry" == Perry Greenfield <pe...@st...> writes: Perry> John Hunter Wrote:> >> Aside from the aforementioned "run" mode of ipython, which does >> just this, the basic incantation is >> >> >>> from matplotlib import interactive, is_interactive >>> b = >> is_interactive() # store the current interactive state >>> >> plot(blah, blah) # make some plots >>> interactive(False) # >> turn interactive off >>> for i in arange(1e4096): >> plot(arange(i), arange(i)**2) # don't try this at home >>> >> interactive(b) # restore previous interactive state >> >> Basically, this is what ipython does. This is wrapped into a >> single function "run", called like >> >> >>> x = 1 # some fluff >>> run ~/myexamples/simple_demo.py # >> turn interactive off for run >>> x = 2 # interactive setting is >> restored >> >> But of course, you can use the interactive / is_interactive >> functions in any script or interactive session. >> >> To make this more accessible, perhaps we should add an >> interactive (or update) kwarg to plot and friends, in the same >> vein that we discussed a kwarg for hold, so you can easily do >> things like >> >> plot(x, y, hold=False) # add plot, clearing previous plot(x, y, >> update=False) # add plot but do not update >> >> But the question arises, does the additional complexity in the >> matplotlib internals required to support this justify the >> savings for the occasional user who would otherwise have to >> type a couple of extra lines? >> Perry> In this case I don't think so. the function interactive() Perry> is what I was looking for, not a keyword argument. Unlike Perry> overplotting, I think interactive() is likely to be used Perry> almost entirely in scripts and functions and that is by far Perry> the better approach. So it's already good enough as far as Perry> I'm concerned. Following these discussions, I just added ion and ioff to the pylab interface, and updated the web site interaction page with (not uploaded yet) with the following. Let me know if you have anything to add here. By default, matplotlib defers drawing until the end of the script because drawing can be an expensive opertation, and you may not want to update the plot every time a single property is changed, only once after all the properties have changed. But in interactive mode, eg from the python shell, you usually do want to update the plot with every command, eg, after changing the xlabel or the marker style of a line. With the TkAgg backend, you can use matplotlib from an arbitrary python shell. Just set TkAgg to be your default backend and interactive to be True in your matplotlibrc file and fire up python. Then >>> from pylab import * >>> plot([1,2,3]) >>> xlabel('hi mom') should work out of the box. Note, in batch mode, ie when making figures from scripts, interactive mode can be slow since it redraws the figure with each command. So you may want to think carefully before making this the default behavior. TkAgg sets interactive mode to True when you issue the show command. Unfortunately, due to the 'mainloop' cycle of GUI toolkits, it is not yet possible to use matplotlib from an arbitrary python shell with the other GUI backends. You must use a custom python shell that runs the GUI is a separate thread. The recommended way to use matplotlib interactively from a shell is with ipython, which has an pylab mode that detects your matplotlib .matplotlibrc file and makes the right settings to run matplotlib with your GUI of choice in interactive mode using threading. gtk users will need to make sure that they have compiled gtk with threading for this to work. Using ipython in pylab mode is basically a nobrainer because it knows enough about matplotlib internals to make all the right settings for you internally peds-pc311:~> ipython -pylab Python 2.3.3 (#2, Apr 13 2004, 17:41:29) Type "copyright", "credits" or "license" for more information. IPython 0.6.5 -- An enhanced Interactive Python. ? -> Introduction to IPython's features. %magic -> Information about IPython's 'magic' % functions. help -> Python's own help system. object? -> Details about 'object'. ?object also works, ?? prints more. Welcome to pylab, a matplotlib-based Python environment. help(matplotlib) -> generic matplotlib information. help(matlab) -> matlab-compatible commands from matplotlib. help(plotting) -> plotting commands. >>> plot( rand(20), rand(20), 'go' ) Note that you did not need to import any matplotlib names because in pylab mode ipython will import them for you. ipython turns on interactive mode for you, and also provides a "run" command so you can run matplotlib scripts from the matplotlib shell and then interactively update your figure. ipython will turn off interactive mode during a run command for efficiency, and then restore the interactive state at the end of the run. >>> cd python/projects/matplotlib/examples/ /home/jdhunter/python/projects/matplotlib/examples >>> run simple_plot.py >>> title('a new title', color='r') The pylab interface provides 4 commands that are useful for interactive control. Note again that the interactgive setting primarily controls whether the figure is redrawn with each plotting command. is_interactive returns the interactive setting, ion turns interactive on, ioff turns it off, and draw forces a redraw of the entire figure. Thus when working with a big figure in which drawing is expensive, you may want to turn matplotlib's interactive setting off temporarily to avoid the performance hit >>> run mybigfatfigure.py >>> ioff() # turn updates off >>> title('now how much would you pay?') >>> xticklabels(fontsize=20, color='green') >>> draw() # force a draw >>> savefig('alldone', dpi=300) >>> close() >>> ion() # turn updates back on >>> plot(rand(20), mfc='g', mec='r', ms=40, mew=4, ls='--', lw=3) |
From: Perry G. <pe...@st...> - 2004-12-11 17:44:28
|
John Hunter wrote: [...] > > By default, matplotlib defers drawing until the end of the script > because drawing can be an expensive opertation, and you may not > want to update the plot every time a single property is changed, only > once after all the properties have changed. > > But in interactive mode, eg from the python shell, you usually do want > to update the plot with every command, eg, after changing the xlabel > or the marker style of a line. With the TkAgg backend, you can use > matplotlib from an arbitrary python shell. Just set TkAgg to be your > default backend and interactive to be True in your matplotlibrc file > and fire up python. Then > > >>> from pylab import * > >>> plot([1,2,3]) > >>> xlabel('hi mom') > > should work out of the box. Note, in batch mode, ie when making > figures from scripts, interactive mode can be slow since it redraws > the figure with each command. So you may want to think carefully > before making this the default behavior. TkAgg sets interactive mode > to True when you issue the show command. > [...] I'd just add that we may want to recommend that using ioff(), ion() be part of the matplotlib idiom for writing demos and larger, more involved plotting programs and scripts particularly where the author of the script or function is unsure of what context it will be run in. That way it always runs efficiently. Does that seem a reasonable thing to recommend? Perry |
From: Perry G. <pe...@st...> - 2004-12-12 04:02:23
|
In thinking about the ioff(), ion() approach it occurs to me that it may not be quite so simple for scripts. I think a common desire is for a script or function to turn off interactive mode if it is on, but at the end, restore the previous interactive state. In this case a push/pop approach to interactive mode may be more appropriate rather than stop/start. In particular, if interactive mode happended to be off, you wouldn't want to turn it on at the end of the script. Perry |
From: John H. <jdh...@ac...> - 2004-12-12 13:57:04
|
>>>>> "Perry" == Perry Greenfield <pe...@st...> writes: Perry> In thinking about the ioff(), ion() approach it occurs to Perry> me that it may not be quite so simple for scripts. I think Perry> a common desire is for a script or function to turn off Perry> interactive mode if it is on, but at the end, restore the Perry> previous interactive state. In this case a push/pop Perry> approach to interactive mode may be more appropriate rather Perry> than stop/start. In particular, if interactive mode Perry> happended to be off, you wouldn't want to turn it on at the Perry> end of the script. BTW, Eric emailed me off list. It appears that running his script in interactive mode was the root cause of his performance problems. In regards to running scripts from the python shell, I think the least invasive approach is to write a run function that stores the interactive state, calls ioff, runs the script with execfile, then calls ion (precisely what ipython does). In fact, perhaps we should add a run function to the pylab interface which does just this. Fernando could simply override this function if he wants to do some additional ipython magic. But this would wrap the logic for those who want to run scripts from the other python shell. Of course it would only work for non-image backends and Tk, or GUI backends associated with a GUI shell like pycrust. I'm less worried about people inadvertently running scripts from the command shell with interactive set to True, because interactive defaults to False in rc and thus the person would have had to intentionally change it, at least at some point in dark history. Hence they are probably aware of it. Singing the praises of ipython yet again, I leave the default in my rc to False, and run ipython when I want to work interactively, letting ipython turn interaction on for me. Thus I can run python somescript.py from the command shell assured that it is off, and still use matplotlib interactively w/o having to tweak the setting. But if there is some concern for users who would like to leave interactive on in rc (eg they like to use the standard python shell or some other shell) and still be able to get the efficiency when running scripts from the command shell, it might be possible to inspect whether we are in a running in a python shell, and plug this additional information into draw_if_interactive. Something like def draw_if_interactive(): if running_in_python_shell() and matplotlib.is_interactive(): canvas.draw() Anyone know how to determine whether you are running code in a python shell versus running a script, eg from a command shell? It occurs to me that "interactive" is not really the best name for this matplotlib state. Really we want something that conveys "draw_after_every_plot_command". When I named it, I was assuming that when working interactively you would want to update with every plot command, but have learned that this is not always the case. Do you think it's worth coming up with new names (isdraw(), draw_always(True/False), etc, while preserving the old names for a while with deprecation)? Because that's what we're really doing, controlling the drawing. JDH |
From: Ted D. <ted...@jp...> - 2004-12-13 19:58:17
|
John, I think the push/pop functions are going to be fairly useful (ipush and ipop??). We're going to be writing a lot scripts (i.e. functions) that generate plots for our users. There is no way to tell inside the script if it's going to be used by a user in interactive mode or by another script (like a batch report generator). Having push/pop would let me do: def stdPlot( [inputs] ): ipush( False ) try: [ create plot ] finally: ipop() Of course it's pretty easy to roll your own but I think it would be nice to have it in the standard set of commands. At 05:54 AM 12/12/2004, John Hunter wrote: > >>>>> "Perry" == Perry Greenfield <pe...@st...> writes: > > Perry> In thinking about the ioff(), ion() approach it occurs to > Perry> me that it may not be quite so simple for scripts. I think > Perry> a common desire is for a script or function to turn off > Perry> interactive mode if it is on, but at the end, restore the > Perry> previous interactive state. In this case a push/pop > Perry> approach to interactive mode may be more appropriate rather > Perry> than stop/start. In particular, if interactive mode > Perry> happended to be off, you wouldn't want to turn it on at the > Perry> end of the script. > >BTW, Eric emailed me off list. It appears that running his script in >interactive mode was the root cause of his performance problems. > >In regards to running scripts from the python shell, I think the least >invasive approach is to write a run function that stores the >interactive state, calls ioff, runs the script with execfile, then >calls ion (precisely what ipython does). In fact, perhaps we should >add a run function to the pylab interface which does just this. >Fernando could simply override this function if he wants to do some >additional ipython magic. But this would wrap the logic for those who >want to run scripts from the other python shell. Of course it would >only work for non-image backends and Tk, or GUI backends associated >with a GUI shell like pycrust. > >I'm less worried about people inadvertently running scripts from the >command shell with interactive set to True, because interactive >defaults to False in rc and thus the person would have had to >intentionally change it, at least at some point in dark history. >Hence they are probably aware of it. Singing the praises of ipython >yet again, I leave the default in my rc to False, and run ipython when >I want to work interactively, letting ipython turn interaction on for >me. Thus I can run python somescript.py from the command shell assured >that it is off, and still use matplotlib interactively w/o having to >tweak the setting. > >But if there is some concern for users who would like to leave >interactive on in rc (eg they like to use the standard python shell or >some other shell) and still be able to get the efficiency when running >scripts from the command shell, it might be possible to inspect >whether we are in a running in a python shell, and plug this >additional information into draw_if_interactive. Something like > >def draw_if_interactive(): > if running_in_python_shell() and matplotlib.is_interactive(): > canvas.draw() > >Anyone know how to determine whether you are running code in a python >shell versus running a script, eg from a command shell? > >It occurs to me that "interactive" is not really the best name for >this matplotlib state. Really we want something that conveys >"draw_after_every_plot_command". When I named it, I was assuming that >when working interactively you would want to update with every plot >command, but have learned that this is not always the case. Do you >think it's worth coming up with new names (isdraw(), >draw_always(True/False), etc, while preserving the old names for a >while with deprecation)? Because that's what we're really doing, >controlling the drawing. > >JDH > > > > > >------------------------------------------------------- >SF email is sponsored by - The IT Product Guide >Read honest & candid reviews on hundreds of IT Products from real users. >Discover which products truly live up to the hype. Start reading now. >http://productguide.itmanagersjournal.com/ >_______________________________________________ >Matplotlib-users mailing list >Mat...@li... >https://lists.sourceforge.net/lists/listinfo/matplotlib-users Ted Drain Jet Propulsion Laboratory ted...@jp... |
From: Perry G. <pe...@st...> - 2004-12-13 20:10:08
|
On Dec 13, 2004, at 2:57 PM, Ted Drain wrote: > John, > I think the push/pop functions are going to be fairly useful (ipush > and ipop??). We're going to be writing a lot scripts (i.e. functions) > that generate plots for our users. There is no way to tell inside the > script if it's going to be used by a user in interactive mode or by > another script (like a batch report generator). Having push/pop would > let me do: > > def stdPlot( [inputs] ): > ipush( False ) > try: > [ create plot ] > finally: > ipop() > > Of course it's pretty easy to roll your own but I think it would be > nice to have it in the standard set of commands. > Yes, this was exactly the kind of usage I was envisioning. In other words, I don't care what mode the user is using, I want this to run in "noninteractive" mode (according to its current meaning), but I don't want to screw up their state. Perry |
From: John H. <jdh...@ac...> - 2004-12-13 20:52:43
|
>>>>> "Ted" == Ted Drain <ted...@jp...> writes: Ted> John, I think the push/pop functions are going to be fairly Ted> useful (ipush and ipop??). We're going to be writing a lot Ted> scripts (i.e. functions) that generate plots for our users. Ted> There is no way to tell inside the script if it's going to be Ted> used by a user in interactive mode or by another script (like Ted> a batch report generator). Having push/pop would let me do: Ted> def stdPlot( [inputs] ): ipush( False ) try: [ create plot ] Ted> finally: ipop() Ted> Of course it's pretty easy to roll your own but I think it Ted> would be nice to have it in the standard set of commands. Hi Ted, I hadn't thought of using a stack. What is the argument for a stack as opposed to a single state manipulated along the lines of (with try except as needed) b = isinteractive() ioff() ....your plot here... if b: ion() Your approach requires one fewer line of code. Are their other advantages to a stack approach? I think a stack may be slightly less intuitive to a typical user, whereas turning drawing mode on and off is fairly straight forward. JDH |
From: Ted D. <ted...@jp...> - 2004-12-13 22:47:54
|
John, There probably isn't a compulsive argument for either way of doing it. The stack method is a very common graphics programming method for handling context switches, rotations, etc. Most graphics systems use the idea of pushing and popping from a graphics context stack so you can do rotations and transformations inside a subroutine w/o messing up anything else. At least where I work, our style guidelines make it a little more verbose. I need to use descriptive variable names (for maintainability) and no one line if statements (which cause problems whenever you need to add debugging print or other statements). Here's the difference between the methods with an additional option thrown in: ------------- Option 1) push/pop ipush() try: [ ... plot ... ] finally: ipop() ------------- Option 2) flags restoreInteractive = isinteractive() ioff() try: [ ... plot ... ] finally: if restoreInteractive: ion() ------------- Option 3) set/get method interactiveOn = isinteractive() ioff() try: [ ... plot ... ] finally: setinteractive( interactiveOn ) Ted At 12:50 PM 12/13/2004, John Hunter wrote: >Hi Ted, > >I hadn't thought of using a stack. What is the argument for a stack >as opposed to a single state manipulated along the lines of (with try >except as needed) > > b = isinteractive() > ioff() > ....your plot here... > if b: ion() > >Your approach requires one fewer line of code. Are their other >advantages to a stack approach? I think a stack may be slightly less >intuitive to a typical user, whereas turning drawing mode on and off >is fairly straight forward. > >JDH > >>>>> "Ted" == Ted Drain <ted...@jp...> writes: > > Ted> John, I think the push/pop functions are going to be fairly > Ted> useful (ipush and ipop??). We're going to be writing a lot > Ted> scripts (i.e. functions) that generate plots for our users. > Ted> There is no way to tell inside the script if it's going to be > Ted> used by a user in interactive mode or by another script (like > Ted> a batch report generator). Having push/pop would let me do: > > Ted> def stdPlot( [inputs] ): ipush( False ) try: [ create plot ] > Ted> finally: ipop() > > Ted> Of course it's pretty easy to roll your own but I think it > Ted> would be nice to have it in the standard set of commands. > > > >------------------------------------------------------- >SF email is sponsored by - The IT Product Guide >Read honest & candid reviews on hundreds of IT Products from real users. >Discover which products truly live up to the hype. Start reading now. >http://productguide.itmanagersjournal.com/ >_______________________________________________ >Matplotlib-users mailing list >Mat...@li... >https://lists.sourceforge.net/lists/listinfo/matplotlib-users |
From: John H. <jdh...@ac...> - 2004-12-14 15:56:36
|
>>>>> "Ted" == Ted Drain <ted...@jp...> writes: Ted> At least where I work, our style guidelines make it a little Ted> more verbose. I need to use descriptive variable names (for The new short names were meant for easy, interactive use, to minimize the number of keystrokes. For scripts, especially if you have verbose coding guidelines, I suggest you use the functions that are already defined in the matplotlib __init__ file import matplotlib b = matplotlib.is_interactive() matplotlib.interactive(False) ....your plot commands here.... matplotlib.interactive(b) The short names call these functions, anyhow. Note that this discussion may be moot, because when writing plotting functions I rarely use the drawing commands of the pylab interface since these are by and large wrappers of other methods, eg Axes methods. Since only the pylab plotting commands trigger the draw_if_interactive method, you can safely do things like ax.plot([1,2,3]) ax.set_xlabel('time') ax.set_title('this is a test') ax.grid(True) w/o worrying about the interactive setting. JDH |
From: Chris B. <Chr...@no...> - 2004-12-09 19:27:16
|
Arnd Baecker wrote: > P.S.: I agree on the speed issues. Unfortunately > most of the newer python graphics packages tend to be > slower than older packages. I think this has two reasons: 1) They are written more in Python, rather than wrapping an existing library written in C or whatever. 2) They often are back-end independent. This introduces an extra layer at every drawing command, and makes it difficult to take advantage of possible optimizations available for a given back end, like Arnd has done for his stuff. One thing that could help here is if all the drawing commands were "vectorized". This would mean that rather than asking the back-end to draw one primitive at a time, a whole set could be passed in. This would allow the back end to possibly optimize the drawing of the set. An example is wxPython's DC.DrawXXXList() methods. These methods take a python sequence of drawing primitives, and loop through that sequence in C++ code. It makes a huge difference when drawing simple objects, like points or line segments. I haven't looked closely at the matplotlib code to see if this can be done, but it could make a difference. -Chris -- Christopher Barker, Ph.D. Oceanographer NOAA/OR&R/HAZMAT (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chr...@no... |
From: John H. <jdh...@ac...> - 2004-12-09 22:03:41
|
>>>>> "Chris" == Chris Barker <Chr...@no...> writes: Chris> One thing that could help here is if all the drawing Chris> commands were "vectorized". This would mean that rather Chris> than asking the back-end to draw one primitive at a time, a Chris> whole set could be passed in. This would allow the back end Chris> to possibly optimize the drawing of the set. An example is Chris> wxPython's DC.DrawXXXList() methods. These methods take a Chris> python sequence of drawing primitives, and loop through Chris> that sequence in C++ code. It makes a huge difference when Chris> drawing simple objects, like points or line segments. Chris> I haven't looked closely at the matplotlib code to see if Chris> this can be done, but it could make a difference. This is basically what collections already do -- http://matplotlib.sourceforge.net/matplotlib.collections.html. Typically when we find an area of code where a bunch of primitives are being drawn independently, we refactor them as a collection. There is a default draw implementation in python that the backends can override in extension code (as agg does). Even if you just use the default python drawing implementation, eg backend_bases.RendererBase.draw_line_collection, the result is much faster that instantiating a large number of independent objects. Every property in a collection is a sequence (might be just length one) and the drawing code iterates over the collection and gets the value of a property for the i-th element of the collection as thisprop = prop[i % len(props)] So if you have a len(1) list, every element in the collection shares the prop, if you have a len(props) list, every element has a unique property and < len(props) the props cycle. Actually, a dictionary mapping element index to property value, which has a default value, would be more flexible, and the performance hit might not be bad. Might be worth refactoring. Actually, the code to plot line markers could be sped up by using collections to draw line markers. Currently we're using plain old python loops for this. JDH |