~ubuntu-branches/ubuntu/utopic/python-chaco/utopic

« back to all changes in this revision

Viewing changes to examples/demo/advanced/scalar_image_function_inspector_old.py

  • Committer: Package Import Robot
  • Author(s): Andrew Starr-Bochicchio
  • Date: 2014-06-01 17:04:08 UTC
  • mfrom: (7.2.5 sid)
  • Revision ID: package-import@ubuntu.com-20140601170408-m86xvdjd83a4qon0
Tags: 4.4.1-1ubuntu1
* Merge from Debian unstable. Remaining Ubuntu changes:
 - Let the binary-predeb target work on the usr/lib/python* directory
   as we don't have usr/share/pyshared anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""
2
 
Renders a colormapped image of a scalar value field, and a cross section
3
 
chosen by a line interactor.
4
 
"""
5
 
 
6
 
# Standard library imports
7
 
from optparse import OptionParser
8
 
import sys
9
 
 
10
 
# Major library imports
11
 
from numpy import array, linspace, meshgrid, nanmin, nanmax,  pi, zeros
12
 
 
13
 
# Enthought library imports
14
 
from chaco.api import ArrayDataSource, ArrayPlotData, ColorBar, ContourLinePlot, \
15
 
                                 ColormappedScatterPlot, CMapImagePlot, \
16
 
                                 ContourPolyPlot, DataRange1D, VPlotContainer, \
17
 
                                 DataRange2D, GridMapper, GridDataSource, \
18
 
                                 HPlotContainer, ImageData, LinearMapper, \
19
 
                                 LinePlot, OverlayPlotContainer, Plot, PlotAxis
20
 
from chaco.default_colormaps import *
21
 
from enable.component_editor import ComponentEditor
22
 
from chaco.tools.api import LineInspector, PanTool, RangeSelection, \
23
 
                                   RangeSelectionOverlay, ZoomTool
24
 
from enable.api import Window
25
 
from traits.api import Any, Array, Callable, CFloat, CInt, Enum, Event, Float, HasTraits, \
26
 
                             Int, Instance, Str, Trait, on_trait_change
27
 
from traitsui.api import Group, Handler, HGroup, Item, View
28
 
from traitsui.menu import Action, CloseAction, Menu, \
29
 
                                     MenuBar, NoButtons, Separator
30
 
 
31
 
 
32
 
class Model(HasTraits):
33
 
 
34
 
    #Traits view definitions:
35
 
    traits_view = View(
36
 
        Group(Item('function'),
37
 
              HGroup(Item('npts_x', label="Number X Points"),
38
 
                     Item('npts_y', label="Number Y Points")),
39
 
              HGroup(Item('min_x', label="Min X value"),
40
 
                     Item('max_x', label="Max X value")),
41
 
              HGroup(Item('min_y', label="Min Y value"),
42
 
                     Item('max_y', label="Max Y value"))),
43
 
                     buttons=["OK", "Cancel"])
44
 
 
45
 
    function = Str("tanh(x**2+y)*cos(y)*jn(0,x+y*2)")
46
 
 
47
 
    npts_x = CInt(400)
48
 
    npts_y = CInt(200)
49
 
 
50
 
    min_x = CFloat(-2*pi)
51
 
    max_x = CFloat(2*pi)
52
 
    min_y = CFloat(-1.5*pi)
53
 
    max_y = CFloat(1.5*pi)
54
 
 
55
 
    xs = Array
56
 
    ys = Array
57
 
    zs = Array
58
 
 
59
 
    minz = Float
60
 
    maxz = Float
61
 
 
62
 
    model_changed = Event
63
 
 
64
 
    def __init__(self, *args, **kwargs):
65
 
        super(Model, self).__init__(*args, **kwargs)
66
 
        self.compute_model()
67
 
 
68
 
    def compute_model(self):
69
 
        # The xs and ys used for the image plot range need to be the
70
 
        # edges of the cells.
71
 
        self.xs = linspace(self.min_x, self.max_x, self.npts_x+1)
72
 
        self.ys = linspace(self.min_y, self.max_y, self.npts_y+1)
73
 
 
74
 
        # The grid of points at which we will evaluate the 2D function
75
 
        # is located at cell centers, so use halfsteps from the
76
 
        # min/max values (which are edges)
77
 
        xstep = (self.max_x - self.min_x) / self.npts_x
78
 
        ystep = (self.max_y - self.min_y) / self.npts_y
79
 
        gridx = linspace(self.min_x+xstep/2, self.max_x-xstep/2, self.npts_x)
80
 
        gridy = linspace(self.min_y+xstep/2, self.max_y-xstep/2, self.npts_y)
81
 
        x, y = meshgrid(gridx, gridy)
82
 
        try:
83
 
            d = dict(x=x, y=y)
84
 
            exec "from scipy import *" in d
85
 
            exec "from scipy.special import *" in d
86
 
            self.zs = eval(self.function, d)
87
 
            self.minz = nanmin(self.zs)
88
 
            self.maxz = nanmax(self.zs)
89
 
            self.model_changed = True
90
 
            self._function = self.function
91
 
        except:
92
 
            self.set(function = self._function, trait_change_notify=False)
93
 
 
94
 
    def _anytrait_changed(self, name, value):
95
 
        if name in ['function', 'npts_x', 'npts_y',
96
 
                    'min_x', 'max_x', 'min_y', 'max_y']:
97
 
            self.compute_model()
98
 
 
99
 
 
100
 
class PlotUI(HasTraits):
101
 
 
102
 
    #Traits view definitions:
103
 
    traits_view = View(
104
 
        Group(Item('container',
105
 
                   editor=ComponentEditor(size=(800,600)),
106
 
                   show_label=False)),
107
 
        buttons=NoButtons,
108
 
        resizable=True)
109
 
 
110
 
    plot_edit_view = View(
111
 
        Group(Item('num_levels'),
112
 
              Item('colormap')),
113
 
              buttons=["OK","Cancel"])
114
 
 
115
 
 
116
 
    num_levels = Int(15)
117
 
    colormap = Enum(color_map_name_dict.keys())
118
 
 
119
 
    #---------------------------------------------------------------------------
120
 
    # Private Traits
121
 
    #---------------------------------------------------------------------------
122
 
 
123
 
    _image_index = Instance(GridDataSource)
124
 
    _image_value = Instance(ImageData)
125
 
 
126
 
    _cmap = Trait(jet, Callable)
127
 
 
128
 
    #---------------------------------------------------------------------------
129
 
    # Public View interface
130
 
    #---------------------------------------------------------------------------
131
 
 
132
 
    def __init__(self, *args, **kwargs):
133
 
        super(PlotUI, self).__init__(*args, **kwargs)
134
 
        self.create_plot()
135
 
 
136
 
    def create_plot(self):
137
 
 
138
 
        # Create the mapper, etc
139
 
        self._image_index = GridDataSource(array([]),
140
 
                                          array([]),
141
 
                                          sort_order=("ascending","ascending"))
142
 
        image_index_range = DataRange2D(self._image_index)
143
 
        self._image_index.on_trait_change(self._metadata_changed,
144
 
                                          "metadata_changed")
145
 
 
146
 
        self._image_value = ImageData(data=array([]), value_depth=1)
147
 
        image_value_range = DataRange1D(self._image_value)
148
 
 
149
 
 
150
 
 
151
 
        # Create the contour plots
152
 
        self.polyplot = ContourPolyPlot(index=self._image_index,
153
 
                                        value=self._image_value,
154
 
                                        index_mapper=GridMapper(range=
155
 
                                            image_index_range),
156
 
                                        color_mapper=\
157
 
                                            self._cmap(image_value_range),
158
 
                                        levels=self.num_levels)
159
 
 
160
 
        self.lineplot = ContourLinePlot(index=self._image_index,
161
 
                                        value=self._image_value,
162
 
                                        index_mapper=GridMapper(range=
163
 
                                            self.polyplot.index_mapper.range),
164
 
                                        levels=self.num_levels)
165
 
 
166
 
 
167
 
        # Add a left axis to the plot
168
 
        left = PlotAxis(orientation='left',
169
 
                        title= "y",
170
 
                        mapper=self.polyplot.index_mapper._ymapper,
171
 
                        component=self.polyplot)
172
 
        self.polyplot.overlays.append(left)
173
 
 
174
 
        # Add a bottom axis to the plot
175
 
        bottom = PlotAxis(orientation='bottom',
176
 
                          title= "x",
177
 
                          mapper=self.polyplot.index_mapper._xmapper,
178
 
                          component=self.polyplot)
179
 
        self.polyplot.overlays.append(bottom)
180
 
 
181
 
 
182
 
        # Add some tools to the plot
183
 
        self.polyplot.tools.append(PanTool(self.polyplot,
184
 
                                           constrain_key="shift"))
185
 
        self.polyplot.overlays.append(ZoomTool(component=self.polyplot,
186
 
                                            tool_mode="box", always_on=False))
187
 
        self.polyplot.overlays.append(LineInspector(component=self.polyplot,
188
 
                                               axis='index_x',
189
 
                                               inspect_mode="indexed",
190
 
                                               write_metadata=True,
191
 
                                               is_listener=False,
192
 
                                               color="white"))
193
 
        self.polyplot.overlays.append(LineInspector(component=self.polyplot,
194
 
                                               axis='index_y',
195
 
                                               inspect_mode="indexed",
196
 
                                               write_metadata=True,
197
 
                                               color="white",
198
 
                                               is_listener=False))
199
 
 
200
 
        # Add these two plots to one container
201
 
        contour_container = OverlayPlotContainer(padding=20,
202
 
                                                 use_backbuffer=True,
203
 
                                                 unified_draw=True)
204
 
        contour_container.add(self.polyplot)
205
 
        contour_container.add(self.lineplot)
206
 
 
207
 
 
208
 
        # Create a colorbar
209
 
        cbar_index_mapper = LinearMapper(range=image_value_range)
210
 
        self.colorbar = ColorBar(index_mapper=cbar_index_mapper,
211
 
                                 plot=self.polyplot,
212
 
                                 padding_top=self.polyplot.padding_top,
213
 
                                 padding_bottom=self.polyplot.padding_bottom,
214
 
                                 padding_right=40,
215
 
                                 resizable='v',
216
 
                                 width=30)
217
 
 
218
 
        self.pd = ArrayPlotData(line_index = array([]),
219
 
                                line_value = array([]),
220
 
                                scatter_index = array([]),
221
 
                                scatter_value = array([]),
222
 
                                scatter_color = array([]))
223
 
 
224
 
        self.cross_plot = Plot(self.pd, resizable="h")
225
 
        self.cross_plot.height = 100
226
 
        self.cross_plot.padding = 20
227
 
        self.cross_plot.plot(("line_index", "line_value"),
228
 
                             line_style="dot")
229
 
        self.cross_plot.plot(("scatter_index","scatter_value","scatter_color"),
230
 
                             type="cmap_scatter",
231
 
                             name="dot",
232
 
                             color_mapper=self._cmap(image_value_range),
233
 
                             marker="circle",
234
 
                             marker_size=8)
235
 
 
236
 
        self.cross_plot.index_range = self.polyplot.index_range.x_range
237
 
 
238
 
        self.pd.set_data("line_index2", array([]))
239
 
        self.pd.set_data("line_value2", array([]))
240
 
        self.pd.set_data("scatter_index2", array([]))
241
 
        self.pd.set_data("scatter_value2", array([]))
242
 
        self.pd.set_data("scatter_color2", array([]))
243
 
 
244
 
        self.cross_plot2 = Plot(self.pd, width = 140, orientation="v", resizable="v", padding=20, padding_bottom=160)
245
 
        self.cross_plot2.plot(("line_index2", "line_value2"),
246
 
                             line_style="dot")
247
 
        self.cross_plot2.plot(("scatter_index2","scatter_value2","scatter_color2"),
248
 
                             type="cmap_scatter",
249
 
                             name="dot",
250
 
                             color_mapper=self._cmap(image_value_range),
251
 
                             marker="circle",
252
 
                             marker_size=8)
253
 
 
254
 
        self.cross_plot2.index_range = self.polyplot.index_range.y_range
255
 
 
256
 
 
257
 
 
258
 
        # Create a container and add components
259
 
        self.container = HPlotContainer(padding=40, fill_padding=True,
260
 
                                        bgcolor = "white", use_backbuffer=False)
261
 
        inner_cont = VPlotContainer(padding=0, use_backbuffer=True)
262
 
        inner_cont.add(self.cross_plot)
263
 
        inner_cont.add(contour_container)
264
 
        self.container.add(self.colorbar)
265
 
        self.container.add(inner_cont)
266
 
        self.container.add(self.cross_plot2)
267
 
 
268
 
 
269
 
    def update(self, model):
270
 
        self.minz = model.minz
271
 
        self.maxz = model.maxz
272
 
        self.colorbar.index_mapper.range.low = self.minz
273
 
        self.colorbar.index_mapper.range.high = self.maxz
274
 
        self._image_index.set_data(model.xs, model.ys)
275
 
        self._image_value.data = model.zs
276
 
        self.pd.set_data("line_index", model.xs)
277
 
        self.pd.set_data("line_index2", model.ys)
278
 
        self.container.invalidate_draw()
279
 
        self.container.request_redraw()
280
 
 
281
 
 
282
 
    #---------------------------------------------------------------------------
283
 
    # Event handlers
284
 
    #---------------------------------------------------------------------------
285
 
 
286
 
    def _metadata_changed(self, old, new):
287
 
        """ This function takes out a cross section from the image data, based
