Category Archives: Chaco

Up Next: Step-by-step Chaco

We got a lot of great feedback from the folks who joined June’s Scientific Computing with Python webinar. Many attendees were very impressed by Chaco and there was a resounding request for a closer look into this 2D plotting tool. So July’s webinar will offer a practical, step-by-step Chaco demonstration.

Chaco screenshots

Also, we’ve put up a schedule of future SCP webinars that takes us into 2010. We really like this series and the exposure it brings to the powerful visualization and analysis tools Python offers scientists. We encourage you to tell your friends and colleagues we have the ability to host up to 1001 guests at these events! Don’t forget that if you miss the meeting, we make our recordings available on our website and and our slides are published at Slideshare.

Once again:

Scientific Computing with Python Webinar

Step-by-step Chaco: 2D plotting with the Enthought Tool Suite

July 17, 2009
1pm CDT(6pm UTC)

register at GoToMeeting

See you next Friday!

Revamped Plot Toolbar

Last October I added a toolbar for Chaco plots. It was functional, but it wasn’t very pretty. I decided to rewrite it from scratch, with emphasis on improving the appearance and improving the auto-hide feature.

The new toolbar also employs a new feature to Enable: gradients! Gradient support is still a work in progress, but improving daily.

PlotToolbar example screenshot

Plotting and status indicators

A while ago I was working on an app, where I often got empty plots. It was completely valid for the plot to be empty, though often an empty plot was the result of an error in the code. Unfortunately, there was no easy way to indicate which condition was causing the empty plot without watching the console.

There were a couple of methods I could use:

  1. Show the log file in the UI
  2. Add a status indicator to the UI

There are a number of problems showing the log file: it takes up a lot of screen real estate, it is not obvious any particular log entry is the cause, and the log entry may require knowledge of the application internals to decipher.

So once I decided that I wanted a status indicator in the IU, the follow up question is, where? I started looking at some of the apps I use most frequently: how does Firefox indicate an error? It shows a little icon in the bottom right corner. I had never noticed it until I started looking for it, which makes it a bad example to me. In comparison, Google Chrome gives you a nice image and error message right where your eyes are focused (in the document pane). Right away the user knows there is an error.

I started thinking about how to display status indicators on Chaco plots. All of the framework was already in place, all that was needed was an Overlay class which could display an image. I decided to use SVG images rather than PNG’s so they can be scaled depending on the size of the plot, though I might be convinced to allow other image formats as well as text.

This screenshot is from the status_overlay.py example. The code (and images) should be considered a work in progress, though it is stable enough to begin using. For those that try it out, there is a nice fade effect too.


chaco erroroverlay

Chaco toolbars

I’ve always wanted a toolbar for Chaco to do simple tasks like copying a plot to the clipboard or saving a plot. A few months ago I decided to do something about it while working on a customer project. Today I finally got around to refactoring the toolbar and the one in BlockCanvas which it was based on. Its a little rough still, mostly because of mismatched icons, but it is fully functional. I’ve added an example to the Chaco examples, which this is a screenshot of. The best part is that the toolbar is extensible so you can make a toolbar with only the buttons you want. I have more plans for the toolbar which I’ll be discussing in the coming weeks…

Chaco Toolbar

Making a Chaco highlight legend

Last week I posted an example of how to use an interactive Chaco tool to highlight selected plots, this week I’m providing a working example using it.

First we need to define the tool, which inherits from Enable’s BaseTool. We override the normal_mouse_move method, which is called every time the mouse moves when neither mouse button is down. The normal_mouse_move method performs a hit test on the legend, highlighting the selected lines and dimming the others.

[sourcecode language=python]
class HighlightLegend(BaseTool):
_selected_plot = Any
_selected_renderers = List

def _get_hit_plots(self, event):
legend=self.component
if legend is None or not legend.is_in(event.x, event.y):
return []

label = legend.get_label_at(event.x, event.y)
if label is None:
return []

index = legend._cached_labels.index(label)
label_name = legend._cached_label_names[index]
return legend.plots[label_name]

def normal_mouse_move(self, event):
new = set(self._get_hit_plots(event))
old = set(self._selected_renderers)

if old == new:
new = set()

# select the new ones:
for renderer in new – old:
self._select(renderer)

# deselect the old ones that are not new
for renderer in old – new:
self._deselect(renderer)

self._selected_renderers = list(new)

def _select(self, selected):
“”” Decorates a plot to indicate it is selected “””
for plot in reduce(operator.add, selected.container.plots.values()):
if plot != selected:
plot.alpha /= 3
else:
plot.line_width *= 2

plot.request_redraw()

def _deselect(self, selected):
for plot in reduce(operator.add, selected.container.plots.values()):
if plot != selected:
plot.alpha *= 3
else:
plot.line_width /= 2

plot.request_redraw()
[/sourcecode]

All that is left to do is attach the new tool to the legend. In this example a plot is created with 2 data series then the plot is made visible and hooked up to the new tool

[sourcecode language=python]
class MyPlot(HasTraits):
plot = Instance(Plot)

traits_view = View(Item(‘plot’, editor=ComponentEditor()))

def __init__(self, index, series1, series2, **kw):
super(MyPlot, self).__init__(**kw)

plot_data = ArrayPlotData(index=index)
plot_data.set_data(‘series1’, series1)
plot_data.set_data(‘series2’, series2)
self.plot = Plot(plot_data)
self.plot.plot((‘index’, ‘series1’))
self.plot.plot((‘index’, ‘series2’))

self.plot.legend.visible = True
self.plot.legend.tools.append(HighlightLegend(self.plot.legend))
[/sourcecode]

By popular demand, here are two screenshots, one without any highlighting, and another with one series highlighted:
not highlighed
highlighted

Plot highlighting using alpha values

I recently added support for changing the alpha of a plot after it has been constructed. Combined with a selection tool you get a really nice highlight feature. In this example, when a plot is selected I double its width and set the alpha of the other plots to 1/3 of their normal value.

plot with alpha

[sourcecode language=”python”]
def _select(self, selected):
“”” Decorates a plot to indicate it is selected “””
for plot in reduce(operator.add, selected.container.plots.values()):
if plot != selected:
plot.alpha /= 3
else:
plot.line_width *= 2

plot.request_redraw()

def _deselect(self, selected):
for plot in reduce(operator.add, selected.container.plots.values()):
if plot != selected:
plot.alpha *= 3
else:
plot.line_width /= 2

plot.request_redraw()
[/sourcecode]

SciPy 2008 Swarm

During the “State of SciPy” presentation that Jarrod Millman and I gave this year at the SciPy 2008 Conference, we showed a “code swarm” video that was put together by David Martin and Chris Galvan. It’s a first-of-it’s-kind, because it combines repositories from several projects; namely NumPy, SciPy, Mayavi, Chaco, Traits, and Matplotlib.

Among other things, you can see how the number of people involved and the level of code production has really accelerated over time.

Enjoy!

Click Here for the Video