~ubuntu-branches/ubuntu/precise/python-chaco/precise

« back to all changes in this revision

Viewing changes to examples/canvas/canvas.py

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2008-12-29 02:34:05 UTC
  • Revision ID: james.westby@ubuntu.com-20081229023405-x7i4kp9mdxzmdnvu
Tags: upstream-3.0.1
ImportĀ upstreamĀ versionĀ 3.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
"""
 
3
The main app for the PlotCanvas application
 
4
"""
 
5
 
 
6
MULTITOUCH = False
 
7
DEBUG = False
 
8
 
 
9
# Major library imports
 
10
from copy import copy
 
11
from numpy import arange, fabs, linspace, pi, sin
 
12
from numpy import random
 
13
from scipy.special import jn
 
14
 
 
15
 
 
16
# Enthought library imports
 
17
from enthought.enable.api import Viewport, Window
 
18
from enthought.enable.tools.api import MoveTool, ResizeTool, ViewportPanTool
 
19
from enthought.enable.example_support import DemoFrame, demo_main
 
20
from enthought.traits.api import Any, Bool, Enum, Float, HasTraits, Instance, \
 
21
                                 List, Str
 
22
 
 
23
 
 
24
# Chaco imports
 
25
from enthought.chaco.api import AbstractOverlay, ArrayPlotData, \
 
26
        Plot, jet, ScatterPlot, LinePlot, LinearMapper
 
27
from enthought.chaco.tools.api import PanTool, SimpleZoom , LegendTool
 
28
 
 
29
# Canvas imports
 
30
from enthought.chaco.plot_canvas import PlotCanvas
 
31
from enthought.chaco.plot_canvas_toolbar import PlotCanvasToolbar, PlotToolbarButton
 
32
from transient_plot_overlay import TransientPlotOverlay
 
33
from axis_tool import AxisTool, RangeController, MPAxisTool
 
34
from plot_clone_tool import PlotCloneTool, MPPlotCloneTool
 
35
from data_source_button import ButtonController, DataSourceButton
 
36
from mp_move_tool import MPMoveTool
 
37
from mp_viewport_pan_tool import MPViewportPanTool
 
38
#from canvas_grid import CanvasGrid
 
39
 
 
40
# Multitouch imports
 
41
if MULTITOUCH:
 
42
    from mptools import MPPanTool, MPDragZoom, MPLegendTool, \
 
43
            MPPanZoom, MPRangeSelection
 
44
    #AxisTool = MPAxisTool
 
45
    PlotCloneTool = MPPlotCloneTool
 
46
 
 
47
NUMPOINTS = 250
 
48
DATA = {
 
49
    "GOOG": random.uniform(-2.0, 10.0, NUMPOINTS),
 
50
    "MSFT": random.uniform(-2.0, 10.0, NUMPOINTS),
 
51
    "AAPL": random.uniform(-2.0, 10.0, NUMPOINTS),
 
52
    "YHOO": random.uniform(-2.0, 10.0, NUMPOINTS),
 
53
    "CSCO": random.uniform(-2.0, 10.0, NUMPOINTS),
 
54
    "INTC": random.uniform(-2.0, 10.0, NUMPOINTS),
 
55
    "ORCL": random.uniform(-2.0, 10.0, NUMPOINTS),
 
56
    "HPQ": random.uniform(-2.0, 10.0, NUMPOINTS),
 
57
    "DELL": random.uniform(-2.0, 10.0, NUMPOINTS),
 
58
    }
 
59
 
 
60
 
 
61
 
 
62
def add_basic_tools(plot):
 
63
    plot.tools.append(PanTool(plot))
 
64
    plot.tools.append(MoveTool(plot, drag_button="right"))
 
65
    zoom = SimpleZoom(component=plot, tool_mode="box", always_on=False)
 
66
    plot.overlays.append(zoom)
 
67
 
 
68
def do_plot(name, pd):
 
69
    xname = name + "_x"
 
70
    yname = name + "_y"
 
