[ANN] wxPyPlot V1.4 Beta1

Hi All,

I have released Version 1.4 beta 1 of wxPyPlot for producing simple plots
in wxPython.

This version adds a few new features:
- A blank plot showing only axes, titles and legend can be made.
- Blank plot shown in demo (Draw5).
- Numeric or numarray can be used.
- Very small speed up when both axis extents are specified in Draw.

Users will require wxPython 2.4.0.6 or later and Numeric or numarray

For your viewing pleasure, the website now has some html docs as well as a
few more screen shots of things. Check out:
http://www.cyberus.ca/~g_will/wxPython/wxpyplot.html

Comments and suggestions welcome.

Regards,

Gordon Williams

···

-------------------------------------------------------------
What is wxPyPlot??

wxPyPlot is an enhanced derivative version of wxPlotCanvas to provide simple
lightweight plotting in wxPython. The emphasis is both on simple and
lightweight.

Before starting this work I looked at two plotting packages that could be
adapted to work with wxPython. SciPy Plt and Chaco are sophisticated and
powerful, but at the expense of consuming huge amounts of computer resources
for simple plots. They can be found at http://scipy.com. I was looking for
something that could be incorporated into a Boa application and had the
ability to plot lines with large numbers of points quickly for data capture
applications. wxPlotCanvas had the speed and some of the functionality that
I was looking for, but lacked a lot of features that I needed. This effort
has filled the gap.

Features:
- Automatic Scaling of Axes
- Legends for lines and markers
- Plot Title and Axis Labels
- Zoom Region with Mouse (Rubber Band) or Programmatically
- Scroll Up/Down, Left/Right
- Plot Grid (Graticule) on Graph
- Printing, Preview, and Page Set-up (margins) -WYSIWYG
- Cursor X-Y User Axis Values
- Simple, Lightweight and Fast
- Can be Used with Boa Applications if Desired
- Lots of Comments and Doc Strings along with Example Usage

I have tested this out on Windows using Python 2.3 and wxPython 2.4.1.2. If
you have the chance to test it on Linux, please let me know how it works.
Suggestions and improvements welcome.

Screen shots, source and instructions for Boa can be found at

http://www.cyberus.ca/~g_will/wxPython/wxpyplot.html

I have released Version 1.4 beta 1 of wxPyPlot for producing simple plots
in wxPython.

Excellent! I use wxPyPlot 1.39 with Boa for a vibration analysis app.
Two questions:
1. Can one make a multi-line legend? "\n" is rendered as a little box...
plotLines.append(PolyLine(data, legend=file+"\n next", colour=colours[fileIndex]))
I looked briefly at def _drawLegend
             #draw legend txt
             pnt= (trhc[0]+legendLHS+legendSymExt[0],
                 trhc[1]+s+lineHeight/2.-legendTextExt[1]/2)
             dc.DrawText(o.getLegend(),pnt[0],pnt[1])
but I'm not sure...

2. How does one do black background/white text?
         self.twoDplotCanvas.SetForegroundColour(wxColour(255, 255, 255))
         self.twoDplotCanvas.SetBackgroundColour(wxColour(0,0,0))
...
        self.twoDplotCanvas.Draw(
                PlotGraphics([plotLines[0]],"Data plot", "Hz", "G"), xAxis = None,
                 yAxis = None, dc = None)

has no effect, seemingly.

I liked the moving version too, but haven't needed it yet. Are you thinking of polar or 3-D? I might be able to "contribute" for the next project, otherwise I'll need to use Gnuplot or Chaco, I guess.

Ray
http://rjs.org/astro

Thanks, i get the idea and it works.

Zunbeltz

···

On Thu, 30 Oct 2003, RJS wrote:

>I have released Version 1.4 beta 1 of wxPyPlot for producing simple plots
>in wxPython.

