Requesting advice on multi-threaded matplotlib session + grids displaying data

Btw, what does "TkAgg sets interactive mode to True when

    > you issue the show command" mean exactly?

It means that if you are using tkagg and issue show, it launches the
interactive interpreter (python shell)

    > Wx has such a grid widget which can be used for
    > displaying/editing data, which is what I was hoping to
    > use. However, I am not sure if one should mix different
    > gui's. Iow, if I use tkagg or gtk as my interactive
    > matplotlib gui, can I also display and interact with
    > wxpython grid widgets in the same script smoothly? Am I
    > asking for trouble having the same script display
    > interactive matplotlib charts using one gui type and then
    > display these grid widgets using another gui type? Or
    > should I just stick with one gui type throughout the
    > entire script so that the interactive matplotlib charts
    > use say gtk and the same script also uses gtk for its grid
    > widgets?

OK, now I see better where you are coming from. You have a deluge of
data coming back from the prompt in the interactive shell and are
looking for a better way to deal with it. This is really beyond the
scope of matplotlib since it is a plotting library and your question
goes more to interacting with data. See ipython for solutions to
facilitate better interaction with data.

I can give you a couple of pointers though.

If you save the return value of a plot as a named variable, the output
will be suppressed. Then you can use array slicing to only show a
portion of it.

  1 >>> n, bins, patches = hist(randn(10000), 100) # no output printed
  2 >>> n[:5] # look at your data in slices using indexing
  Out[2]: [1,1,2,5,3,]

ipython has additional features to automatically suppress really large
arrays

  1 >>> rand(100,100)
  Out[1]: array (100,100) , type = d, has 10000 elements

On to your question about mixing GUIs. Don't do it. You will
explode.

If you want to display your data in a wx grid, you could use the wxagg
matplotlib backend and write some functions to display the data in a
wx grid. Eg, if you are working in a shell that supports wx
interactive work (pycrust), you could write a function to display any
array or vector in a wx grid and then call that function
interactively. Fernando is working on an interactive shell (mentioned
previously) that supports matplotlib/gtk. Once he gets the kinks
worked out, he plans to support matplotlib/wx as well.

If you want to work in gtk (eg matplotlib/gtkagg) the equivalent to a
wx grid is a treeview/liststore. You can write functions to pipe
arrays into grids and then display them by calling that function
interactively. Here is an example using Fernando's ipython-gtk

  hunter:~/python/examples/pygtk> python ~/tmp/ip/ipython-gtk.py
  Extra content at the end of the document
  Python 2.3.2 (#1, Oct 13 2003, 11:33:15)
  [GCC 3.3.1] on linux2
  Type "copyright", "credits" or "license" for more information.
  (MatplotlibShell)

  1 >>> from matplotlib.numerix import rand
  2 >>> from array_to_grid import view_array
  3 >>> view_array( rand(20,10))
  Out[3]: <ArrayView object (GtkWindow) at 0x4136db94>

And this is the screenshot -
http://nitace.bsd.uchicago.edu:8080/files/share/Screenshot-Ipython-gtk.py.png

While it would be possible for us to write functions in matplotlib
that would implement view_array (or something like it) for each of the
GUI backends, allowing you to call this function for tk, wx or gtk,
it's really beyond the scope of matplotlib (we're busy enough trying
to plot!). It's more in the domain of a matlab / mathematica like
integrated scientific computing environment, another topic near and
dear to Fernando's heart.

Here is the code array_to_grid.py - you can do a lot more with
treeviews and liststores, eg make a proper editable spreadsheet
interface with scroll bars in both x and y directions, but this will
get you started

'Display an array as a treeview'

import pygtk
pygtk.require('2.0')
import gobject
import gtk
from gtk import gdk

def view_array(X):
    'instantiate an ArrayView instance and show it'
    grid = ArrayView(X)
    grid.show_all()
    return grid
    