71
    pd.set_data(xname, range(len(DATA[name])))
 
72
    pd.set_data(yname, DATA[name])
 
73
    
 
74
    plot = Plot(pd, padding = 30,
 
75
                unified_draw = True,
 
76
                border_visible = True,
 
77
                )
 
78
    plot.x_axis.visible = False
 
79
    plot.title = name
 
80
    plot.plot((xname, yname), name=name, type="line", color="blue",)
 
81
    return plot
 
82
 
 
83
def clone_renderer(r):
 
84
    """ Returns a clone of plot renderer r """
 
85
    basic_traits = ["orientation", "line_width", "color", "outline_color", 
 
86
                    "bgcolor", "border_visible", "border_color", "visible",
 
87
                    "fill_padding", "resizable", "aspect_ratio",
 
88
                    "draw_layer", "draw_order", "border_width", "resizable",
 
89
                    "index", "value",]
 
90
 
 
91
    scatter_traits = ["custom_symbol", "marker", "marker_size", "selection_marker",
 
92
                      "selection_marker_size", "selection_line_width",
 
93
                      "selection_color"]
 
94
 
 
95
    line_traits = ["selected_color", "selected_line_style", "metadata_name",
 
96
                   "render_style"]
 
97
 
 
98
    if isinstance(r, ScatterPlot):
 
99
        return r.clone_traits(basic_traits + scatter_traits)
 
100
    elif isinstance(r, LinePlot):
 
101
        return r.clone_traits(basic_traits + line_traits)
 
102
 
 
103
def clone_plot(clonetool, drop_position):
 
104
    # A little sketchy...
 
105
    canvas = clonetool.component.container.component.component
 
106
 
 
107
    # Create a new Plot object
 
108
    oldplot = clonetool.component
 
109
    newplot = Plot(oldplot.data)
 
110
    basic_traits = ["orientation", "default_origin", "bgcolor", "border_color",
 
111
                    "border_width", "border_visible", "draw_layer", "unified_draw",
 
112
                    "fit_components", "fill_padding", "visible", "aspect_ratio",
 
113
                    "title"]
 
114
                   
 
115
    for attr in basic_traits:
 
116
        setattr(newplot, attr, getattr(oldplot, attr))
 
117
 
 
118
    # copy the ranges
 
119
    dst = newplot.range2d
 
120
    src = oldplot.range2d
 
121
    #for attr in ('_low_setting', '_low_value', '_high_setting', '_high_value'):
 
122
    #    setattr(dst, attr, getattr(src, attr))
 
123
    dst._xrange.sources = copy(src._xrange.sources)
 
124
    dst._yrange.sources = copy(src._yrange.sources)
 
125
 
 
126
    newplot.padding = oldplot.padding
 
127
    newplot.bounds = oldplot.bounds[:]
 
128
    newplot.resizable = ""
 
129
    newplot.position = drop_position
 
130
 
 
131
    newplot.datasources = copy(oldplot.datasources)
 
132
 
 
133
    for name, renderers in oldplot.plots.items():
 
134
        newrenderers = []
 
135
        for renderer in renderers:
 
136
            new_r = clone_renderer(renderer)
 
137
            new_r.index_mapper = LinearMapper(range=newplot.index_range)
 
138
            new_r.value_mapper = LinearMapper(range=newplot.value_range)
 
139
            new_r._layout_needed = True
 
140
            new_r.invalidate_draw()
 
141
            new_r.resizable = "hv"
 
142
            newrenderers.append(new_r)
 
143
        newplot.plots[name] = newrenderers
 
144
    #newplot.plots = copy(oldplot.plots)
 
145
 
 
146
    for name, renderers in newplot.plots.items():
 
147
        newplot.add(*renderers)
 
148
 
 
149
    newplot.index_axis.title = oldplot.index_axis.title
 
150
    newplot.index_axis.unified_draw = True
 
151
    newplot.value_axis.title = oldplot.value_axis.title
 
152
    newplot.value_axis.unified_draw = True
 