Excellent! I use wxPyPlot 1.39 with Boa for a vibration analysis app.
Two questions:
1. Can one make a multi-line legend? "\n" is rendered as a little box...
plotLines.append(PolyLine(data, legend=file+"\n next",
colour=colours[fileIndex]))
I looked briefly at def _drawLegend
             #draw legend txt
             pnt= (trhc[0]+legendLHS+legendSymExt[0],
                 trhc[1]+s+lineHeight/2.-legendTextExt[1]/2)
             dc.DrawText(o.getLegend(),pnt[0],pnt[1])
but I'm not sure...

2. How does one do black background/white text?
         self.twoDplotCanvas.SetForegroundColour(wxColour(255, 255, 255))
         self.twoDplotCanvas.SetBackgroundColour(wxColour(0,0,0))
...
        self.twoDplotCanvas.Draw(
                PlotGraphics([plotLines[0]],"Data plot", "Hz", "G"), xAxis
= None,
                 yAxis = None, dc = None)

has no effect, seemingly.

I liked the moving version too, but haven't needed it yet. Are you thinking
of polar or 3-D? I might be able to "contribute" for the next project,
otherwise I'll need to use Gnuplot or Chaco, I guess.

Ray
CCD Astronomy

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org

Hi all,

For my FloatCanvas, I want to be able to enable interactive use by
passing on mouse events from the canvas to the enclosing window. THe
idea is that if someone clicks a mouse in the FloatCanvas, the mouse
event can be recieved by the parent of the FloatCanvas. There is an
added complication: I want to be add or change a data member of the
events, so that the handler can get the world coordinates of the mouse
event, rather than the pixel coordinates.

I have gotten this to work (borrowing from the Wiki):

FC_LEFT_DOWN = wxNewEventType()

def FC_EVT_LEFT_DOWN( window, function ):
    window.Connect( -1, -1, FC_LEFT_DOWN, function )

class MouseEvent(wxPyCommandEvent): #Base Class for all FloatCanvas
mouse events

    def __init__(self, EventType, WinID, Coords):
        wxPyCommandEvent.__init__(self, EventType, WinID)
        self.Coords = Coords
    
    def SetCoords(self,Coords):
        self.Coords = Coords
        
    def GetCoords(self):
        return self.Coords

class LeftDownEvent(MouseEvent):
    def __init__(self, WinID, Coords = None):
        MouseEvent.__init__(self, FC_LEFT_DOWN, WinID, Coords)

then, in my left button event handler:

            if event.LeftDown():
                pt = self.PixelToWorld( event.GetPosition() )
                evt = LeftDownEvent( self.GetId() )
                evt.SetCoords(pt)
                self.GetEventHandler().ProcessEvent(evt)

This is all fine and well, except that I now have to define a whole slew
of different mouse events, and they all have to have a huge number of
methods, if I want full functionality. I also need the full set of EVT_*
macros to bind them.

While working on this, it dawned on me that what would be really nifty
is to just take the native mouse event, add some informtion about world
coordinates to it, and then pass that on. I have gotten partway there:

One part that's tricky is that FloatCanvas consists of a wxPanel on
which stuff is Drawn, which then optionally sits on another wxPanel, so
that I can put a toolbar and such with it. Since, if I have this right,
wxMouseEvents are not CommandEvents, they don't get passe dup the
enclosing hierarchy. I solved this by haveing the event handler bound to
the DrawPanel event process the event in the enclosing wxPanel's
EventHandler:

self.GetEventHandler().ProcessEvent(event)

# self is the enclosing wxPanel, and event is the wx-generated event.

Then I catch that in the main wxPanel:

EVT_LEFT_DOWN(self, self.MainLeftButtonEvent)

and in that handler I process it in the parent's Event Handler:

    def MainLeftButtonEvent(self,event):
        print "in MainLeftButtonEvent"
        event.Coords = (45,65)
        self.GetParent().GetEventHandler().ProcessEvent(event)

Now I am almost there. I can catch the event in the enclosing frame, but
it doesn't see the added atribute: Coords. If I leave that off, it works
fine. If event was an ordinary Python class, I could just dynamically
add another atribute, but it doesn't seem to work in this case.

