[SciPy-user] Chaco & wxWindows
pwang at enthought.com
Tue Nov 29 15:49:21 CST 2005
(I'm moving this thread to the scipy-chaco list, and CCing this message to the
general scipy-users list.)
Bas van Dijk wrote:
> The user should be able to zoom in and out and scroll over the plot
> (Preferably by using the +,- and arrow keys).
There is a very flexible interaction mechanism to allow composing these sorts
of behaviors. The zoom and pan interactions are already implemented, and
others can be derived easily from existing ones. (The pan interaction is
actually still on a branch and not the trunk, but it's easy enough to move
You just need to modify the previous code a little bit to add zooming:
from enthought.chaco.interaction.zoom_interaction import ZoomInteraction
class MyFrame ( wx.Frame ):
def __init__ ( self, *args, **kw ):
wx.Frame.__init__( *(self,) + args, **kw )
data = sin(arange(-5.0, 5.0, 0.3))
zoom = ZoomInteraction(reset_on_complete=True)
x_axis = PlotAxis(title="X axis")
y_axis = PlotAxis(title="Y axis")
plot = PlotValue(data, type="scatter,line",
axis_index = x_axis, axis = y_axis,
plot_window = Window(self, component=PlotComponent(plot))
There's a quirk in the zoom interaction that requires you to create the axes
explicitly, instead of letting the canvas create it automatically. Also,
there is no limit to the amount that a user can try to zoom, so you need to do
that yourself, e.g. by checking on the bound_low and bound_high of the axis
As written, the zoom interaction allows the user to select a rectangular
region with the left mouse button, and a single right-click will unzoom. You
can look at the code inside chaco/interactions/zoom_interaction to see how to
make your own interaction that behaves somewhat differently.
It's pretty trivial to adapt the existing interactions to use keypresses.
I've added a keyboard_pan_demo.py to chaco/demo/. Here is what the panning
interaction looks like:
stepsize = 10 # number of pixels to move left or right
accepts_focus = True
def _key_changed(self, event):
# event is an enable.events.KeyEvent; character is a simple char
# or the name of a control char (see enable.wx.window.key_map).
if event.character == "Right":
delta = self.stepsize
elif event.character == "Left":
delta = -self.stepsize
handled_axes = 
for plotvalue in self.canvas.values:
x_axis = plotvalue.axis_index
# Check for auto-scaling and turn it off.
if 'auto' in (x_axis.bound_low, x_axis.bound_high):
axis_info = plotvalue._axis_info_index
x_axis.bound_low = axis_info.min
x_axis.bound_high = axis_info.max
xscale = plotvalue._plot_sxdx / (x_axis.bound_high -
if x_axis not in handled_axes:
x_axis.bound_low += delta/xscale
x_axis.bound_high += delta/xscale
Note that as you pan, the axis scale labels on the bottom change, and so the
plot resizes a bit. This behavior can be mitigated by creating the axis with
a set format:
x_axis = PlotAxis(title="X axis", label_format="%2d")
Also note that you have to click on the plot first before it starts receiving
keyboard events. This is a known issue that's on my list of things to fix.
> It would also be nice if the user can change other things like the scale of
> the axes and maybe also the axes titles. But I already read in the excellent
> Chaco tutorial how to do that.
Great! But keep in mind that the tutorial is a little out of date with what's
in the SVN. :)
> Another question I have is if the Chaco plots can be used in an interactive
> manner? The application I developed is a logging program. It connects to a
> scientific instrument and starts plotting the values it receives.
Yes, after you've updated data, just call canvas.update() to schedule a redraw.
> The reason I want to use another plotting package (I'm now using scipy.plt) is
> that scipy.plt doesn't do double buffering. So when a new value comes in, the
> screen flickers when it is plotted.
> Do you know if Chaco can solve this problem?
Well, yes and no. Chaco does do double buffering, because the draw process is
done to an internal bitmap that then gets blitted by WX. However, if you
update too quickly, then flicker simply gets translated into "sluggishness",
i.e. things don't update in a responsive fashion. At what rate is your data
coming in? Perhaps you need to be buffering data, and not the graphics drawing?
More information about the SciPy-user