[Yt-svn] yt: 2 new changesets

hg at spacepope.org hg at spacepope.org
Thu Mar 25 23:30:03 PDT 2010


hg Repository: yt
details:   yt/rev/cd121e64b0dc
changeset: 1481:cd121e64b0dc
user:      Matthew Turk <matthewturk at gmail.com>
date:
Thu Mar 25 19:08:11 2010 -0700
description:
Updating pan-n-scan widget to work with zooming and updating the data range and
index range simultaneously.  This requires some new classes in the Chaco API
which I need to add here to be compiled & included if they do not exist in the
Chaco install on system.

hg Repository: yt
details:   yt/rev/0ea10be4b283
changeset: 1482:0ea10be4b283
user:      Matthew Turk <matthewturk at gmail.com>
date:
Thu Mar 25 23:29:56 2010 -0700
description:
Adding more stuff to the chaco interface

diffstat:

 yt/extensions/image_panner/pan_and_scan_widget.py |  121 +++++++++++++++++++++--
 1 files changed, 108 insertions(+), 13 deletions(-)

diffs (168 lines):

diff -r 915d0ab1b06b -r 0ea10be4b283 yt/extensions/image_panner/pan_and_scan_widget.py
--- a/yt/extensions/image_panner/pan_and_scan_widget.py	Thu Mar 25 13:50:32 2010 -0700
+++ b/yt/extensions/image_panner/pan_and_scan_widget.py	Thu Mar 25 23:29:56 2010 -0700
@@ -23,20 +23,80 @@
 
 # Major library imports
 from vm_panner import VariableMeshPanner
-from numpy import linspace, meshgrid, pi, sin, mgrid
+from numpy import linspace, meshgrid, pi, sin, mgrid, zeros
 
 # Enthought library imports
 from enthought.enable.api import Component, ComponentEditor, Window
-from enthought.traits.api import HasTraits, Instance, Button
+from enthought.traits.api import HasTraits, Instance, Button, Any, Callable, \
+        on_trait_change
 from enthought.traits.ui.api import Item, Group, View
 
 # Chaco imports
-from enthought.chaco.api import ArrayPlotData, jet, Plot
-from enthought.chaco.image_data import FunctionImageData
-from enthought.chaco.tools.api import PanTool, ZoomTool
+from enthought.chaco.api import ArrayPlotData, jet, Plot, HPlotContainer, \
+        ColorBar, DataRange1D, DataRange2D, LinearMapper, ImageData
+from enthought.chaco.tools.api import PanTool, ZoomTool, RangeSelection, \
+        RangeSelectionOverlay
 from enthought.chaco.tools.image_inspector_tool import ImageInspectorTool, \
      ImageInspectorOverlay
-from enthought.chaco.function_data_source import FunctionDataSource
+
+if not hasattr(DataRange2D, "_subranges_updated"):
+    print "You'll need to add _subranges updated to enthought/chaco/data_range_2d.py"
+    print 'Add this at the correct indentation level:'
+    print
+    print '    @on_trait_change("_xrange.updated,_yrange.updated")'
+    print '    def _subranges_updated(self):'
+    print '        self.updated = True'
+    print
+    raise RuntimeError
+
+class FunctionImageData(ImageData):
+    # The function to call with the low and high values of the range.
+    # It should return an array of values.
+    func = Callable
+
+    # A reference to a datarange
+    data_range = Instance(DataRange2D)
+
+    def __init__(self, **kw):
+        # Explicitly call the AbstractDataSource constructor because
+        # the ArrayDataSource ctor wants a data array
+        ImageData.__init__(self, **kw)
+        self.recalculate()
+
+    @on_trait_change('data_range.updated')
+    def recalculate(self):
+        if self.func is not None and self.data_range is not None:
+            newarray = self.func(self.data_range.low, self.data_range.high)
+            ImageData.set_data(self, newarray)
+        else:
+            self._data = zeros((512,512),dtype=float)
+
+    def set_data(self, *args, **kw):
+        raise RuntimeError("Cannot set numerical data on a FunctionDataSource")
+
+    def set_mask(self, mask):
+        # This would be REALLY FREAKING SLICK, but it's current unimplemented
+        raise NotImplementedError
+
+    def remove_mask(self):
+        raise NotImplementedError
+
+
+
+class ImagePixelizerHelper(object):
+    index = None
+    def __init__(self, panner):
+        self.panner = panner
+
+    def __call__(self, low, high):
+        b = self.panner.set_low_high(low, high)
+        if self.index is not None:
+            num_x_ticks = b.shape[0] + 1
+            num_y_ticks = b.shape[1] + 1
+            xs = mgrid[low[0]:high[0]:num_x_ticks*1j]
+            ys = mgrid[low[1]:high[1]:num_y_ticks*1j]
+            self.index.set_data( xs, ys )
+        return b
 
 class VariableMeshPannerView(HasTraits):
 