I was thinking of writting a factory function that would take the event
as a parameter, and create a new event object that had all the same
stuff, plus my added attribute, but then this new event object wouldn't
be the same kind, and wouldn't get caught by the same macro:

EVT_LEFT_DOWN

or would it?...hmmmm

Has anyone got any ideas? It feels like I am so close to an elegant
solution....

-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

Chris.Barker@noaa.gov

Hi all,

For my FloatCanvas, I want to be able to enable interactive use by
passing on mouse events from the canvas to the enclosing window. THe
idea is that if someone clicks a mouse in the FloatCanvas, the mouse
event can be recieved by the parent of the FloatCanvas. There is an
added complication: I want to be add or change a data member of the
events, so that the handler can get the world coordinates of the mouse
event, rather than the pixel coordinates.

I have gotten this to work (borrowing from the Wiki):

FC_LEFT_DOWN = wxNewEventType()

def FC_EVT_LEFT_DOWN( window, function ):
    window.Connect( -1, -1, FC_LEFT_DOWN, function )

class MouseEvent(wxPyCommandEvent): #Base Class for all FloatCanvas
mouse events

    def __init__(self, EventType, WinID, Coords):
        wxPyCommandEvent.__init__(self, EventType, WinID)
        self.Coords = Coords
    
    def SetCoords(self,Coords):
        self.Coords = Coords
        
    def GetCoords(self):
        return self.Coords

class LeftDownEvent(MouseEvent):
    def __init__(self, WinID, Coords = None):
        MouseEvent.__init__(self, FC_LEFT_DOWN, WinID, Coords)

then, in my left button event handler:

            if event.LeftDown():
                pt = self.PixelToWorld( event.GetPosition() )
                evt = LeftDownEvent( self.GetId() )
                evt.SetCoords(pt)
                self.GetEventHandler().ProcessEvent(evt)

This is all fine and well, except that I now have to define a whole slew
of different mouse events, and they all have to have a huge number of
methods, if I want full functionality. I also need the full set of EVT_*
macros to bind them.

While working on this, it dawned on me that what would be really nifty
is to just take the native mouse event, add some informtion about world
coordinates to it, and then pass that on. I have gotten partway there:

One part that's tricky is that FloatCanvas consists of a wxPanel on
which stuff is Drawn, which then optionally sits on another wxPanel, so
that I can put a toolbar and such with it. Since, if I have this right,
wxMouseEvents are not CommandEvents, they don't get passe dup the
enclosing hierarchy. I solved this by haveing the event handler bound to
the DrawPanel event process the event in the enclosing wxPanel's
EventHandler:

self.GetEventHandler().ProcessEvent(event)

# self is the enclosing wxPanel, and event is the wx-generated event.

Then I catch that in the main wxPanel:

EVT_LEFT_DOWN(self, self.MainLeftButtonEvent)

and in that handler I process it in the parent's Event Handler:

    def MainLeftButtonEvent(self,event):
        print "in MainLeftButtonEvent"
        event.Coords = (45,65)
        self.GetParent().GetEventHandler().ProcessEvent(event)

Now I am almost there. I can catch the event in the enclosing frame, but
it doesn't see the added atribute: Coords. If I leave that off, it works
fine. If event was an ordinary Python class, I could just dynamically
add another atribute, but it doesn't seem to work in this case.

I was thinking of writting a factory function that would take the event
as a parameter, and create a new event object that had all the same
stuff, plus my added attribute, but then this new event object wouldn't
be the same kind, and wouldn't get caught by the same macro:

EVT_LEFT_DOWN

or would it?...hmmmm

Has anyone got any ideas? It feels like I am so close to an elegant
solution....

-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

Chris.Barker@noaa.gov

Chris Barker wrote:

Now I am almost there. I can catch the event in the enclosing frame, but
it doesn't see the added atribute: Coords. If I leave that off, it works
fine. If event was an ordinary Python class, I could just dynamically
add another atribute, but it doesn't seem to work in this case.

