Create Pane For matplotlib chart

53 views
Skip to first unread message

felix74

unread,
Sep 17, 2012, 1:23:18 AM9/17/12
to leo-e...@googlegroups.com
I'm trying to create a interactive chart in a embedded in a new leo pane using matplotlib. However, I am not sure about the the best way  to implement this. I would appreciate some guidance on this please? The questions I would like answered are:
1/ How do I create a new blank pane for embedding a chart as well as other QtWidgets.
2/ Can I do this in a script or do I need to work with leo source 

The context for wanting to do this is that I want to create a data processing and visualization tool kit in leo. Like Excel but using nodes instead of columns. As such I have data in nodes and can create new data nodes by applying python functions to data in existing nodes. The thing missing is the visualization within a leo pane (I can easily launch a chart in it's own window) .

Terry Brown

unread,
Sep 17, 2012, 12:46:29 PM9/17/12
to leo-e...@googlegroups.com
On Sun, 16 Sep 2012 22:23:18 -0700 (PDT)
felix74 <hju...@googlemail.com> wrote:

> I'm trying to create a interactive chart in a embedded in a new leo pane
> using matplotlib. However, I am not sure about the the best way to
> implement this. I would appreciate some guidance on this please? The
> questions I would like answered are:
> 1/ How do I create a new blank pane for embedding a chart as well as other
> QtWidgets.
> 2/ Can I do this in a script or do I need to work with leo source

You can run this script from any body pane:
---cut here---
from PyQt4 import QtGui
class MatplotPaneProvider:
def __init__(self, c):
self.c = c
if hasattr(c, 'free_layout'):
splitter = c.free_layout.get_top_splitter()
if splitter:
splitter.register_provider(self)
def ns_provides(self):
return[('Add matplot', '_add_matplot_pane')]
def ns_provide(self, id_):
if id_ == '_add_matplot_pane':
c = self.c
w = QtGui.QSlider()
return w
def ns_provider_id(self):
# used by register_provider() to unregister previously registered
# providers of the same service
# provider ID is not the same as the service id_ above
return "completely unique value here"

MatplotPaneProvider(c)
---cut here---

Paste just as above and run the script. Nothing happens. Right click
on one of the pane dividers and select Insert. A new pane with a
button 'Action' appears. Click it, and select "Add matplot" from the
context menu.

Instead of "w = QtGui.QSlider()", you want "w = myMatplotWidget()"

Cheers -Terry

felix74

unread,
Sep 18, 2012, 8:59:59 AM9/18/12
to leo-e...@googlegroups.com
Terry,
 
Thanks for your help with this it was very helpful and a lot simpler than I feared. I have managed to get a matplotlib graph embedded within a pane in leo as a widget. I now need some help with how to interact with the widget using scripts in leo. I am unsure about the following:
 
1/ How do I expose the widget within th leo python environment?
Here I have created a self.mat in your MatplotPaneProvider class to make the windget accessible but it doesn't feel like the correct way to do this.
 
from PyQt4 import QtGui
class MatplotPaneProvider:
def __init__(self, c):
     self.c = c
     self.mat = myMatplotWidget()

     if hasattr(c, 'free_layout'):
         splitter = c.free_layout.get_top_splitter()
     if splitter:
         splitter.register_provider(self)
    def ns_provides(self):
         return[('Add matplot', '_add_matplot_pane')]
    def ns_provide(self, id_):
         if id_ == '_add_matplot_pane':
         c = self.c
         return self.mat
 
    def ns_provider_id(self):
# used by register_provider() to unregister previously registered
# providers of the same service
# provider ID is not the same as the service id_ above
return "completely unique value here"
 
mat = MatplotPaneProvider(c)
mat.mat.someMethod()
mat.mat.someOtherMethod()
 
2/I would also like to make the widget accessible from any script within leo. What's the leo way of doing this?
 
3/ If I create more than 1 pane containing these widgest. How do I switch between them in scripts?
 
4/ Running this script more than once creates multiple items for Add Matplot when pressing the Action button. How do I stop this from happening? I have alrewady tried returning a unique integer in  ns_provider_id but that did not work.
 
cheers
Hetal
--

Terry Brown

unread,
Sep 18, 2012, 9:41:20 AM9/18/12
to leo-e...@googlegroups.com
On Tue, 18 Sep 2012 05:59:59 -0700 (PDT)
felix74 <hju...@googlemail.com> wrote:

> Terry,
>
> Thanks for your help with this it was very helpful and a lot simpler than I
> feared. I have managed to get a matplotlib graph embedded within a pane in
> leo as a widget. I now need some help with how to interact with the
> widget using scripts in leo. I am unsure about the following:
>
> *1/ How do I expose the widget within th leo python environment?*

If you were only going to have one and you weren't going to destroy it,
you could just do something simple like c._matplot = self in its
constrictor (assuming c was passed to the constructor).

If you're going to have more than one and they may be destroyed, it
might be simplest to let the free_layout / nested_splitter system manage
them.

ts = c.free_layout.get_top_splitter()
matplotters = ts.findChildren(myMatplotWidget)

should return a list of the widgets of your class in the layout, but
only if they're in the main window, widgets in extra windows opened
from the "Open window" context menu item would be missed, I can add a
find_children() method to complement the find_child() method the
splitters already have to account for this.

Detail: the above is just using Qt's QObject.findChildren(), the
nested_splitter find_child() and (not yet written) find_children()
versions search the extra windows as well.

> Here I have created a self.mat in your MatplotPaneProvider class to make
> the windget accessible but it doesn't feel like the correct way to do this.

It should probably provide a fresh myMatplotWidget every time it's
called, so don't construct one in the Provider's init, but in the
ns_provide method.

> from PyQt4 import QtGui
> class MatplotPaneProvider:
> def __init__(self, c):
> self.c = c
> * self.mat = myMatplotWidget()*
> if hasattr(c, 'free_layout'):
[snip]
> *2/I would also like to make the widget accessible from any script within
> leo. What's the leo way of doing this?*

See above.

> *3/ If I create more than 1 pane containing these widgest. How do I switch
> between them in scripts?*

Above again :-)

> *4/ Running this script more than once creates multiple items for Add
> Matplot when pressing the Action button. How do I stop this from happening?
> I have alrewady tried returning a unique integer in * ns_provider_id *but
> that did not work.*

The value returned by ns_provider_id should be unique for the provider
class, but constant. So it can just return "matplotlib provider ver 1"
or something.

Cheers -Terry

Edward K. Ream

unread,
Apr 30, 2013, 6:17:53 PM4/30/13
to leo-editor
On Mon, Sep 17, 2012 at 11:46 AM, Terry Brown <terry_...@yahoo.com> wrote:
On Sun, 16 Sep 2012 22:23:18 -0700 (PDT)
felix74 <hju...@googlemail.com> wrote:

> I'm trying to create a interactive chart in a embedded in a new leo pane
> using matplotlib. However, I am not sure about the the best way  to
> implement this. I would appreciate some guidance on this please? The
> questions I would like answered are:
> 1/ How do I create a new blank pane for embedding a chart as well as other
> QtWidgets.
> 2/ Can I do this in a script or do I need to work with leo source

You can run this script from any body pane:

[Snip]

I'm going to file this under Leo/To Document for now.

Would this be a good blog item?  These blog items might eventually find their way into an ever-expanding "Topics" chapter.  What do you think?

Edward
Reply all
Reply to author
Forward
0 new messages