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

« back to all changes in this revision

Viewing changes to examples/demo/advanced/data_stream.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
 
Sample visualization of simulated live data stream
3
 
 
4
 
Shows how Chaco and Traits can be used to easily build a data
5
 
acquisition and visualization system.
6
 
 
7
 
Two frames are opened: one has the plot and allows configuration of
8
 
various plot properties, and one which simulates controls for the hardware
9
 
device from which the data is being acquired; in this case, it is a mockup
10
 
random number generator whose mean and standard deviation can be controlled
11
 
by the user.
12
 
"""
13
 
 
14
 
# Major library imports
15
 
import random
16
 
import wx
17
 
from numpy import arange, array, hstack, random
18
 
 
19
 
# Enthought imports
20
 
from traits.api import Array, Bool, Callable, Enum, Float, HasTraits, \
21
 
                                 Instance, Int, Trait
22
 
from traitsui.api import Group, HGroup, Item, View, spring, Handler
23
 
from pyface.timer.api import Timer
24
 
 
25
 
# Chaco imports
26
 
from chaco.chaco_plot_editor import ChacoPlotItem
27
 
 
28
 
 
29
 
class Viewer(HasTraits):
30
 
    """ This class just contains the two data arrays that will be updated
31
 
    by the Controller.  The visualization/editor for this class is a
32
 
    Chaco plot.
33
 
    """
34
 
 
35
 
    index = Array
36
 
 
37
 
    data = Array
38
 
 
39
 
    plot_type = Enum("line", "scatter")
40
 
 
41
 
    # This "view" attribute defines how an instance of this class will
42
 
    # be displayed when .edit_traits() is called on it.  (See MyApp.OnInit()
43
 
    # below.)
44
 
    view = View(ChacoPlotItem("index", "data",
45
 
                               type_trait="plot_type",
46
 
                               resizable=True,
47
 
                               x_label="Time",
48
 
                               y_label="Signal",
49
 
                               color="blue",
50
 
                               bgcolor="white",
51
 
                               border_visible=True,
52
 
                               border_width=1,
53
 
                               padding_bg_color="lightgray",
54
 
                               width=800,
55
 
                               height=380,
56
 
                               marker_size=2,
57
 
                               show_label=False),
58
 
                HGroup(spring, Item("plot_type", style='custom'), spring),
59
 
                resizable = True,
60
 
                buttons = ["OK"],
61
 
                width=800, height=500)
62
 
 
63
 
 
64
 
class Controller(HasTraits):
65
 
 
66
 
    # A reference to the plot viewer object
67
 
    viewer = Instance(Viewer)
68
 
 
69
 
    # Some parameters controller the random signal that will be generated
70
 
    distribution_type = Enum("normal", "lognormal")
71
 
    mean = Float(0.0)
72
 
    stddev = Float(1.0)
73
 
 
74
 
    # The max number of data points to accumulate and show in the plot
75
 
    max_num_points = Int(100)
76
 
 
77
 
    # The number of data points we have received; we need to keep track of
78
 
    # this in order to generate the correct x axis data series.
79
 
    num_ticks = Int(0)
80
 
 
81
 
    # private reference to the random number generator.  this syntax
82
 
    # just means that self._generator should be initialized to
83
 
    # random.normal, which is a random number function, and in the future
84
 
    # it can be set to any callable object.
85
 
    _generator = Trait(random.normal, Callable)
86
 
 
87
 
    view = View(Group('distribution_type',
88
 
                      'mean',
89
 
                      'stddev',
90
 
                      'max_num_points',
91
 
                      orientation="vertical"),
92
 
                      buttons=["OK", "Cancel"])
93
 
 
94
 
    def timer_tick(self, *args):
95
 
        """ Callback function that should get called based on a wx timer
96
 
        tick.  This will generate a new random datapoint and set it on
97
 
        the .data array of our viewer object.