Only the wxPyEvent and wxPyCommandEvent have the needed magic to preserve the Python instance... So you could go back to what you had before, but make the wxMouseEvent be an attribute of your custom MouseEvent class. Handler code could then get at the original mouse event data via that attribute.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

The last test told me something: the message got to the list (I can see
it in the web archives) but never got sent to me. Now I realize I havn't
got any messages from wxPython-users for a whiile, so I just
resubscribed, and now I'm trying again...

-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

Chris.Barker@noaa.gov

Chris Barker wrote:

The last test told me something: the message got to the list (I can see
it in the web archives) but never got sent to me. Now I realize I havn't
got any messages from wxPython-users for a whiile, so I just
resubscribed, and now I'm trying again...

Must be working again - I got both of your messages.

Bob

Robin Dunn wrote:

Only the wxPyEvent and wxPyCommandEvent have the needed magic to
preserve the Python instance... So you could go back to what you had
before, but make the wxMouseEvent be an attribute of your custom
MouseEvent class. Handler code could then get at the original mouse
event data via that attribute.

Hmm, I suspected as much, and had thought of that, but now I'm trying to
figure out how to keep from having to write a whole bunch of boilerplate
code... after all, there are something like 13 mouse events, and 13
EVT_* functions to go with them...

Do you think if I create a custom event, but pass the native event type
into the wxPyEvent __init__, that it could then get caught by the same
EVT_ macros as the regular mouse events?

Hmmm, I'm going to try something like this and see what I can come up
with.

-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

Hi all,

I'm working on some custom events, and I'm trying to work out how one is
supposed to post a wxPyEvent, rather than a wxPyCommandEvent. A command
event gets passed up the hierarchy of windows until it's processed, so
this works fine:

self.GetEventHandler().ProcessEvent(MyEvent)

and it gets caught in the containing window with a call to:

MY_EVT_LEFT_DOWN( window, function )

However, if MyEvent is a wxPyEvent instead, this doesn't work. I think
the Event is being processed just in self, and not passed on. I can get
iot to work with this:

self.GetParent().GetEventHandler().ProcessEvent(MyEvent)

but it seems very odd to specifically process the event in the parent.
Is there another way to do this, or is the cleanest way to do it?

By the way, I don't think I can use wxPostEvent, as I need it to be
handled right away.

-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

Chris.Barker@noaa.gov

Chris Barker wrote:

The last test told me something: the message got to the list (I can see
it in the web archives) but never got sent to me. Now I realize I havn't
got any messages from wxPython-users for a whiile, so I just
resubscribed, and now I'm trying again...

Once in a while a message will take a long time to be delivered but if you are not getting any then it probably is a subscription problem. Did resubscribing help?

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Chris Barker wrote:

However, if MyEvent is a wxPyEvent instead, this doesn't work. I think
the Event is being processed just in self, and not passed on.

That is correct, and is by design.

I can get
iot to work with this:

self.GetParent().GetEventHandler().ProcessEvent(MyEvent)

but it seems very odd to specifically process the event in the parent.
Is there another way to do this, or is the cleanest way to do it?

If you only want it to go to the parent that is the right way.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Chris Barker wrote:

Robin Dunn wrote:

Only the wxPyEvent and wxPyCommandEvent have the needed magic to preserve the Python instance... So you could go back to what you had before, but make the wxMouseEvent be an attribute of your custom MouseEvent class. Handler code could then get at the original mouse event data via that attribute.

Hmm, I suspected as much, and had thought of that, but now I'm trying to
figure out how to keep from having to write a whole bunch of boilerplate
code... after all, there are something like 13 mouse events, and 13
EVT_* functions to go with them...

Do you think if I create a custom event, but pass the native event type
into the wxPyEvent __init__, that it could then get caught by the same
EVT_ macros as the regular mouse events?

It should, but there could be problems if the event is caught by C++ code expecting to get a wxMouseEvent. If you're only doing this on the FloatCanvas or other panels, etc. though it should be fine.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