288
 
        on the line inspector selections, and updates the line and scatter
289
 
        plots."""
290
 
 
291
 
        self.cross_plot.value_range.low = self.minz
292
 
        self.cross_plot.value_range.high = self.maxz
293
 
        self.cross_plot2.value_range.low = self.minz
294
 
        self.cross_plot2.value_range.high = self.maxz
295
 
        if self._image_index.metadata.has_key("selections"):
296
 
            x_ndx, y_ndx = self._image_index.metadata["selections"]
297
 
            if y_ndx and x_ndx:
298
 
                self.pd.set_data("line_value",
299
 
                                 self._image_value.data[y_ndx,:])
300
 
                self.pd.set_data("line_value2",
301
 
                                 self._image_value.data[:,x_ndx])
302
 
                xdata, ydata = self._image_index.get_data()
303
 
                xdata, ydata = xdata.get_data(), ydata.get_data()
304
 
                self.pd.set_data("scatter_index", array([xdata[x_ndx]]))
305
 
                self.pd.set_data("scatter_index2", array([ydata[y_ndx]]))
306
 
                self.pd.set_data("scatter_value",
307
 
                    array([self._image_value.data[y_ndx, x_ndx]]))
308
 
                self.pd.set_data("scatter_value2",
309
 
                    array([self._image_value.data[y_ndx, x_ndx]]))
310
 
                self.pd.set_data("scatter_color",
311
 
                    array([self._image_value.data[y_ndx, x_ndx]]))
312
 
                self.pd.set_data("scatter_color2",
313
 
                    array([self._image_value.data[y_ndx, x_ndx]]))
314
 
        else:
315
 
            self.pd.set_data("scatter_value", array([]))
316
 
            self.pd.set_data("scatter_value2", array([]))
317
 
            self.pd.set_data("line_value", array([]))
318
 
            self.pd.set_data("line_value2", array([]))
319
 
 
320
 
    def _colormap_changed(self):
321
 
        self._cmap = color_map_name_dict[self.colormap]
322
 
        if hasattr(self, "polyplot"):
323
 
            value_range = self.polyplot.color_mapper.range
324
 
            self.polyplot.color_mapper = self._cmap(value_range)
325
 
            value_range = self.cross_plot.color_mapper.range
326
 
            self.cross_plot.color_mapper = self._cmap(value_range)
327
 
            # FIXME: change when we decide how best to update plots using
328
 
            # the shared colormap in plot object
329
 
            self.cross_plot.plots["dot"][0].color_mapper = self._cmap(value_range)
330
 
            self.cross_plot2.plots["dot"][0].color_mapper = self._cmap(value_range)
331
 
            self.container.request_redraw()
332
 
 
333
 
    def _num_levels_changed(self):
334
 
        if self.num_levels > 3:
335
 
            self.polyplot.levels = self.num_levels
336
 
            self.lineplot.levels = self.num_levels
337
 
 
338
 
 
339
 
 
340
 
class Controller(Handler):
341
 
 
342
 
    #---------------------------------------------------------------------------
343
 
    # State traits
344
 
    #---------------------------------------------------------------------------
345
 
 
346
 
    model = Instance(Model)
347
 
    view = Instance(PlotUI)
348
 
 
349
 
    #---------------------------------------------------------------------------
350
 
    # Handler interface
351
 
    #---------------------------------------------------------------------------
352
 
 
353
 
    def init(self, info):
354
 
        self.model = info.object.model
355
 
        self.view = info.object.view
356
 
        self.model.on_trait_change(self._model_changed, "model_changed")
357
 
 
358
 
 
359
 
    #---------------------------------------------------------------------------
360
 
    # Public Controller interface
361
 
    #---------------------------------------------------------------------------
362
 
 
363
 
    def edit_model(self, ui_info):
364
 
        self.model.configure_traits()
365
 
 
366
 
    def edit_plot(self, ui_info):
367
 
        self.view.configure_traits(view="plot_edit_view")
368
 
 
369
 
 
370
 
    #---------------------------------------------------------------------------
371
 
    # Private Controller interface
372
 
    #---------------------------------------------------------------------------
373
 
 
374
 
    def _model_changed(self):
375
 
        if self.view is not None:
376
 
            self.view.update(self.model)
377
 
 
378
 
class ModelView(HasTraits):
379
 
 
380
 
    model = Instance(Model)
381
 
    view = Instance(PlotUI)
382
 
    traits_view = View(Item('@view',
383
 
                            show_label=False),
384
 
                       menubar=MenuBar(Menu(Action(name="Edit Model",
385
 
                                                   action="edit_model"),
386
 
                                            Action(name="Edit Plot",
387
 
                                                   action="edit_plot"),
388
 
                                            CloseAction,
389
 
                                            name="File")),
390
 
                       handler = Controller,
391
 
                       title = "Function Inspector",
392
 
                       resizable=True)
393
 
 
394
 
    @on_trait_change('model, view')
395
 
    def update_view(self):
396
 
        if self.model is not None and self.view is not None:
397
 
            self.view.update(self.model)
398
 
 
399
 
options_dict = {'colormap' : "jet",
400
 
                'num_levels' : 15,
401
 
                'function' : "tanh(x**2+y)*cos(y)*jn(0,x+y*2)"}
402
 
model=Model(**options_dict)
403
 
view=PlotUI(**options_dict)
404
 
popup = ModelView(model=model, view=view)
405
 
 
406
 
def show_plot(**kwargs):
407
 
    model = Model(**kwargs)
408
 
    view = PlotUI(**kwargs)
409
 
    modelview=ModelView(model=model, view=view)
410
 
    modelview.configure_traits()
411
 
 
412
 
def main(argv=None):
413
 
 
414
 
    if argv is None:
415
 
        argv = sys.argv
416
 
 
417
 
    usage = "usage: %prog [options]"
418
 
    parser = OptionParser(usage=usage, version="%prog 1.0")
419
 
 
420
 
    parser.add_option("-c", "--colormap",
421
 
                  action="store", type="string", dest="colormap", default="jet",
422
 
                  metavar="CMAP", help="choose a default colormapper")
423
 
 
424
 
    parser.add_option("-n", "--nlevels",
425
 
                  action="store", type="int", dest="num_levels", default=15,
426
 
                  help="number countour levels to plot [default: %default]")
427
 
 
428
 
    parser.add_option("-f", "--function",
429
 
                  action="store", type="string", dest="function",
430
 
                  default="tanh(x**2+y)*cos(y)*jn(0,x+y*2)",
431
 
                  help="function of x and y [default: %default]")
432
 
 
433
 
    opts, args = parser.parse_args(argv[1:])
434
 
 
435
 
    if len(args) > 0:
436
 
        parser.error("Incorrect number of arguments")
437
 
 
438
 
    show_plot(colormap=opts.colormap, num_levels=opts.num_levels,
439
 
              function=opts.function)
440
 
 
441
 
if __name__ == "__main__":
442
 
    sys.exit(main())