98
 
        """
99
 
        # Generate a new number and increment the tick count
100
 
        new_val = self._generator(self.mean, self.stddev)
101
 
        self.num_ticks += 1
102
 
 
103
 
        # grab the existing data, truncate it, and append the new point.
104
 
        # This isn't the most efficient thing in the world but it works.
105
 
        cur_data = self.viewer.data
106
 
        new_data = hstack((cur_data[-self.max_num_points+1:], [new_val]))
107
 
        new_index = arange(self.num_ticks - len(new_data) + 1, self.num_ticks+0.01)
108
 
 
109
 
        self.viewer.index = new_index
110
 
        self.viewer.data = new_data
111
 
        return
112
 
 
113
 
    def _distribution_type_changed(self):
114
 
        # This listens for a change in the type of distribution to use.
115
 
        if self.distribution_type == "normal":
116
 
            self._generator = random.normal
117
 
        else:
118
 
            self._generator = random.lognormal
119
 
 
120
 
#===============================================================================
121
 
# # Demo class that is used by the demo.py application.
122
 
#===============================================================================
123
 
# NOTE: The Demo class is being created for the purpose of running this
124
 
# example using a TraitsDemo-like app (see examples/demo/demo.py in Traits3).
125
 
# The demo.py file looks for a 'demo' or 'popup' or 'modal popup' keyword
126
 
# when it executes this file, and displays a view for it.
127
 
 
128
 
class DemoHandler(Handler):
129
 
 
130
 
    def closed(self, info, is_ok):
131
 
        """ Handles a dialog-based user interface being closed by the user.
132
 
        Overridden here to stop the timer once the window is destroyed.
133
 
        """
134
 
 
135
 
        info.object.timer.Stop()
136
 
        return
137
 
 
138
 
class Demo(HasTraits):
139
 
    controller = Instance(Controller)
140
 
    viewer = Instance(Viewer, ())
141
 
    timer = Instance(Timer)
142
 
    view = View(Item('controller', style='custom', show_label=False),
143
 
                Item('viewer', style='custom', show_label=False),
144
 
                handler = DemoHandler,
145
 
                resizable=True)
146
 
 
147
 
    def edit_traits(self, *args, **kws):
148
 
        # Start up the timer! We should do this only when the demo actually
149
 
        # starts and not when the demo object is created.
150
 
        self.timer=Timer(100, self.controller.timer_tick)
151
 
        return super(Demo, self).edit_traits(*args, **kws)
152
 
 
153
 
    def configure_traits(self, *args, **kws):
154
 
        # Start up the timer! We should do this only when the demo actually
155
 
        # starts and not when the demo object is created.
156
 
        self.timer=Timer(100, self.controller.timer_tick)
157
 
        return super(Demo, self).configure_traits(*args, **kws)
158
 
 
159
 
    def _controller_default(self):
160
 
        return Controller(viewer=self.viewer)
161
 
 
162
 
popup=Demo()
163
 
 
164
 
# wxApp used when this file is run from the command line.
165
 
 
166
 
class MyApp(wx.PySimpleApp):
167
 
 
168
 
    def OnInit(self, *args, **kw):
169
 
        viewer = Viewer()
170
 
        controller = Controller(viewer = viewer)
171
 
 
172
 
        # Pop up the windows for the two objects
173
 
        viewer.edit_traits()
174
 
        controller.edit_traits()
175
 
 
176
 
        # Set up the timer and start it up
177
 
        self.setup_timer(controller)
178
 
        return True
179
 
 
180
 
 
181
 
    def setup_timer(self, controller):
182
 
        # Create a new WX timer
183
 
        timerId = wx.NewId()
184
 
        self.timer = wx.Timer(self, timerId)
185
 
 
186
 
        # Register a callback with the timer event
187
 
        self.Bind(wx.EVT_TIMER, controller.timer_tick, id=timerId)
188
 
 
189
 
        # Start up the timer!  We have to tell it how many milliseconds
190
 
        # to wait between timer events.  For now we will hardcode it
191
 
        # to be 100 ms, so we get 10 points per second.
192
 
        self.timer.Start(100.0, wx.TIMER_CONTINUOUS)
193
 
        return
194
 
 
195
 
 
196
 
# This is called when this example is to be run in a standalone mode.
197
 
if __name__ == "__main__":
198
 
    app = MyApp()
199
 
    app.MainLoop()
200
 
 
201
 
# EOF