Once in a while a message will take a long time to be delivered but if
you are not getting any then it probably is a subscription problem. Did
resubscribing help?

yup, re-subscribing took care of it.

-CHB

···

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

Chris.Barker@noaa.gov

Robin Dunn wrote:

> Do you think if I create a custom event, but pass the native event type
> into the wxPyEvent __init__, that it could then get caught by the same
> EVT_ macros as the regular mouse events?

It should, but there could be problems if the event is caught by C++
code expecting to get a wxMouseEvent. If you're only doing this on the
FloatCanvas or other panels, etc. though it should be fine.

I tried this, and it works. I think since I'm using a wxPyEvent, rather
than a wxPyCommandEvent, it won't get caught anywhere else.

Now I'm closer, but not exactly what I want. This is what I'm doing now:

First create a new Event class that wraps the Native Events:

class MouseEvent(wxPyEvent): #Base Class for all FloatCanvas mouse
events
    def __init__(self, NativeEvent, WinID, Coords = None):
        wxPyEvent.__init__(self)

        # set the EventType so that it can be caught with the native
        # event binding functions
        self.SetEventType( NativeEvent.GetEventType() )
        self.NativeEvent = NativeEvent
        self.Coords = Coords
    
    def SetCoords(self,Coords):
        self.Coords = Coords
        
    def GetCoords(self):
        return self.Coords

Then make sure this event gets created and passed on:

In FloatCanvas.__init__:

EVT_LEFT_DOWN(self.DrawPanel, self.LeftButtonEvent)
# none that the DrawPanel is a panel on the FloatCanvas Panel

And in LeftButtonEvent:
                pt = self.PixelToWorld( event.GetPosition() )
                #evt = LeftDownEvent( self.GetId() )
                evt = MouseEvent(event, self.GetId(), pt)
                self.GetParent().GetEventHandler().ProcessEvent(evt)

Then in the Parent of the FloatCanvas:

EVT_LEFT_DOWN(self, self.OnLeftDown ) # the usual function will catch
                                      #the new Event, as it as the same
type.

So all is well and good, and I can access the Native event as an
attribute of the event that's handled. However, what I'd really like is
to have all themathods of the native event just there. Ordnarily, this
would be done by subclassing, but I can't subclass the wrapped event. It
seems Python's dynamicism should let me do this. I've tried adding the
following to the MouseEvent class:

    def __getattr__(self, name):
        return eval(self.NativeEvent.__getattr__(name)

But that doesn't work. The idea is to return the attribute of the Native
Event, but it gives me the following error:

File "/usr/lib/python2.3/site-packages/wxPython/events.py", line 384, in
__getattr__
AttributeError: GetPosition

The Native Event does have that attribute, so I don't understand what's
up. I clearly don't get how all the __getattr__ stuff works. Can anyone
help?

-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

Chris.Barker@noaa.gov

Chris Barker wrote:

So all is well and good, and I can access the Native event as an
attribute of the event that's handled. However, what I'd really like is
to have all themathods of the native event just there. Ordnarily, this
would be done by subclassing, but I can't subclass the wrapped event. It
seems Python's dynamicism should let me do this. I've tried adding the
following to the MouseEvent class:

    def __getattr__(self, name):
        return eval(self.NativeEvent.__getattr__(name)

But that doesn't work. The idea is to return the attribute of the Native
Event, but it gives me the following error:

Try this:

  def __getattr__(self, name):
    return getattr(self.NativeEvent, name)

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

Try this:

        def __getattr__(self, name):
                return getattr(self.NativeEvent, name)

Thanks Robin. I had just figured that out myself an hour or so ago, and
it does work. I'm still trying to figure out how to best structure this.
The way I have it now, the event is handles by the parent of the
FloatCanvas, but as it's possible to have other stuff in that parent,
other mouse events that don't originate at the canvas are getting caught
by the same handler. hmmm.

-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

Chris.Barker@noaa.gov