3
The main app for the PlotCanvas application
9
# Major library imports
11
from numpy import arange, fabs, linspace, pi, sin
12
from numpy import random
13
from scipy.special import jn
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, \
25
from enthought.chaco.api import AbstractOverlay, ArrayPlotData, \
26
Plot, jet, ScatterPlot, LinePlot, LinearMapper
27
from enthought.chaco.tools.api import PanTool, SimpleZoom , LegendTool
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
42
from mptools import MPPanTool, MPDragZoom, MPLegendTool, \
43
MPPanZoom, MPRangeSelection
44
#AxisTool = MPAxisTool
45
PlotCloneTool = MPPlotCloneTool
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),
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)
68
def do_plot(name, pd):
71
pd.set_data(xname, range(len(DATA[name])))
72
pd.set_data(yname, DATA[name])
74
plot = Plot(pd, padding = 30,
76
border_visible = True,
78
plot.x_axis.visible = False
80
plot.plot((xname, yname), name=name, type="line", color="blue",)
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",
91
scatter_traits = ["custom_symbol", "marker", "marker_size", "selection_marker",
92
"selection_marker_size", "selection_line_width",
95
line_traits = ["selected_color", "selected_line_style", "metadata_name",
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)
103
def clone_plot(clonetool, drop_position):
104
# A little sketchy...
105
canvas = clonetool.component.container.component.component
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",
115
for attr in basic_traits:
116
setattr(newplot, attr, getattr(oldplot, attr))
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)
126
newplot.padding = oldplot.padding
127
newplot.bounds = oldplot.bounds[:]
128
newplot.resizable = ""
129
newplot.position = drop_position
131
newplot.datasources = copy(oldplot.datasources)
133
for name, renderers in oldplot.plots.items():
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)
146
for name, renderers in newplot.plots.items():
147
newplot.add(*renderers)
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
154
# Add new tools to the new plot
155
newplot.tools.append(AxisTool(component=newplot,
156
range_controller=canvas.range_controller))
158
# Add tools to the new plot
159
pan_traits = ["drag_button", "constrain", "constrain_key", "constrain_direction",
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",
169
for tool in oldplot.tools:
170
if isinstance(tool, PanTool):
171
newtool = tool.clone_traits(pan_traits)
172
newtool.component = newplot
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)
181
for tool in oldplot.tools:
182
if isinstance(tool, MoveTool):
183
newtool = tool.clone_traits(move_traits)
184
newtool.component = newplot
187
newtool = MoveTool(newplot, drag_button="right")
188
newplot.tools.append(newtool)
190
for tool in oldplot.tools:
191
if isinstance(tool, SimpleZoom):
192
newtool = tool.clone_traits(zoom_traits)
193
newtool.component = newplot
196
newtool = SimpleZoom(newplot)
197
newplot.tools.append(newtool)
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(
208
newplot._layout_needed = True
210
clonetool.dest.add(newplot)
211
newplot.invalidate_draw()
212
newplot.request_redraw()
213
canvas.request_redraw()
217
def make_toolbar(canvas):
219
toolbar = PlotCanvasToolbar(bounds=[70, 200],
227
# Create the scatterplot
229
scatterplot = Plot(pd, padding=15, bgcolor="white", unified_draw=True,
232
scatterplot.tools.append(PanTool(scatterplot, drag_button="right"))
233
scatterplot.tools.append(SimpleZoom(scatterplot))
235
scatterplot.tools.append(MPPanZoom(scatterplot))
236
scatterplot.overlays.append(PlotCloneTool(scatterplot, dest=canvas,
237
plot_cloner=clone_plot))
240
overlay = TransientPlotOverlay(component=toolbar,
241
overlay_component=scatterplot,
244
visible = False, # initially invisible
246
scatterplot.container = overlay
249
controller = ButtonController()
250
for name in DATA.keys():
251
plot = do_plot(name, pd)
253
plot.tools.append(MPPanZoom(plot))
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",
259
plot.overlays.append(PlotCloneTool(plot, dest=canvas,
260
plot_cloner=clone_plot))
261
plot_overlay = TransientPlotOverlay(component=toolbar,
262
overlay_component=plot,
266
plot.container = plot_overlay
267
button = DataSourceButton(label=name,
270
button_controller = controller,
272
plot_overlay = plot_overlay,
275
canvas.overlays.append(plot_overlay)
276
controller.plot = scatterplot
277
controller.plot_overlay = overlay
278
canvas.overlays.append(overlay)
283
class PlotFrame(DemoFrame):
285
def _create_viewport(self):
286
# Create a container and add our plots
287
canvas = PlotCanvas()
288
canvas.range_controller = RangeController(cavas = canvas)
290
toolbar = make_toolbar(canvas)
291
toolbar.component = canvas
292
canvas.overlays.append(toolbar)
294
viewport = Viewport(component=canvas)
296
viewport.tools.append(MPViewportPanTool(viewport))
298
viewport.tools.append(ViewportPanTool(viewport, drag_button="right"))
301
def _create_window_mt(self):
302
viewport = self._create_viewport()
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()
311
tconf.from_arguments(args)
313
provider = NetworkBlobProvider(host=tconf.Server.host, port=tconf.Server.port)
315
return BlobWindow(self, -1, component=viewport, blob_provider=provider)
317
def _create_window_simple(self):
318
viewport = self._create_viewport()
319
return Window(self, -1, component=viewport)
321
def _create_window(self):
323
return self._create_window_mt()
325
return self._create_window_simple()
327
if __name__ == "__main__":
328
demo_main(PlotFrame, size=(1000,700), title="PlotCanvas")