@@ -45,10 +105,11 @@
     panner = Instance(VariableMeshPanner)
     fid = Instance(FunctionImageData)
     limits = Button
+    helper = Any
     
     traits_view = View(
                     Group(
-                        Item('plot', editor=ComponentEditor(size=(512,512)), 
+                        Item('container', editor=ComponentEditor(size=(512,512)), 
                              show_label=False),
                         Item('limits', show_label=False),
                         orientation = "vertical"),
@@ -60,17 +121,21 @@
         super(VariableMeshPannerView, self).__init__(**kwargs)
         # Create the plot
         pd = ArrayPlotData()
+        plot = Plot(pd)
         self.pd = pd
-        fid = FunctionImageData(func = self.panner.set_low_high)
+        helper = ImagePixelizerHelper(self.panner)
+        fid = FunctionImageData(func = helper)
+        fid._data = self.panner.buffer
         self.fid = fid
         bounds = self.panner.bounds
         pd.set_data("imagedata", fid)
 
-        plot = Plot(pd)
-        img_plot = plot.img_plot("imagedata", colormap=jet)[0]
-
-        xlim, ylim = self.panner.bounds
-        plot.range2d.set_bounds( (xlim[0], ylim[0]), (xlim[1], ylim[1]) )
+        img_plot = plot.img_plot("imagedata", colormap=jet,
+                                 interpolation='nearest',
+                                 xbounds=(0.0, 1.0),
+                                 ybounds=(0.0, 1.0))[0]
+        helper.index = img_plot.index
+        self.helper = helper
 
         fid.data_range = plot.range2d
 
@@ -85,6 +150,36 @@
         img_plot.overlays.append(overlay)
         self.plot = plot
 
+        image_value_range = DataRange1D(fid)
+        cbar_index_mapper = LinearMapper(range=image_value_range)
+        self.colorbar = ColorBar(index_mapper=cbar_index_mapper,
+                                 plot=img_plot,
+                                 padding_right=40,
+                                 resizable='v',
+                                 width=30)
+
+        self.colorbar.tools.append(
+            PanTool(self.colorbar, constrain_direction="y", constrain=True))
+        zoom_overlay = ZoomTool(self.colorbar, axis="index", tool_mode="range",
+                                always_on=True, drag_button="right")
+        self.colorbar.overlays.append(zoom_overlay)
+
+        # create a range selection for the colorbar
+        range_selection = RangeSelection(component=self.colorbar)
+        self.colorbar.tools.append(range_selection)
+        self.colorbar.overlays.append(
+                RangeSelectionOverlay(component=self.colorbar,
+                                      border_color="white",
+                                      alpha=0.8, fill_color="lightgray"))
+
+        # we also want to the range selection to inform the cmap plot of
+        # the selection, so set that up as well
+        range_selection.listeners.append(img_plot)
+
+        self.container = HPlotContainer(padding=30)
+        self.container.add(self.colorbar)
+        self.container.add(self.plot)
+
     def _limits_fired(self):
         print self.pd["imagedata"].min(), self.pd["imagedata"].max(),
         print self.fid.data.min(), self.fid.data.max()



More information about the yt-svn mailing list