153
 
 
154
    # Add new tools to the new plot
 
155
    newplot.tools.append(AxisTool(component=newplot, 
 
156
        range_controller=canvas.range_controller))
 
157
 
 
158
    # Add tools to the new plot
 
159
    pan_traits = ["drag_button", "constrain", "constrain_key", "constrain_direction",
 
160
                  "speed"]
 
161
    zoom_traits = ["tool_mode", "always_on", "axis", "enable_wheel", "drag_button",
 
162
                   "wheel_zoom_step", "enter_zoom_key", "exit_zoom_key", "pointer",
 
163
                   "color", "alpha", "border_color", "border_size", "disable_on_complete",
 
164
                   "minimum_screen_delta", "max_zoom_in_factor", "max_zoom_out_factor"]
 
165
    move_traits = ["drag_button", "end_drag_on_leave", "cancel_keys", "capture_mouse",
 
166
                   "modifier_key"]
 
167
 
 
168
    if not MULTITOUCH:
 
169
        for tool in oldplot.tools:
 
170
            if isinstance(tool, PanTool):
 
171
                newtool = tool.clone_traits(pan_traits)
 
172
                newtool.component = newplot
 
173
                break
 
174
        else:
 
175
            newtool = PanTool(newplot)
 
176
        # Reconfigure the pan tool to always use the left mouse, because we will
 
177
        # put plot move on the right mouse button
 
178
        newtool.drag_button = "left"
 
179
        newplot.tools.append(newtool)
 
180
 
 
181
        for tool in oldplot.tools:
 
182
            if isinstance(tool, MoveTool):
 
183
                newtool = tool.clone_traits(move_traits)
 
184
                newtool.component = newplot
 
185
                break
 
186
        else:
 
187
            newtool = MoveTool(newplot, drag_button="right")
 
188
        newplot.tools.append(newtool)
 
189
 
 
190
        for tool in oldplot.tools:
 
191
            if isinstance(tool, SimpleZoom):
 
192
                newtool = tool.clone_traits(zoom_traits)
 
193
                newtool.component = newplot
 
194
                break
 
195
        else:
 
196
            newtool = SimpleZoom(newplot)
 
197
        newplot.tools.append(newtool)
 
198
 
 
199
    else:
 
200
        pz = MPPanZoom(newplot)
 
201
        #pz.pan.constrain = True
 
202
        #pz.pan.constrain_direction = "x"
 
203
        #pz.zoom.mode = "range"
 
204
        #pz.zoom.axis = "index"
 
205
        newplot.tools.append(MPPanZoom(newplot))
 
206
        #newplot.tools.append(MTMoveTool(
 
207
 
 
208
    newplot._layout_needed = True
 
209
 
 
210
    clonetool.dest.add(newplot)
 
211
    newplot.invalidate_draw()
 
212
    newplot.request_redraw()
 
213
    canvas.request_redraw()
 
214
    return
 
215
 
 
216
    
 
217
def make_toolbar(canvas):
 
218
    # Create the toolbar
 
219
    toolbar = PlotCanvasToolbar(bounds=[70, 200], 
 
220
                                position=[50,350],
 
221
                                fill_padding=True,
 
222
                                bgcolor="lightgrey",
 
223
                                padding = 5,
 
224
                                align = "left",
 
225
                                )
 
226
 
 
227
    # Create the scatterplot
 
228
    pd = ArrayPlotData()
 
229
    scatterplot = Plot(pd, padding=15, bgcolor="white", unified_draw=True,
 
230
                       border_visible=True)
 
231
    if not MULTITOUCH:
 
232
        scatterplot.tools.append(PanTool(scatterplot, drag_button="right"))
 
233
        scatterplot.tools.append(SimpleZoom(scatterplot))
 
234
    else:
 
235
        scatterplot.tools.append(MPPanZoom(scatterplot))
 
236
    scatterplot.overlays.append(PlotCloneTool(scatterplot, dest=canvas,
 
237
                                              plot_cloner=clone_plot))
 