class ArrayView(gtk.Window):

    def __init__(self, X):
        gtk.Window.__init__(self)

        self.numRows, self.numCols = X.shape
        self.data = X

        self.set_title('Array display')
        self.set_border_width(8)

        vbox = gtk.VBox(False, 8)
        self.add(vbox)

        sw = gtk.ScrolledWindow()
        sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        sw.set_policy(gtk.POLICY_NEVER,
                      gtk.POLICY_AUTOMATIC)
        vbox.pack_start(sw, True, True)

        model = self.create_model()

        self.treeview = gtk.TreeView(model)
        self.treeview.set_rules_hint(True)

        sw.add(self.treeview)

        self.add_columns()

        self.set_default_size(640, 480)

        self.add_events(gdk.BUTTON_PRESS_MASK |
                       gdk.KEY_PRESS_MASK|
                       gdk.KEY_RELEASE_MASK)

    def add_columns(self):
        model = self.treeview.get_model()
        renderer = gtk.CellRendererText()

        for i in range(self.numCols):
            column = gtk.TreeViewColumn('%d'%i, gtk.CellRendererText(), text=i)
            self.treeview.append_column(column)

    def create_model(self):
        types = [gobject.TYPE_DOUBLE]*self.numCols
        store = gtk.ListStore(*types)

        for row in self.data:
            iter = store.append()
            pairs = []
            for i, num in enumerate(row): pairs.extend((i, num))

            store.set(iter, *pairs)
        return store

if __name__=='__main__':
    from matplotlib.numerix import rand
    view_array(rand(10,10))
    gtk.main()

John,

That makes sense. Tks vm.

I am still confused on what approach needs to be taken to get the data grids
to be *interactive* from the python command prompt. It seems to me that
such interactivity requires threading (ie, creating any new data grid gui
window in its own thread). Is that correct, or is there some other way to
do it?

In fact, with the example below, in order to get it to work, I needed to add
a couple of lines to call the mainloop:

from matplotlib.numerix import rand
from array_to_grid import view_array
view_array( rand(20,10))

<ArrayView object (GtkWindow) at 0x1136eb8>

import gtk
gtk.main()