238
 
 
239
    # Create the overlay
 
240
    overlay = TransientPlotOverlay(component=toolbar,
 
241
                                   overlay_component=scatterplot,
 
242
                                   bounds=[350,350],
 
243
                                   border_visible=True,
 
244
                                   visible = False,  # initially invisible
 
245
                                   )
 
246
    scatterplot.container = overlay
 
247
    
 
248
    # Create buttons 
 
249
    controller = ButtonController()
 
250
    for name in DATA.keys():
 
251
        plot = do_plot(name, pd)
 
252
        if MULTITOUCH:
 
253
            plot.tools.append(MPPanZoom(plot))
 
254
        else:
 
255
            plot.tools.append(PanTool(plot, drag_button="right", constrain=True,
 
256
                                      constrain_direction="x"))
 
257
            plot.tools.append(SimpleZoom(plot, tool_mode="range", axis="index",
 
258
                                         always_on=False))
 
259
        plot.overlays.append(PlotCloneTool(plot, dest=canvas,
 
260
                                           plot_cloner=clone_plot))
 
261
        plot_overlay = TransientPlotOverlay(component=toolbar,
 
262
                                            overlay_component=plot,
 
263
                                            border_visible=True,
 
264
                                            visible=False,
 
265
                                            )
 
266
        plot.container = plot_overlay
 
267
        button = DataSourceButton(label=name, 
 
268
                                  bounds=[80,46],
 
269
                                  padding = 5,
 
270
                                  button_controller = controller,
 
271
                                  #canvas = canvas,
 
272
                                  plot_overlay = plot_overlay,
 
273
                                  plotname = name)
 
274
        toolbar.add(button)
 
275
        canvas.overlays.append(plot_overlay)
 
276
    controller.plot = scatterplot
 
277
    controller.plot_overlay = overlay
 
278
    canvas.overlays.append(overlay)
 
279
 
 
280
    return toolbar
 
281
 
 
282
 
 
283
class PlotFrame(DemoFrame):
 
284
 
 
285
    def _create_viewport(self):
 
286
        # Create a container and add our plots
 
287
        canvas = PlotCanvas()
 
288
        canvas.range_controller = RangeController(cavas = canvas)
 
289
 
 
290
        toolbar = make_toolbar(canvas)
 
291
        toolbar.component = canvas
 
292
        canvas.overlays.append(toolbar)
 
293
 
 
294
        viewport = Viewport(component=canvas)
 
295
        if MULTITOUCH:
 
296
            viewport.tools.append(MPViewportPanTool(viewport))
 
297
        else:
 
298
            viewport.tools.append(ViewportPanTool(viewport, drag_button="right"))
 
299
        return viewport
 
300
 
 
301
    def _create_window_mt(self):
 
302
        viewport = self._create_viewport()
 
303
 
 
304
        from enactable.configuration import arg_parser, get_global_config
 
305
        from enactable.enable.enable_blob_listener import BlobWindow
 
306
        from enactable.enable.blobprovider import NetworkBlobProvider
 
307
        parser = arg_parser()
 
308
        args = parser.parse_args()
 
309
        cfg = get_global_config()
 
310
        tconf = cfg.tconf
 
311
        tconf.from_arguments(args)
 
312
 
 
313
        provider = NetworkBlobProvider(host=tconf.Server.host, port=tconf.Server.port)
 
314
        provider.start()
 
315
        return BlobWindow(self, -1, component=viewport, blob_provider=provider)
 
316
    
 
317
    def _create_window_simple(self):
 
318
        viewport = self._create_viewport()
 
319
        return Window(self, -1, component=viewport)
 
320
 
 
321
    def _create_window(self):
 
322
        if MULTITOUCH:
 
323
            return self._create_window_mt()
 
324
        else:
 
325
            return self._create_window_simple()
 
326
        
 
327
if __name__ == "__main__":
 
328
    demo_main(PlotFrame, size=(1000,700), title="PlotCanvas")
 
329
 
 
330
# EOF