After I call gtk.main(), I then lose all ability to interact with the python
command prompt :-(. This gui mainloop concept is something I am a little
confused on. I understand why one has to call such a mainloop for a gui: so
the gui window can be alerted by the os that some kind of event has been
fired, like a mouse click, so it can respond in the appropriate manner. But
I don't want to create an application that takes over the mainloop. I am
not writing a window-driven application. I want to continue to interact
with the python command prompt (and hopefully be able to interact with any
launched gui windows from it). So I suppose I have to figure out how to get
such mainloops to run in separate threads (or is "process" the correct word
here???) in order to have access to the python command prompt (and possibly
even create more data grids!). Is that correct? Im also a little confused
bc I have read statements like "all graphics commands should be handled in a
single thread." The "Thinking in Tkinter" web site
(http://www.ferg.org/thinking_in_tkinter/index.html) says:

          Note that you should not run these programs under IDLE.
          IDLE is itself a Tkinter application, with its own
          "mainloop" that will conflict with the mainloop in these
          programs. If you really want to view and run these
          programs using IDLE, then -- for each program -- you
          should comment out the "mainloop" statement in the
          program before running it.

That kind of warning sounds a little depressing. Is it not possible to
(somewhat easily) launch various gui windows, like a data grid, in their own
threads (processes?) and still have control of the python command prompt and
be able to interact with such gui windows?

Any pointers anyone can give me to learn more about launching interactive
gui widgets from the python command prompt and maintaining interactivity
with the python command prompt would be greatly appreciated.

Many thanks once again.

Sincerely,

Tom

···

-----Original Message-----
From: John Hunter [mailto:jdhunter@…4…]
Sent: Wednesday, August 18, 2004 1:31 PM
To: Thomas Barket
Cc: matplotlib-users@lists.sourceforge.net
Subject: Re: [Matplotlib-users] Requesting advice on multi-threaded
matplotlib session + grids displaying data

    > Btw, what does "TkAgg sets interactive mode to True when
    > you issue the show command" mean exactly?

It means that if you are using tkagg and issue show, it launches the
interactive interpreter (python shell)

    > Wx has such a grid widget which can be used for
    > displaying/editing data, which is what I was hoping to
    > use. However, I am not sure if one should mix different
    > gui's. Iow, if I use tkagg or gtk as my interactive
    > matplotlib gui, can I also display and interact with
    > wxpython grid widgets in the same script smoothly? Am I
    > asking for trouble having the same script display
    > interactive matplotlib charts using one gui type and then
    > display these grid widgets using another gui type? Or
    > should I just stick with one gui type throughout the
    > entire script so that the interactive matplotlib charts
    > use say gtk and the same script also uses gtk for its grid
    > widgets?

OK, now I see better where you are coming from. You have a deluge of data
coming back from the prompt in the interactive shell and are looking for a
better way to deal with it. This is really beyond the scope of matplotlib
since it is a plotting library and your question goes more to interacting
with data. See ipython for solutions to facilitate better interaction with
data.

I can give you a couple of pointers though.

If you save the return value of a plot as a named variable, the output will
be suppressed. Then you can use array slicing to only show a portion of it.

  1 >>> n, bins, patches = hist(randn(10000), 100) # no output printed
  2 >>> n[:5] # look at your data in slices using indexing
  Out[2]: [1,1,2,5,3,]

ipython has additional features to automatically suppress really large
arrays

  1 >>> rand(100,100)
  Out[1]: array (100,100) , type = d, has 10000 elements

On to your question about mixing GUIs. Don't do it. You will explode.

If you want to display your data in a wx grid, you could use the wxagg
matplotlib backend and write some functions to display the data in a wx
grid. Eg, if you are working in a shell that supports wx interactive work
(pycrust), you could write a function to display any array or vector in a wx
grid and then call that function interactively. Fernando is working on an
interactive shell (mentioned
previously) that supports matplotlib/gtk. Once he gets the kinks worked
out, he plans to support matplotlib/wx as well.

If you want to work in gtk (eg matplotlib/gtkagg) the equivalent to a wx
grid is a treeview/liststore. You can write functions to pipe arrays into
grids and then display them by calling that function interactively. Here is
an example using Fernando's ipython-gtk

  hunter:~/python/examples/pygtk> python ~/tmp/ip/ipython-gtk.py
  Extra content at the end of the document
  Python 2.3.2 (#1, Oct 13 2003, 11:33:15)
  [GCC 3.3.1] on linux2
  Type "copyright", "credits" or "license" for more information.
  (MatplotlibShell)

  1 >>> from matplotlib.numerix import rand
  2 >>> from array_to_grid import view_array
  3 >>> view_array( rand(20,10))
  Out[3]: <ArrayView object (GtkWindow) at 0x4136db94>

And this is the screenshot -
http://nitace.bsd.uchicago.edu:8080/files/share/Screenshot-Ipython-gtk.py.pn
g

While it would be possible for us to write functions in matplotlib that
would implement view_array (or something like it) for each of the GUI
backends, allowing you to call this function for tk, wx or gtk, it's really
beyond the scope of matplotlib (we're busy enough trying to plot!). It's
more in the domain of a matlab / mathematica like integrated scientific
computing environment, another topic near and dear to Fernando's heart.

Here is the code array_to_grid.py - you can do a lot more with treeviews and
liststores, eg make a proper editable spreadsheet interface with scroll bars
in both x and y directions, but this will get you started

'Display an array as a treeview'

import pygtk
pygtk.require('2.0')
import gobject
import gtk
from gtk import gdk

def view_array(X):
    'instantiate an ArrayView instance and show it'
    grid = ArrayView(X)
    grid.show_all()
    return grid
    
class ArrayView(gtk.Window):

    def __init__(self, X):
        gtk.Window.__init__(self)

        self.numRows, self.numCols = X.shape
        self.data = X

        self.set_title('Array display')
        self.set_border_width(8)

        vbox = gtk.VBox(False, 8)
        self.add(vbox)

        sw = gtk.ScrolledWindow()
        sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        sw.set_policy(gtk.POLICY_NEVER,
                      gtk.POLICY_AUTOMATIC)
        vbox.pack_start(sw, True, True)

        model = self.create_model()

        self.treeview = gtk.TreeView(model)
        self.treeview.set_rules_hint(True)

        sw.add(self.treeview)

        self.add_columns()

        self.set_default_size(640, 480)

        self.add_events(gdk.BUTTON_PRESS_MASK |
                       gdk.KEY_PRESS_MASK|
                       gdk.KEY_RELEASE_MASK)

    def add_columns(self):
        model = self.treeview.get_model()
        renderer = gtk.CellRendererText()

        for i in range(self.numCols):
            column = gtk.TreeViewColumn('%d'%i, gtk.CellRendererText(),
text=i)
            self.treeview.append_column(column)

    def create_model(self):
        types = [gobject.TYPE_DOUBLE]*self.numCols
        store = gtk.ListStore(*types)

        for row in self.data:
            iter = store.append()
            pairs = []
            for i, num in enumerate(row): pairs.extend((i, num))

            store.set(iter, *pairs)
        return store

if __name__=='__main__':
    from matplotlib.numerix import rand
    view_array(rand(10,10))
    gtk.main()