Subversion Repositories Projects

Rev

Rev 701 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 701 Rev 721
1
#!/usr/bin/env python
1
#!/usr/bin/env python
2
# -*- coding: iso-8859-15 -*-
2
# -*- coding: iso-8859-15 -*-
3
# generated by wxGlade 0.6.3 on Thu Sep 24 15:46:36 2009
3
# generated by wxGlade 0.6.3 on Thu Sep 24 15:46:36 2009
4
 
4
 
5
#
5
#
6
# Mikrokopter VibrationTest  Rev: $Rev: 701 $
6
# Mikrokopter VibrationTest  Rev: $Rev: 721 $
7
#
7
#
8
# Author: Frederic Goddeeris   (frederic@rc-flight.be) 
8
# Author: Frederic Goddeeris   (frederic@rc-flight.be) 
9
#
9
#
10
 
10
 
11
import sys
11
import sys
12
import os
12
import os
13
import time
13
import time
14
import thread
14
import thread
15
import ConfigParser
15
import ConfigParser
16
import math
16
import math
17
 
17
 
18
import wx
18
import wx
19
import wx.lib
19
import wx.lib
20
import wx.lib.plot
20
import wx.lib.plot
21
import wx.lib.newevent
21
import wx.lib.newevent
22
import wx.lib.agw.speedmeter as speedmeter
22
import wx.lib.agw.speedmeter as speedmeter
23
 
23
 
24
import MkProtocol
24
import MkProtocol
25
 
25
 
26
 
26
 
27
 
27
 
28
CHANNEL_NAMES = ["GyroYaw", "GyroRoll", "GyroNick", "Pressure", "Batt", "AccTop", "AccRoll", "AccNick"]
28
CHANNEL_NAMES = ["GyroYaw", "GyroRoll", "GyroNick", "Pressure", "Batt", "AccTop", "AccRoll", "AccNick"]
29
MOTOR_MAX = 16
29
MOTOR_MAX = 16
30
 
30
 
31
FS = 11111
31
FS = 11111
32
pi = 3.14
32
pi = 3.14
33
COLOR_YELLOW = wx.Colour(255, 240, 0)
33
COLOR_YELLOW = wx.Colour(255, 240, 0)
34
COLOR_BACKGROUND = wx.Colour(0x80, 0x80, 0x80)
34
COLOR_BACKGROUND = wx.Colour(0x80, 0x80, 0x80)
35
 
35
 
36
COLORS = [wx.RED, wx.GREEN, wx.BLUE, COLOR_YELLOW, COLOR_BACKGROUND, wx.BLACK,]*2
36
COLORS = [wx.RED, wx.GREEN, wx.BLUE, COLOR_YELLOW, COLOR_BACKGROUND, wx.BLACK,]*2
37
 
37
 
38
rootPath = ""
38
rootPath = ""
39
 
39
 
40
# Needs Numeric or numarray or NumPy
40
# Needs Numeric or numarray or NumPy
41
try:
41
try:
42
    import numpy.oldnumeric as _Numeric
42
    import numpy.oldnumeric as _Numeric
43
except:
43
except:
44
    try:
44
    try:
45
        import numarray as _Numeric  #if numarray is used it is renamed Numeric
45
        import numarray as _Numeric  #if numarray is used it is renamed Numeric
46
    except:
46
    except:
47
        try:
47
        try:
48
            import Numeric as _Numeric
48
            import Numeric as _Numeric
49
        except:
49
        except:
50
            msg= """
50
            msg= """
51
            This module requires the Numeric/numarray or NumPy module,
51
            This module requires the Numeric/numarray or NumPy module,
52
            which could not be imported.  It probably is not installed
52
            which could not be imported.  It probably is not installed
53
            (it's not part of the standard Python distribution). See the
53
            (it's not part of the standard Python distribution). See the
54
            Numeric Python site (http://numpy.scipy.org) for information on
54
            Numeric Python site (http://numpy.scipy.org) for information on
55
            downloading source or binaries."""
55
            downloading source or binaries."""
56
            raise ImportError, "Numeric,numarray or NumPy not found. \n" + msg
56
            raise ImportError, "Numeric,numarray or NumPy not found. \n" + msg
57
 
57
 
58
# begin wxGlade: extracode
58
# begin wxGlade: extracode
59
# end wxGlade
59
# end wxGlade
60
 
60
 
61
 
61
 
62
# This creates a new Event class and a EVT binder function
62
# This creates a new Event class and a EVT binder function
63
(MeasStatusUpdateEvent, EVT_MEAS_STATUS_UPDATE) = wx.lib.newevent.NewEvent()  
63
(MeasStatusUpdateEvent, EVT_MEAS_STATUS_UPDATE) = wx.lib.newevent.NewEvent()  
64
(MeasDataEvent, EVT_MEAS_DATA) = wx.lib.newevent.NewEvent()  
64
(MeasDataEvent, EVT_MEAS_DATA) = wx.lib.newevent.NewEvent()  
65
 
65
 
66
class MeasureDialog(wx.Dialog):
66
class MeasureDialog(wx.Dialog):
67
    def __init__(self, *args, **kwds):
67
    def __init__(self, *args, **kwds):
68
        # begin wxGlade: MeasureDialog.__init__
68
        # begin wxGlade: MeasureDialog.__init__
69
        kwds["style"] = wx.CAPTION|wx.RESIZE_BORDER|wx.THICK_FRAME
69
        kwds["style"] = wx.CAPTION|wx.RESIZE_BORDER|wx.THICK_FRAME
70
        wx.Dialog.__init__(self, *args, **kwds)
70
        wx.Dialog.__init__(self, *args, **kwds)
71
        self.text_ctrl_1 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
71
        self.text_ctrl_1 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
72
        self.button = wx.Button(self, -1, "STOP")
72
        self.button = wx.Button(self, -1, "STOP")
73
        self.voltageCtrl = speedmeter.SpeedMeter(self, extrastyle=speedmeter.SM_DRAW_HAND | speedmeter.SM_DRAW_PARTIAL_SECTORS |  speedmeter.SM_DRAW_MIDDLE_ICON )
73
        self.voltageCtrl = speedmeter.SpeedMeter(self, extrastyle=speedmeter.SM_DRAW_HAND | speedmeter.SM_DRAW_PARTIAL_SECTORS |  speedmeter.SM_DRAW_MIDDLE_ICON )
74
        self.speedCtrl = speedmeter.SpeedMeter(self, extrastyle=speedmeter.SM_DRAW_HAND | speedmeter.SM_DRAW_PARTIAL_SECTORS | speedmeter.SM_DRAW_MIDDLE_TEXT | speedmeter.SM_DRAW_SECONDARY_TICKS)
74
        self.speedCtrl = speedmeter.SpeedMeter(self, extrastyle=speedmeter.SM_DRAW_HAND | speedmeter.SM_DRAW_PARTIAL_SECTORS | speedmeter.SM_DRAW_MIDDLE_TEXT | speedmeter.SM_DRAW_SECONDARY_TICKS)
75
 
75
 
76
        self.__set_properties()
76
        self.__set_properties()
77
        self.__do_layout()
77
        self.__do_layout()
78
 
78
 
79
        self.Bind(wx.EVT_BUTTON, self.onButton, self.button)
79
        self.Bind(wx.EVT_BUTTON, self.onButton, self.button)
80
        # end wxGlade
80
        # end wxGlade
81
       
81
       
82
        self.button.SetFocus()
82
        self.button.SetFocus()
83
       
83
       
84
        self.running = True
84
        self.running = True
85
        self.Bind(EVT_MEAS_STATUS_UPDATE, self.OnUpdate)
85
        self.Bind(EVT_MEAS_STATUS_UPDATE, self.OnUpdate)
86
        self.Bind(EVT_MEAS_DATA, self.OnData)
86
        self.Bind(EVT_MEAS_DATA, self.OnData)
87
        # The first argument that is passed to the constructor is the parent
87
        # The first argument that is passed to the constructor is the parent
88
        self.app = args[0].app
88
        self.app = args[0].app
89
        self.error = False
89
        self.error = False
90
        self.firstVoltage = True
90
        self.firstVoltage = True
91
 
91
 
92
 
92
 
93
    def __set_properties(self):
93
    def __set_properties(self):
94
        # begin wxGlade: MeasureDialog.__set_properties
94
        # begin wxGlade: MeasureDialog.__set_properties
95
        self.SetTitle("Measuring Status")
95
        self.SetTitle("Measuring Status")
96
        self.text_ctrl_1.SetMinSize((400,300))
96
        self.text_ctrl_1.SetMinSize((400,300))
97
        self.voltageCtrl.SetMinSize((50,-1))
97
        self.voltageCtrl.SetMinSize((50,-1))
98
        self.speedCtrl.SetMinSize((50,-1))
98
        self.speedCtrl.SetMinSize((50,-1))
99
        # end wxGlade
99
        # end wxGlade
100
       
100
       
101
        # Configure Voltage Ctrl
101
        # Configure Voltage Ctrl
102
        self.voltageCtrl.SetAngleRange(0,pi)
102
        self.voltageCtrl.SetAngleRange(0,pi)
103
        intervals = range(0, 5)
103
        intervals = range(0, 5)
104
        self.voltageCtrl.SetIntervals(intervals)
104
        self.voltageCtrl.SetIntervals(intervals)
105
        colours = [wx.RED, wx.GREEN, wx.GREEN, COLOR_YELLOW]
105
        colours = [wx.RED, wx.GREEN, wx.GREEN, COLOR_YELLOW]
106
        self.voltageCtrl.SetIntervalColours(colours)
106
        self.voltageCtrl.SetIntervalColours(colours)
107
        ticks = ["", "", "", "", ""]
107
        ticks = ["", "", "", "", ""]
108
        self.voltageCtrl.SetTicks(ticks)
108
        self.voltageCtrl.SetTicks(ticks)
109
        self.voltageCtrl.SetTicksColour(wx.WHITE)
109
        self.voltageCtrl.SetTicksColour(wx.WHITE)
110
        self.voltageCtrl.SetHandColour(COLOR_YELLOW)
110
        self.voltageCtrl.SetHandColour(COLOR_YELLOW)
111
 
111
 
112
        icon = wx.Icon("%s/Resources/fuel.ico" % rootPath, wx.BITMAP_TYPE_ICO)
112
        icon = wx.Icon("%s/Resources/fuel.ico" % rootPath, wx.BITMAP_TYPE_ICO)
113
        icon.SetWidth(24)
113
        icon.SetWidth(24)
114
        icon.SetHeight(24)
114
        icon.SetHeight(24)
115
 
115
 
116
        self.voltageCtrl.SetMiddleIcon(icon)        
116
        self.voltageCtrl.SetMiddleIcon(icon)        
117
        self.voltageCtrl.SetSpeedBackground(COLOR_BACKGROUND)        
117
        self.voltageCtrl.SetSpeedBackground(COLOR_BACKGROUND)        
118
        self.voltageCtrl.SetArcColour(wx.WHITE)
118
        self.voltageCtrl.SetArcColour(wx.WHITE)
119
        self.voltageCtrl.SetSpeedValue(2)
119
        self.voltageCtrl.SetSpeedValue(2)
120
 
120
 
121
        # Configure Speed Ctr;
121
        # Configure Speed Ctr;
122
        self.speedCtrl.SetAngleRange(0,pi)        
122
        self.speedCtrl.SetAngleRange(0,pi)        
123
        intervals = range(0, 261, 20)
123
        intervals = range(0, 261, 20)
124
        self.speedCtrl.SetIntervals(intervals)
124
        self.speedCtrl.SetIntervals(intervals)
125
 
125
 
126
        colours = [COLOR_BACKGROUND]*(len(intervals)-1)
126
        colours = [COLOR_BACKGROUND]*(len(intervals)-1)
127
        for i in range(5,10):
127
        for i in range(5,10):
128
          colours[i] = wx.GREEN
128
          colours[i] = wx.GREEN
129
        self.speedCtrl.SetIntervalColours(colours)
129
        self.speedCtrl.SetIntervalColours(colours)
130
        ticks = [str(interval) for interval in intervals]
130
        ticks = [str(interval) for interval in intervals]
131
        self.speedCtrl.SetTicks(ticks)
131
        self.speedCtrl.SetTicks(ticks)
132
        self.speedCtrl.SetTicksColour(wx.WHITE)
132
        self.speedCtrl.SetTicksColour(wx.WHITE)
133
        self.speedCtrl.SetNumberOfSecondaryTicks(1)
133
        self.speedCtrl.SetNumberOfSecondaryTicks(1)
134
        self.speedCtrl.SetTicksFont(wx.Font(7, wx.SWISS, wx.NORMAL, wx.NORMAL))
134
        self.speedCtrl.SetTicksFont(wx.Font(7, wx.SWISS, wx.NORMAL, wx.NORMAL))
135
        self.speedCtrl.SetMiddleText("Speed")
135
        self.speedCtrl.SetMiddleText("Speed")
136
        self.speedCtrl.SetMiddleTextColour(wx.WHITE)
136
        self.speedCtrl.SetMiddleTextColour(wx.WHITE)
137
        self.speedCtrl.SetMiddleTextFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.BOLD))
137
        self.speedCtrl.SetMiddleTextFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.BOLD))
138
        self.speedCtrl.SetHandColour(COLOR_YELLOW)
138
        self.speedCtrl.SetHandColour(COLOR_YELLOW)
139
        self.speedCtrl.SetSpeedBackground(COLOR_BACKGROUND)  
139
        self.speedCtrl.SetSpeedBackground(COLOR_BACKGROUND)  
140
        self.speedCtrl.SetArcColour(wx.WHITE)        
140
        self.speedCtrl.SetArcColour(wx.WHITE)        
141
        self.speedCtrl.SetSpeedValue(0)
141
        self.speedCtrl.SetSpeedValue(0)
142
 
142
 
143
 
143
 
144
    def __do_layout(self):
144
    def __do_layout(self):
145
        # begin wxGlade: MeasureDialog.__do_layout
145
        # begin wxGlade: MeasureDialog.__do_layout
146
        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
146
        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
147
        sizer_4 = wx.BoxSizer(wx.VERTICAL)
147
        sizer_4 = wx.BoxSizer(wx.VERTICAL)
148
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
148
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
149
        sizer_1.Add((20, 20), 0, 0, 0)
149
        sizer_1.Add((20, 20), 0, 0, 0)
150
        sizer_2.Add((20, 20), 0, 0, 0)
150
        sizer_2.Add((20, 20), 0, 0, 0)
151
        sizer_2.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
151
        sizer_2.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
152
        sizer_2.Add((20, 20), 0, 0, 0)
152
        sizer_2.Add((20, 20), 0, 0, 0)
153
        sizer_2.Add(self.button, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
153
        sizer_2.Add(self.button, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
154
        sizer_2.Add((20, 20), 0, 0, 0)
154
        sizer_2.Add((20, 20), 0, 0, 0)
155
        sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
155
        sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
156
        sizer_1.Add((20, 20), 0, 0, 0)
156
        sizer_1.Add((20, 20), 0, 0, 0)
157
        sizer_4.Add(self.voltageCtrl, 1, wx.EXPAND, 0)
157
        sizer_4.Add(self.voltageCtrl, 1, wx.EXPAND, 0)
158
        sizer_4.Add(self.speedCtrl, 1, wx.EXPAND, 0)
158
        sizer_4.Add(self.speedCtrl, 1, wx.EXPAND, 0)
159
        sizer_1.Add(sizer_4, 1, wx.EXPAND, 0)
159
        sizer_1.Add(sizer_4, 1, wx.EXPAND, 0)
160
        sizer_1.Add((20, 20), 0, 0, 0)
160
        sizer_1.Add((20, 20), 0, 0, 0)
161
        self.SetSizer(sizer_1)
161
        self.SetSizer(sizer_1)
162
        sizer_1.Fit(self)
162
        sizer_1.Fit(self)
163
        self.Layout()
163
        self.Layout()
164
        # end wxGlade
164
        # end wxGlade
165
       
165
       
166
    def OnData(self, evt):
166
    def OnData(self, evt):
167
        print "Received Data"
167
        print "Received Data"
168
        self.app.AddTest2(evt.vibTest)
168
        self.app.AddTest2(evt.vibTest)
169
       
169
       
170
    def OnUpdate(self, evt):
170
    def OnUpdate(self, evt):
171
        print "Status update"
171
        print "Status update"
172
        self.running = evt.running
172
        self.running = evt.running
173
        if evt.error:
173
        if evt.error:
174
            self.error = True;
174
            self.error = True;
175
            self.text_ctrl_1.WriteText("ERROR: ")
175
            self.text_ctrl_1.WriteText("ERROR: ")
176
            self.text_ctrl_1.SetBackgroundColour("Red")  
176
            self.text_ctrl_1.SetBackgroundColour("Red")  
177
        self.text_ctrl_1.WriteText("%s\n"%evt.msg)
177
        self.text_ctrl_1.WriteText("%s\n"%evt.msg)
178
        if (not self.running):
178
        if (not self.running):
179
            if (not self.error):
179
            if (not self.error):
180
                self.text_ctrl_1.SetBackgroundColour("Green")
180
                self.text_ctrl_1.SetBackgroundColour("Green")
181
                self.text_ctrl_1.write(" ") # so that the background is redrawn
181
                self.text_ctrl_1.write(" ") # so that the background is redrawn
182
            self.button.SetLabel("Close")
182
            self.button.SetLabel("Close")
183
           
183
           
184
        if evt.speed != None:
184
        if evt.speed != None:
185
            self.speedCtrl.SetSpeedValue(evt.speed)
185
            self.speedCtrl.SetSpeedValue(evt.speed)
186
           
186
           
187
        if evt.voltage != None:
187
        if evt.voltage != None:
188
            vmin,vmax,v = evt.voltage
188
            vmin,vmax,v = evt.voltage
189
            if self.firstVoltage:
189
            if self.firstVoltage:
190
                ticks = ["", "%.1f V"%vmin, "", "%.1f V"%vmax, ""]
190
                ticks = ["", "%.1f V"%vmin, "", "%.1f V"%vmax, ""]
191
                self.voltageCtrl.SetTicks(ticks)
191
                self.voltageCtrl.SetTicks(ticks)
192
                self.firstVoltage = False
192
                self.firstVoltage = False
193
            i = (v-vmin)/(vmax-vmin)  # 0..1
193
            i = (v-vmin)/(vmax-vmin)  # 0..1
194
            i *= 2
194
            i *= 2
195
            i = i+1
195
            i = i+1
196
            i = min(max(i,0),4)
196
            i = min(max(i,0),4)
197
            self.voltageCtrl.SetSpeedValue(i)
197
            self.voltageCtrl.SetSpeedValue(i)
198
 
198
 
199
           
199
           
200
       
200
       
201
    def onButton(self, event): # wxGlade: MeasureDialog.<event_handler>
201
    def onButton(self, event): # wxGlade: MeasureDialog.<event_handler>
202
        if (not self.running):
202
        if (not self.running):
203
            self.Destroy()
203
            self.Destroy()
204
        else:
204
        else:
205
            self.app.cancelMeasurement()
205
            self.app.cancelMeasurement()
206
 
206
 
207
# end of class MeasureDialog
207
# end of class MeasureDialog
208
 
208
 
209
 
209
 
210
class SettingsDialog(wx.Dialog):
210
class SettingsDialog(wx.Dialog):
211
    def __init__(self, *args, **kwds):
211
    def __init__(self, *args, **kwds):
212
        # begin wxGlade: SettingsDialog.__init__
212
        # begin wxGlade: SettingsDialog.__init__
213
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
213
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
214
        wx.Dialog.__init__(self, *args, **kwds)
214
        wx.Dialog.__init__(self, *args, **kwds)
215
        self.button_5 = wx.Button(self, wx.ID_CANCEL, "")
215
        self.button_5 = wx.Button(self, wx.ID_CANCEL, "")
216
        self.button_6 = wx.Button(self, wx.ID_OK, "")
216
        self.button_6 = wx.Button(self, wx.ID_OK, "")
217
 
217
 
218
        self.__set_properties()
218
        self.__set_properties()
219
        self.__do_layout()
219
        self.__do_layout()
220
 
220
 
221
        self.Bind(wx.EVT_BUTTON, self.onOK, self.button_6)
221
        self.Bind(wx.EVT_BUTTON, self.onOK, self.button_6)
222
        # end wxGlade
222
        # end wxGlade
223
 
223
 
224
        # The first argument that is passed to the constructor is the parent
224
        # The first argument that is passed to the constructor is the parent
225
        self.settings = args[0].app.settings
225
        self.settings = args[0].app.settings
226
        # Add text-boxes for all settings
226
        # Add text-boxes for all settings
227
        self.tb = []
227
        self.tb = []
228
        self.grid_sizer_2.SetRows(len(self.settings))
228
        self.grid_sizer_2.SetRows(len(self.settings))
229
        for setting in self.settings.iteritems():
229
        for setting in self.settings.iteritems():
230
            lb = wx.StaticText(self, -1, setting[1].descr, style=wx.ALIGN_RIGHT)
230
            lb = wx.StaticText(self, -1, setting[1].descr, style=wx.ALIGN_RIGHT)
231
            tb = wx.TextCtrl(self, -1, str(setting[1].value))
231
            tb = wx.TextCtrl(self, -1, str(setting[1].value))
232
            self.grid_sizer_2.Add(lb, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
232
            self.grid_sizer_2.Add(lb, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
233
            self.grid_sizer_2.Add(tb, 0, 0, 0)
233
            self.grid_sizer_2.Add(tb, 0, 0, 0)
234
            self.tb.append(tb)
234
            self.tb.append(tb)
235
        self.sizer_5.Fit(self)
235
        self.sizer_5.Fit(self)
236
        self.Layout()
236
        self.Layout()
237
 
237
 
238
    def __set_properties(self):
238
    def __set_properties(self):
239
        # begin wxGlade: SettingsDialog.__set_properties
239
        # begin wxGlade: SettingsDialog.__set_properties
240
        self.SetTitle("Settings")
240
        self.SetTitle("Settings")
241
        # end wxGlade
241
        # end wxGlade
242
 
242
 
243
    def __do_layout(self):
243
    def __do_layout(self):
244
        # begin wxGlade: SettingsDialog.__do_layout
244
        # begin wxGlade: SettingsDialog.__do_layout
245
        sizer_5 = wx.BoxSizer(wx.VERTICAL)
245
        sizer_5 = wx.BoxSizer(wx.VERTICAL)
246
        grid_sizer_3 = wx.GridSizer(1, 2, 0, 0)
246
        grid_sizer_3 = wx.GridSizer(1, 2, 0, 0)
247
        sizer_6 = wx.BoxSizer(wx.HORIZONTAL)
247
        sizer_6 = wx.BoxSizer(wx.HORIZONTAL)
248
        grid_sizer_2 = wx.GridSizer(1, 2, 4, 4)
248
        grid_sizer_2 = wx.GridSizer(1, 2, 4, 4)
249
        sizer_5.Add((20, 20), 0, 0, 0)
249
        sizer_5.Add((20, 20), 0, 0, 0)
250
        sizer_6.Add((20, 20), 0, 0, 0)
250
        sizer_6.Add((20, 20), 0, 0, 0)
251
        sizer_6.Add(grid_sizer_2, 0, 0, 0)
251
        sizer_6.Add(grid_sizer_2, 0, 0, 0)
252
        sizer_6.Add((20, 20), 0, 0, 0)
252
        sizer_6.Add((20, 20), 0, 0, 0)
253
        sizer_5.Add(sizer_6, 1, wx.EXPAND, 0)
253
        sizer_5.Add(sizer_6, 1, wx.EXPAND, 0)
254
        sizer_5.Add((20, 20), 0, 0, 0)
254
        sizer_5.Add((20, 20), 0, 0, 0)
255
        grid_sizer_3.Add(self.button_5, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 0)
255
        grid_sizer_3.Add(self.button_5, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 0)
256
        grid_sizer_3.Add(self.button_6, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 0)
256
        grid_sizer_3.Add(self.button_6, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 0)
257
        sizer_5.Add(grid_sizer_3, 0, wx.EXPAND, 0)
257
        sizer_5.Add(grid_sizer_3, 0, wx.EXPAND, 0)
258
        sizer_5.Add((20, 20), 0, 0, 0)
258
        sizer_5.Add((20, 20), 0, 0, 0)
259
        self.SetSizer(sizer_5)
259
        self.SetSizer(sizer_5)
260
        sizer_5.Fit(self)
260
        sizer_5.Fit(self)
261
        self.Layout()
261
        self.Layout()
262
        # end wxGlade
262
        # end wxGlade
263
 
263
 
264
        # Store some of the items, we will need them later
264
        # Store some of the items, we will need them later
265
        self.grid_sizer_2 = grid_sizer_2  
265
        self.grid_sizer_2 = grid_sizer_2  
266
        self.sizer_5 = sizer_5
266
        self.sizer_5 = sizer_5
267
 
267
 
268
       
268
       
269
    def onOK(self, event): # wxGlade: SettingsDialog.<event_handler>
269
    def onOK(self, event): # wxGlade: SettingsDialog.<event_handler>
270
        print "Updating parameters"
270
        print "Updating parameters"
271
        try:
271
        try:
272
            i=0
272
            i=0
273
            for setting in self.settings.iteritems():
273
            for setting in self.settings.iteritems():
274
              print setting[0], self.tb[i].GetValue()
274
              print setting[0], self.tb[i].GetValue()
275
              setting[1].set(self.tb[i].GetValue())
275
              setting[1].set(self.tb[i].GetValue())
276
              i += 1
276
              i += 1
277
            event.Skip()
277
            event.Skip()
278
        except:
278
        except:
279
            wx.MessageBox("Invalid format for \"%s\" setting." % setting[1].descr)
279
            wx.MessageBox("Invalid format for \"%s\" setting." % setting[1].descr)
280
       
280
       
281
# end of class SettingsDialog
281
# end of class SettingsDialog
282
 
282
 
283
 
283
 
284
 
284
 
285
class MainFrame(wx.Frame):
285
class MainFrame(wx.Frame):
286
    def __init__(self, *args, **kwds):
286
    def __init__(self, *args, **kwds):
287
        # begin wxGlade: MainFrame.__init__
287
        # begin wxGlade: MainFrame.__init__
288
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
288
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
289
        wx.Frame.__init__(self, *args, **kwds)
289
        wx.Frame.__init__(self, *args, **kwds)
290
       
290
       
291
        # Menu Bar
291
        # Menu Bar
292
        self.frame_1_menubar = wx.MenuBar()
292
        self.frame_1_menubar = wx.MenuBar()
293
        wxglade_tmp_menu = wx.Menu()
293
        wxglade_tmp_menu = wx.Menu()
294
        wxglade_tmp_menu.Append(101, "Settings", "", wx.ITEM_NORMAL)
294
        wxglade_tmp_menu.Append(101, "Settings", "", wx.ITEM_NORMAL)
295
        wxglade_tmp_menu.AppendSeparator()
295
        wxglade_tmp_menu.AppendSeparator()
296
        wxglade_tmp_menu.Append(150, "Exit", "", wx.ITEM_NORMAL)
296
        wxglade_tmp_menu.Append(150, "Exit", "", wx.ITEM_NORMAL)
297
        self.frame_1_menubar.Append(wxglade_tmp_menu, "&File")
297
        self.frame_1_menubar.Append(wxglade_tmp_menu, "&File")
298
        wxglade_tmp_menu = wx.Menu()
298
        wxglade_tmp_menu = wx.Menu()
299
        wxglade_tmp_menu.Append(301, "Delete All\tAlt+D", "", wx.ITEM_NORMAL)
299
        wxglade_tmp_menu.Append(301, "Delete All\tAlt+D", "", wx.ITEM_NORMAL)
300
        wxglade_tmp_menu.Append(302, "Delete Selected\tCtrl+D", "", wx.ITEM_NORMAL)
300
        wxglade_tmp_menu.Append(302, "Delete Selected\tCtrl+D", "", wx.ITEM_NORMAL)
301
        wxglade_tmp_menu.AppendSeparator()
301
        wxglade_tmp_menu.AppendSeparator()
302
        wxglade_tmp_menu.Append(310, "Select All\tCtrl+A", "", wx.ITEM_NORMAL)
302
        wxglade_tmp_menu.Append(310, "Select All\tCtrl+A", "", wx.ITEM_NORMAL)
303
        wxglade_tmp_menu.AppendSeparator()
303
        wxglade_tmp_menu.AppendSeparator()
304
        wxglade_tmp_menu.Append(303, "Load\tCtrl+L", "", wx.ITEM_NORMAL)
304
        wxglade_tmp_menu.Append(303, "Load\tCtrl+L", "", wx.ITEM_NORMAL)
305
        wxglade_tmp_menu.Append(304, "Save\tCtrl+S", "", wx.ITEM_NORMAL)
305
        wxglade_tmp_menu.Append(304, "Save\tCtrl+S", "", wx.ITEM_NORMAL)
306
        self.frame_1_menubar.Append(wxglade_tmp_menu, "TestSet")
306
        self.frame_1_menubar.Append(wxglade_tmp_menu, "TestSet")
307
        wxglade_tmp_menu = wx.Menu()
307
        wxglade_tmp_menu = wx.Menu()
308
        wxglade_tmp_menu.Append(401, "Flash VibTest FC software", "", wx.ITEM_NORMAL)
308
        wxglade_tmp_menu.Append(401, "Flash VibTest FC software", "", wx.ITEM_NORMAL)
309
        wxglade_tmp_menu.Append(402, "Restore original FC software", "", wx.ITEM_NORMAL)
309
        wxglade_tmp_menu.Append(402, "Restore original FC software", "", wx.ITEM_NORMAL)
310
        self.frame_1_menubar.Append(wxglade_tmp_menu, "MK")
310
        self.frame_1_menubar.Append(wxglade_tmp_menu, "MK")
311
        wxglade_tmp_menu = wx.Menu()
311
        wxglade_tmp_menu = wx.Menu()
312
        wxglade_tmp_menu.Append(1099, "About", "", wx.ITEM_NORMAL)
312
        wxglade_tmp_menu.Append(1099, "About", "", wx.ITEM_NORMAL)
313
        self.frame_1_menubar.Append(wxglade_tmp_menu, "Help")
313
        self.frame_1_menubar.Append(wxglade_tmp_menu, "Help")
314
        self.SetMenuBar(self.frame_1_menubar)
314
        self.SetMenuBar(self.frame_1_menubar)
315
        # Menu Bar end
315
        # Menu Bar end
316
        self.label_1 = wx.StaticText(self, -1, "Test Description :", style=wx.ALIGN_RIGHT)
316
        self.label_1 = wx.StaticText(self, -1, "Test Description :", style=wx.ALIGN_RIGHT)
317
        self.descrCtrl = wx.TextCtrl(self, -1, "N/A")
317
        self.descrCtrl = wx.TextCtrl(self, -1, "N/A")
318
        self.label_1_copy = wx.StaticText(self, -1, "Channel(s) :", style=wx.ALIGN_RIGHT)
318
        self.label_1_copy = wx.StaticText(self, -1, "Channel(s) :", style=wx.ALIGN_RIGHT)
319
        self.gyroYawCb = wx.CheckBox(self, -1, "Gyro Yaw")
319
        self.gyroYawCb = wx.CheckBox(self, -1, "Gyro Yaw")
320
        self.gyroRollCb = wx.CheckBox(self, -1, "Gyro Roll")
320
        self.gyroRollCb = wx.CheckBox(self, -1, "Gyro Roll")
321
        self.gyroNickCb = wx.CheckBox(self, -1, "Gyro Nick")
321
        self.gyroNickCb = wx.CheckBox(self, -1, "Gyro Nick")
322
        self.accTopCb = wx.CheckBox(self, -1, "ACC Top")
322
        self.accTopCb = wx.CheckBox(self, -1, "ACC Top")
323
        self.accRollCb = wx.CheckBox(self, -1, "ACC Roll")
323
        self.accRollCb = wx.CheckBox(self, -1, "ACC Roll")
324
        self.accNickCb = wx.CheckBox(self, -1, "ACC Nick")
324
        self.accNickCb = wx.CheckBox(self, -1, "ACC Nick")
325
        self.label_3 = wx.StaticText(self, -1, "Motor(s) :", style=wx.ALIGN_RIGHT)
325
        self.label_3 = wx.StaticText(self, -1, "Motor(s) :", style=wx.ALIGN_RIGHT)
326
        self.motorsCtrl = wx.TextCtrl(self, -1, "1")
326
        self.motorsCtrl = wx.TextCtrl(self, -1, "1")
327
        self.label_4 = wx.StaticText(self, -1, "Speed(s) :")
327
        self.label_4 = wx.StaticText(self, -1, "Speed(s) :")
328
        self.speedCtrl = wx.TextCtrl(self, -1, "100-200:10")
328
        self.speedCtrl = wx.TextCtrl(self, -1, "100-200:10")
329
        self.bitmap_button_1 = wx.BitmapButton(self, -1, wx.Bitmap("Resources\\Fairytale_player_play.png", wx.BITMAP_TYPE_ANY))
329
        self.bitmap_button_1 = wx.BitmapButton(self, -1, wx.Bitmap("Resources\\Fairytale_player_play.png", wx.BITMAP_TYPE_ANY))
330
        self.static_line_1 = wx.StaticLine(self, -1)
330
        self.static_line_1 = wx.StaticLine(self, -1)
331
        self.graphCtrl = wx.lib.plot.PlotCanvas(self, size=(800,300))
331
        self.graphCtrl = wx.lib.plot.PlotCanvas(self, size=(800,300))
332
        self.label_40 = wx.StaticText(self, -1, "Graph Type ")
332
        self.label_40 = wx.StaticText(self, -1, "Graph Type ")
333
        self.graphTypeChoice = wx.Choice(self, -1, choices=["Raw Signal", "Filtered Signal", "Spectrum"])
333
        self.graphTypeChoice = wx.Choice(self, -1, choices=["Raw Signal", "Filtered Signal", "Spectrum"])
334
        self.label_41 = wx.StaticText(self, -1, "Y Axis Range ")
334
        self.label_41 = wx.StaticText(self, -1, "Y Axis Range ")
335
        self.yAxisChoice = wx.Choice(self, -1, choices=["25", "50", "75", "100", "200"])
335
        self.yAxisChoice = wx.Choice(self, -1, choices=["25", "50", "75", "100", "200", "500", "1000"])
336
        self.copyGraphButton = wx.Button(self, -1, "Copy Graph Data")
336
        self.copyGraphButton = wx.Button(self, -1, "Copy Graph Data")
337
        self.TestListCtrl = wx.ListCtrl(self, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
337
        self.TestListCtrl = wx.ListCtrl(self, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
338
 
338
 
339
        self.__set_properties()
339
        self.__set_properties()
340
        self.__do_layout()
340
        self.__do_layout()
341
 
341
 
342
        self.Bind(wx.EVT_MENU, self.OnSettings, id=101)
342
        self.Bind(wx.EVT_MENU, self.OnSettings, id=101)
343
        self.Bind(wx.EVT_MENU, self.onExit, id=150)
343
        self.Bind(wx.EVT_MENU, self.onExit, id=150)
344
        self.Bind(wx.EVT_MENU, self.onClear, id=301)
344
        self.Bind(wx.EVT_MENU, self.onClear, id=301)
345
        self.Bind(wx.EVT_MENU, self.onClearSelected, id=302)
345
        self.Bind(wx.EVT_MENU, self.onClearSelected, id=302)
346
        self.Bind(wx.EVT_MENU, self.onSelectAll, id=310)
346
        self.Bind(wx.EVT_MENU, self.onSelectAll, id=310)
347
        self.Bind(wx.EVT_MENU, self.OnImport, id=303)
347
        self.Bind(wx.EVT_MENU, self.OnImport, id=303)
348
        self.Bind(wx.EVT_MENU, self.onExport, id=304)
348
        self.Bind(wx.EVT_MENU, self.onExport, id=304)
349
        self.Bind(wx.EVT_MENU, self.onAbout, id=1099)
349
        self.Bind(wx.EVT_MENU, self.onAbout, id=1099)
350
        self.Bind(wx.EVT_BUTTON, self.onStartMeasure, self.bitmap_button_1)
350
        self.Bind(wx.EVT_BUTTON, self.onStartMeasure, self.bitmap_button_1)
351
        self.Bind(wx.EVT_CHOICE, self.onGraphTypeChange, self.graphTypeChoice)
351
        self.Bind(wx.EVT_CHOICE, self.onGraphTypeChange, self.graphTypeChoice)
352
        self.Bind(wx.EVT_CHOICE, self.onYAxisChange, self.yAxisChoice)
352
        self.Bind(wx.EVT_CHOICE, self.onYAxisChange, self.yAxisChoice)
353
        self.Bind(wx.EVT_BUTTON, self.onCopyGraphData, self.copyGraphButton)
353
        self.Bind(wx.EVT_BUTTON, self.onCopyGraphData, self.copyGraphButton)
354
        # end wxGlade
354
        # end wxGlade
355
        favicon = wx.Icon('%s/Resources/60px-Procman.ico' % rootPath, wx.BITMAP_TYPE_ICO, 32, 32)
355
        favicon = wx.Icon('%s/Resources/60px-Procman.ico' % rootPath, wx.BITMAP_TYPE_ICO, 32, 32)
356
        wx.Frame.SetIcon(self, favicon)
356
        wx.Frame.SetIcon(self, favicon)
357
        self.graphCtrl.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
357
        self.graphCtrl.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
358
        self.measureState = 0
358
        self.measureState = 0
359
       
359
       
360
 
360
 
361
    def setApp(self, app):
361
    def setApp(self, app):
362
        self.app = app
362
        self.app = app
363
 
363
 
364
    def __set_properties(self):
364
    def __set_properties(self):
365
        # begin wxGlade: MainFrame.__set_properties
365
        # begin wxGlade: MainFrame.__set_properties
366
        self.SetTitle("VibrationTest")
366
        self.SetTitle("VibrationTest")
367
        self.SetSize((850, 700))
367
        self.SetSize((850, 700))
368
        self.label_1.SetMinSize((110, -1))
368
        self.label_1.SetMinSize((110, -1))
369
        self.label_1.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
369
        self.label_1.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
370
        self.descrCtrl.SetMinSize((350, -1))
370
        self.descrCtrl.SetMinSize((350, -1))
371
        self.label_1_copy.SetMinSize((110, -1))
371
        self.label_1_copy.SetMinSize((110, -1))
372
        self.label_1_copy.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
372
        self.label_1_copy.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
373
        self.gyroYawCb.SetMinSize((100, -1))
373
        self.gyroYawCb.SetMinSize((100, -1))
374
        self.gyroYawCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
374
        self.gyroYawCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
375
        self.gyroRollCb.SetMinSize((100, -1))
375
        self.gyroRollCb.SetMinSize((100, -1))
376
        self.gyroRollCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
376
        self.gyroRollCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
377
        self.gyroNickCb.SetMinSize((100, -1))
377
        self.gyroNickCb.SetMinSize((100, -1))
378
        self.gyroNickCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
378
        self.gyroNickCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
379
        self.accTopCb.SetMinSize((100, -1))
379
        self.accTopCb.SetMinSize((100, -1))
380
        self.accTopCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
380
        self.accTopCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
381
        self.accRollCb.SetMinSize((100, -1))
381
        self.accRollCb.SetMinSize((100, -1))
382
        self.accRollCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
382
        self.accRollCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
383
        self.accRollCb.SetValue(1)
383
        self.accRollCb.SetValue(1)
384
        self.accNickCb.SetMinSize((100, -1))
384
        self.accNickCb.SetMinSize((100, -1))
385
        self.accNickCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
385
        self.accNickCb.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
386
        self.label_3.SetMinSize((110, -1))
386
        self.label_3.SetMinSize((110, -1))
387
        self.label_3.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
387
        self.label_3.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
388
        self.label_4.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
388
        self.label_4.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
389
        self.speedCtrl.SetToolTipString("e.g. \n 100 \n 100,150 \n 100-200:10 \n 50,100-200:10 \n 5*100,5*200")
389
        self.speedCtrl.SetToolTipString("e.g. \n 100 \n 100,150 \n 100-200:10 \n 50,100-200:10 \n 5*100,5*200")
390
        self.bitmap_button_1.SetToolTipString("Start Measurement")
390
        self.bitmap_button_1.SetToolTipString("Start Measurement")
391
        self.bitmap_button_1.SetSize(self.bitmap_button_1.GetBestSize())
391
        self.bitmap_button_1.SetSize(self.bitmap_button_1.GetBestSize())
392
        self.static_line_1.SetMinSize((800,3))
392
        self.static_line_1.SetMinSize((800,3))
393
        self.graphCtrl.SetMinSize((800,300))
393
        self.graphCtrl.SetMinSize((800,300))
394
        self.label_40.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
394
        self.label_40.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
395
        self.graphTypeChoice.SetSelection(0)
395
        self.graphTypeChoice.SetSelection(0)
396
        self.label_41.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
396
        self.label_41.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
397
        self.yAxisChoice.SetSelection(1)
397
        self.yAxisChoice.SetSelection(1)
398
        self.copyGraphButton.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
398
        self.copyGraphButton.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
399
        self.TestListCtrl.SetMinSize((800,300))
399
        self.TestListCtrl.SetMinSize((800,300))
400
        self.TestListCtrl.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
400
        self.TestListCtrl.SetFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
401
        # end wxGlade
401
        # end wxGlade
402
 
402
 
403
    def __do_layout(self):
403
    def __do_layout(self):
404
        # begin wxGlade: MainFrame.__do_layout
404
        # begin wxGlade: MainFrame.__do_layout
405
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
405
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
406
        sizer_8 = wx.BoxSizer(wx.VERTICAL)
406
        sizer_8 = wx.BoxSizer(wx.VERTICAL)
407
        sizer_11 = wx.BoxSizer(wx.VERTICAL)
407
        sizer_11 = wx.BoxSizer(wx.VERTICAL)
408
        sizer_12 = wx.BoxSizer(wx.HORIZONTAL)
408
        sizer_12 = wx.BoxSizer(wx.HORIZONTAL)
409
        sizer_17 = wx.BoxSizer(wx.VERTICAL)
409
        sizer_17 = wx.BoxSizer(wx.VERTICAL)
410
        sizer_9 = wx.BoxSizer(wx.HORIZONTAL)
410
        sizer_9 = wx.BoxSizer(wx.HORIZONTAL)
411
        sizer_7 = wx.BoxSizer(wx.HORIZONTAL)
411
        sizer_7 = wx.BoxSizer(wx.HORIZONTAL)
412
        sizer_13 = wx.BoxSizer(wx.VERTICAL)
412
        sizer_13 = wx.BoxSizer(wx.VERTICAL)
413
        sizer_16 = wx.BoxSizer(wx.HORIZONTAL)
413
        sizer_16 = wx.BoxSizer(wx.HORIZONTAL)
414
        sizer_10 = wx.BoxSizer(wx.HORIZONTAL)
414
        sizer_10 = wx.BoxSizer(wx.HORIZONTAL)
415
        sizer_18 = wx.BoxSizer(wx.VERTICAL)
415
        sizer_18 = wx.BoxSizer(wx.VERTICAL)
416
        sizer_20 = wx.BoxSizer(wx.HORIZONTAL)
416
        sizer_20 = wx.BoxSizer(wx.HORIZONTAL)
417
        sizer_19 = wx.BoxSizer(wx.HORIZONTAL)
417
        sizer_19 = wx.BoxSizer(wx.HORIZONTAL)
418
        sizer_14 = wx.BoxSizer(wx.HORIZONTAL)
418
        sizer_14 = wx.BoxSizer(wx.HORIZONTAL)
419
        sizer_3.Add((20, 20), 0, 0, 0)
419
        sizer_3.Add((20, 20), 0, 0, 0)
420
        sizer_8.Add((20, 20), 0, 0, 0)
420
        sizer_8.Add((20, 20), 0, 0, 0)
421
        sizer_14.Add(self.label_1, 0, wx.ALIGN_CENTER_VERTICAL, 0)
421
        sizer_14.Add(self.label_1, 0, wx.ALIGN_CENTER_VERTICAL, 0)
422
        sizer_14.Add((20, 20), 0, 0, 0)
422
        sizer_14.Add((20, 20), 0, 0, 0)
423
        sizer_14.Add(self.descrCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
423
        sizer_14.Add(self.descrCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
424
        sizer_13.Add(sizer_14, 0, 0, 0)
424
        sizer_13.Add(sizer_14, 0, 0, 0)
425
        sizer_13.Add((20, 5), 0, 0, 0)
425
        sizer_13.Add((20, 5), 0, 0, 0)
426
        sizer_10.Add(self.label_1_copy, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
426
        sizer_10.Add(self.label_1_copy, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
427
        sizer_10.Add((20, 20), 0, 0, 0)
427
        sizer_10.Add((20, 20), 0, 0, 0)
428
        sizer_19.Add(self.gyroYawCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
428
        sizer_19.Add(self.gyroYawCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
429
        sizer_19.Add((20, 20), 0, 0, 0)
429
        sizer_19.Add((20, 20), 0, 0, 0)
430
        sizer_19.Add(self.gyroRollCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
430
        sizer_19.Add(self.gyroRollCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
431
        sizer_19.Add((20, 20), 0, 0, 0)
431
        sizer_19.Add((20, 20), 0, 0, 0)
432
        sizer_19.Add(self.gyroNickCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
432
        sizer_19.Add(self.gyroNickCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
433
        sizer_18.Add(sizer_19, 1, wx.EXPAND, 0)
433
        sizer_18.Add(sizer_19, 1, wx.EXPAND, 0)
434
        sizer_20.Add(self.accTopCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
434
        sizer_20.Add(self.accTopCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
435
        sizer_20.Add((20, 20), 0, 0, 0)
435
        sizer_20.Add((20, 20), 0, 0, 0)
436
        sizer_20.Add(self.accRollCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
436
        sizer_20.Add(self.accRollCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
437
        sizer_20.Add((20, 20), 0, 0, 0)
437
        sizer_20.Add((20, 20), 0, 0, 0)
438
        sizer_20.Add(self.accNickCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
438
        sizer_20.Add(self.accNickCb, 0, wx.ALIGN_CENTER_VERTICAL, 0)
439
        sizer_18.Add(sizer_20, 1, wx.EXPAND, 0)
439
        sizer_18.Add(sizer_20, 1, wx.EXPAND, 0)
440
        sizer_10.Add(sizer_18, 1, wx.EXPAND, 0)
440
        sizer_10.Add(sizer_18, 1, wx.EXPAND, 0)
441
        sizer_13.Add(sizer_10, 1, wx.EXPAND, 0)
441
        sizer_13.Add(sizer_10, 1, wx.EXPAND, 0)
442
        sizer_13.Add((20, 5), 0, 0, 0)
442
        sizer_13.Add((20, 5), 0, 0, 0)
443
        sizer_16.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL, 0)
443
        sizer_16.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL, 0)
444
        sizer_16.Add((20, 20), 0, 0, 0)
444
        sizer_16.Add((20, 20), 0, 0, 0)
445
        sizer_16.Add(self.motorsCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
445
        sizer_16.Add(self.motorsCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
446
        sizer_16.Add((50, 20), 0, 0, 0)
446
        sizer_16.Add((50, 20), 0, 0, 0)
447
        sizer_16.Add(self.label_4, 0, wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
447
        sizer_16.Add(self.label_4, 0, wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
448
        sizer_16.Add((20, 20), 0, 0, 0)
448
        sizer_16.Add((20, 20), 0, 0, 0)
449
        sizer_16.Add(self.speedCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
449
        sizer_16.Add(self.speedCtrl, 0, wx.ALIGN_CENTER_VERTICAL, 0)
450
        sizer_13.Add(sizer_16, 0, wx.EXPAND, 0)
450
        sizer_13.Add(sizer_16, 0, wx.EXPAND, 0)
451
        sizer_7.Add(sizer_13, 1, wx.EXPAND, 0)
451
        sizer_7.Add(sizer_13, 1, wx.EXPAND, 0)
452
        sizer_7.Add((20, 20), 0, 0, 0)
452
        sizer_7.Add((20, 20), 0, 0, 0)
453
        sizer_7.Add((20, 20), 0, 0, 0)
453
        sizer_7.Add((20, 20), 0, 0, 0)
454
        sizer_9.Add(sizer_7, 0, 0, 0)
454
        sizer_9.Add(sizer_7, 0, 0, 0)
455
        sizer_9.Add(self.bitmap_button_1, 0, 0, 0)
455
        sizer_9.Add(self.bitmap_button_1, 0, 0, 0)
456
        sizer_8.Add(sizer_9, 0, 0, 0)
456
        sizer_8.Add(sizer_9, 0, 0, 0)
457
        sizer_17.Add((20, 20), 0, 0, 0)
457
        sizer_17.Add((20, 20), 0, 0, 0)
458
        sizer_17.Add(self.static_line_1, 0, wx.EXPAND, 0)
458
        sizer_17.Add(self.static_line_1, 0, wx.EXPAND, 0)
459
        sizer_17.Add((20, 20), 0, 0, 0)
459
        sizer_17.Add((20, 20), 0, 0, 0)
460
        sizer_8.Add(sizer_17, 0, wx.EXPAND, 0)
460
        sizer_8.Add(sizer_17, 0, wx.EXPAND, 0)
461
        sizer_11.Add(self.graphCtrl, 1, wx.EXPAND, 0)
461
        sizer_11.Add(self.graphCtrl, 1, wx.EXPAND, 0)
462
        sizer_11.Add((20, 5), 0, 0, 0)
462
        sizer_11.Add((20, 5), 0, 0, 0)
463
        sizer_12.Add(self.label_40, 0, wx.ALIGN_CENTER_VERTICAL, 0)
463
        sizer_12.Add(self.label_40, 0, wx.ALIGN_CENTER_VERTICAL, 0)
464
        sizer_12.Add(self.graphTypeChoice, 0, 0, 0)
464
        sizer_12.Add(self.graphTypeChoice, 0, 0, 0)
465
        sizer_12.Add((40, 20), 0, 0, 0)
465
        sizer_12.Add((40, 20), 0, 0, 0)
466
        sizer_12.Add(self.label_41, 0, wx.ALIGN_CENTER_VERTICAL, 0)
466
        sizer_12.Add(self.label_41, 0, wx.ALIGN_CENTER_VERTICAL, 0)
467
        sizer_12.Add(self.yAxisChoice, 0, 0, 0)
467
        sizer_12.Add(self.yAxisChoice, 0, 0, 0)
468
        sizer_12.Add((80, 20), 0, 0, 0)
468
        sizer_12.Add((80, 20), 0, 0, 0)
469
        sizer_12.Add(self.copyGraphButton, 0, 0, 0)
469
        sizer_12.Add(self.copyGraphButton, 0, 0, 0)
470
        sizer_11.Add(sizer_12, 0, 0, 0)
470
        sizer_11.Add(sizer_12, 0, 0, 0)
471
        sizer_8.Add(sizer_11, 0, 0, 0)
471
        sizer_8.Add(sizer_11, 0, 0, 0)
472
        sizer_8.Add((20, 30), 0, 0, 0)
472
        sizer_8.Add((20, 30), 0, 0, 0)
473
        sizer_8.Add(self.TestListCtrl, 1, 0, 0)
473
        sizer_8.Add(self.TestListCtrl, 1, 0, 0)
474
        sizer_8.Add((20, 20), 0, 0, 0)
474
        sizer_8.Add((20, 20), 0, 0, 0)
475
        sizer_3.Add(sizer_8, 1, wx.EXPAND, 0)
475
        sizer_3.Add(sizer_8, 1, wx.EXPAND, 0)
476
        self.SetSizer(sizer_3)
476
        self.SetSizer(sizer_3)
477
        self.Layout()
477
        self.Layout()
478
        self.SetSize((850, 700))
478
        self.SetSize((850, 700))
479
        # end wxGlade
479
        # end wxGlade
480
 
480
 
481
        # List events
481
        # List events
482
        self.TestListCtrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnTestSelected, self.TestListCtrl)
482
        self.TestListCtrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnTestSelected, self.TestListCtrl)
483
 
483
 
484
        # Configure Graph
484
        # Configure Graph
485
        #self.graphCtrl = wx.lib.plot.PlotCanvas(self.GraphPanel, size=(800,300))
485
        #self.graphCtrl = wx.lib.plot.PlotCanvas(self.GraphPanel, size=(800,300))
486
       
486
       
487
        self.graphCtrl.SetPointLabelFunc(self.DrawPointLabel)
487
        self.graphCtrl.SetPointLabelFunc(self.DrawPointLabel)
488
       
488
       
489
        self.graphCtrl.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.NORMAL))
489
        self.graphCtrl.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.NORMAL))
490
        self.graphCtrl.SetFontSizeAxis(10)
490
        self.graphCtrl.SetFontSizeAxis(10)
491
        self.graphCtrl.SetFontSizeLegend(7)
491
        self.graphCtrl.SetFontSizeLegend(7)
492
        self.graphCtrl.setLogScale((False,False))
492
        self.graphCtrl.setLogScale((False,False))
493
 
493
 
494
 
494
 
495
        # Configure TestListCtrl
495
        # Configure TestListCtrl
496
        self.TestListCtrl.InsertColumn(0, "Description")
496
        self.TestListCtrl.InsertColumn(0, "Description")
497
        self.TestListCtrl.InsertColumn(1, "Voltage")
497
        self.TestListCtrl.InsertColumn(1, "Voltage")
498
        self.TestListCtrl.InsertColumn(2, "Speed")
498
        self.TestListCtrl.InsertColumn(2, "Speed")
499
        self.TestListCtrl.InsertColumn(3, "Channel")
499
        self.TestListCtrl.InsertColumn(3, "Channel")
500
        self.TestListCtrl.InsertColumn(4, "Vibration Value")
500
        self.TestListCtrl.InsertColumn(4, "Vibration Value")
501
        self.TestListCtrl.SetColumnWidth(4, 500)
501
        self.TestListCtrl.SetColumnWidth(4, 500)
502
 
502
 
503
    def DrawPointLabel(self, dc, mDataDict):
503
    def DrawPointLabel(self, dc, mDataDict):
504
        """This is the fuction that defines how the pointLabels are plotted
504
        """This is the fuction that defines how the pointLabels are plotted
505
            dc - DC that will be passed
505
            dc - DC that will be passed
506
            mDataDict - Dictionary of data that you want to use for the pointLabel
506
            mDataDict - Dictionary of data that you want to use for the pointLabel
507
 
507
 
508
            As an example I have decided I want a box at the curve point
508
            As an example I have decided I want a box at the curve point
509
            with some text information about the curve plotted below.
509
            with some text information about the curve plotted below.
510
            Any wxDC method can be used.
510
            Any wxDC method can be used.
511
        """
511
        """
512
        # ----------
512
        # ----------
513
        dc.SetPen(wx.Pen(wx.BLACK))
513
        dc.SetPen(wx.Pen(wx.BLACK))
514
        dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
514
        dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
515
       
515
       
516
        sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point
516
        sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point
517
        dc.DrawRectangle( sx-5,sy-5, 10, 10)  #10by10 square centered on point
517
        dc.DrawRectangle( sx-5,sy-5, 10, 10)  #10by10 square centered on point
518
        px,py = mDataDict["pointXY"]
518
        px,py = mDataDict["pointXY"]
519
        cNum = mDataDict["curveNum"]
519
        cNum = mDataDict["curveNum"]
520
        pntIn = mDataDict["pIndex"]
520
        pntIn = mDataDict["pIndex"]
521
        legend = mDataDict["legend"]
521
        legend = mDataDict["legend"]
522
        #make a string to display
522
        #make a string to display
523
        s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
523
        s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
524
        dc.DrawText(s, sx , sy+1)
524
        dc.DrawText(s, sx , sy+1)
525
        # -----------
525
        # -----------
526
 
526
 
527
 
527
 
528
    def onNewTest(self, test):
528
    def onNewTest(self, test):
529
        index = self.TestListCtrl.InsertStringItem(sys.maxint, test.descr)
529
        index = self.TestListCtrl.InsertStringItem(sys.maxint, test.descr)
530
        self._fillRowInTestList(index, test)
530
        self._fillRowInTestList(index, test)
531
        self.TestListCtrl.Select(index)
531
        self.TestListCtrl.Select(index)
532
 
532
 
533
    def _fillRowInTestList(self, index, test):
533
    def _fillRowInTestList(self, index, test):
534
        self.TestListCtrl.SetStringItem(index, 0, test.descr)
534
        self.TestListCtrl.SetStringItem(index, 0, test.descr)
535
        self.TestListCtrl.SetStringItem(index, 1, "%.1f V" %test.voltage)
535
        self.TestListCtrl.SetStringItem(index, 1, "%.1f V" %test.voltage)
536
        self.TestListCtrl.SetStringItem(index, 2, str(test.speed))
536
        self.TestListCtrl.SetStringItem(index, 2, str(test.speed))
537
        self.TestListCtrl.SetStringItem(index, 3, test.channel)
537
        self.TestListCtrl.SetStringItem(index, 3, test.channel)
538
 
538
 
539
        vv = test.getVibValue()
539
        vv = test.getVibValue()
540
        vvs = "|%s| (%.1f)" % ("----------------------------------------------------------------------------------------------------"[0:min(int(vv+1)/2,100)], vv)
540
        vvs = "|%s| (%.1f)" % ("----------------------------------------------------------------------------------------------------"[0:min(int(vv+1)/2,100)], vv)
541
        self.TestListCtrl.SetStringItem(index, 4, vvs)
541
        self.TestListCtrl.SetStringItem(index, 4, vvs)
542
 
542
 
543
    def refreshData(self):
543
    def refreshData(self):
544
        for idx in range(len(self.app.VibTests)):
544
        for idx in range(len(self.app.VibTests)):
545
            self._fillRowInTestList(idx, self.app.getTest(idx))
545
            self._fillRowInTestList(idx, self.app.getTest(idx))
546
        self.drawGraph()
546
        self.drawGraph()
547
           
547
           
548
    def OnTestSelected(self, event):
548
    def OnTestSelected(self, event):
549
         testId = event.m_itemIndex
549
         testId = event.m_itemIndex
550
         print "Test Selected id=%d" % (testId)
550
         print "Test Selected id=%d" % (testId)
551
         self.activeTestId = testId
551
         self.activeTestId = testId
552
         self.drawGraph()
552
         self.drawGraph()
553
         
553
         
554
         
554
         
555
    def orderSelectedTests(self):
555
    def orderSelectedTests(self):
556
        tests = []
556
        tests = []
557
        idx = self.TestListCtrl.GetFirstSelected()
557
        idx = self.TestListCtrl.GetFirstSelected()
558
        while idx != -1:
558
        while idx != -1:
559
            header = "%s %s"%(self.app.getTest(idx).descr,self.app.getTest(idx).channel)
559
            header = "%s %s"%(self.app.getTest(idx).descr,self.app.getTest(idx).channel)
560
            found = False
560
            found = False
561
            for t in tests:
561
            for t in tests:
562
              if t[0] == header:
562
              if t[0] == header:
563
                t.append(idx)
563
                t.append(idx)
564
                found = True
564
                found = True
565
                break
565
                break
566
            if not found:
566
            if not found:
567
                tests.append([header, idx])
567
                tests.append([header, idx])
568
            idx = self.TestListCtrl.GetNextSelected(idx)
568
            idx = self.TestListCtrl.GetNextSelected(idx)
569
        return tests
569
        return tests
570
     
570
     
571
    def OnMouseLeftDown(self,event):
571
    def OnMouseLeftDown(self,event):
572
        x,y = self.graphCtrl._getXY(event)
572
        x,y = self.graphCtrl._getXY(event)
573
        s= "Left Mouse Down at Point: (%.4f, %.4f)" % (x,y)
573
        s= "Left Mouse Down at Point: (%.4f, %.4f)" % (x,y)
574
        print s
574
        print s
575
        if self.measureState == 0:
575
        if self.measureState == 0:
576
            self.measureX1 = x
576
            self.measureX1 = x
577
            self.measureState += 1
577
            self.measureState += 1
578
        elif self.measureState == 1:
578
        elif self.measureState == 1:
579
            dx = x-self.measureX1
579
            dx = x-self.measureX1
580
            rpm = 60.0*1000/dx
580
            rpm = 60.0*1000/dx
581
            s = "Time-Difference: %.1fms\n"%dx
581
            s = "Time-Difference: %.1fms\n"%dx
582
            for i in range(1,8):
582
            for i in range(1,8):
583
                s += "\n%dT -> %d RPM" %(i,rpm*i)
583
                s += "\n%dT -> %d RPM" %(i,rpm*i)
584
            dial = wx.MessageDialog(None, s, 'RPM Measurement', wx.OK )
584
            dial = wx.MessageDialog(None, s, 'RPM Measurement', wx.OK )
585
            dial.ShowModal()
585
            dial.ShowModal()
586
         
586
         
587
            self.measureState = 0
587
            self.measureState = 0
588
           
588
           
589
       
589
       
590
 
590
 
591
    def drawGraph(self):
591
    def drawGraph(self):
592
         
592
         
593
         y = int(self.yAxisChoice.GetStringSelection())
593
         y = int(self.yAxisChoice.GetStringSelection())
594
 
594
 
595
         nbSelected = self.TestListCtrl.SelectedItemCount
595
         nbSelected = self.TestListCtrl.SelectedItemCount
596
 
596
 
597
         if nbSelected == 0:
597
         if nbSelected == 0:
598
              self.graphCtrl.Clear()
598
              self.graphCtrl.Clear()
599
         
599
         
600
         elif nbSelected > 1:
600
         elif nbSelected > 1:
601
             self.graphTypeChoice.Disable()
601
             self.graphTypeChoice.Disable()
602
             self.copyGraphButton.Enable()
602
             self.copyGraphButton.Enable()
603
             
603
             
604
             tests = self.orderSelectedTests()
604
             tests = self.orderSelectedTests()
605
             
605
             
606
             lines = []
606
             lines = []
607
             maxX = 0
607
             maxX = 0
608
             cCnt = 0
608
             cCnt = 0
609
             for s in tests:
609
             for s in tests:
610
               data = []
610
               data = []
611
               x=1
611
               x=1
612
               for t in s[1:]:
612
               for t in s[1:]:
613
                 data.append([x,self.app.getTest(t).getVibValue()])
613
                 data.append([x,self.app.getTest(t).getVibValue()])
614
                 x += 1
614
                 x += 1
615
               lines.append(wx.lib.plot.PolyLine(data, legend= s[0], colour=COLORS[cCnt], width=2))
615
               lines.append(wx.lib.plot.PolyLine(data, legend= s[0], colour=COLORS[cCnt], width=2))
616
               lines.append(wx.lib.plot.PolyMarker(data, legend= "", colour=COLORS[cCnt], marker='circle',size=2))
616
               lines.append(wx.lib.plot.PolyMarker(data, legend= "", colour=COLORS[cCnt], marker='circle',size=2))
617
               maxX = max(maxX, x)
617
               maxX = max(maxX, x)
618
               cCnt += 1
618
               cCnt += 1
619
                       
619
                       
620
             title = "Comparing tests"
620
             title = "Comparing tests"
621
             self.graphCtrl.setLogScale((False,False))
621
             self.graphCtrl.setLogScale((False,False))
622
             self.graphCtrl.Draw(wx.lib.plot.PlotGraphics(lines, title, "Test", "Vibration Value"), xAxis=(1,maxX), yAxis=(0,y))
622
             self.graphCtrl.Draw(wx.lib.plot.PlotGraphics(lines, title, "Test", "Vibration Value"), xAxis=(1,maxX), yAxis=(0,y))
623
             self.graphCtrl.SetEnableGrid('Horizontal')
623
             self.graphCtrl.SetEnableGrid('Horizontal')
624
             self.graphCtrl.SetEnableLegend(True)
624
             self.graphCtrl.SetEnableLegend(True)
625
             
625
             
626
 
626
 
627
         else:
627
         else:
628
             self.graphTypeChoice.Enable()
628
             self.graphTypeChoice.Enable()
629
             self.copyGraphButton.Disable()
629
             self.copyGraphButton.Disable()
630
             vibTest = self.app.getTest(self.activeTestId)
630
             vibTest = self.app.getTest(self.activeTestId)
631
             nb = vibTest.getDataLen()
631
             nb = vibTest.getDataLen()
632
 
632
 
633
             if self.graphTypeChoice.GetSelection() == 0:
633
             if self.graphTypeChoice.GetSelection() == 0:
634
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
634
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
635
                 xydata.shape = (nb, 2)
635
                 xydata.shape = (nb, 2)
636
                 xydata[:,1] = vibTest.getRawData()
636
                 xydata[:,1] = vibTest.getRawData()
637
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
637
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
638
       
638
       
639
                 title = "Raw Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
639
                 title = "Raw Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
640
                 self.graphCtrl.setLogScale((False,False))
640
                 self.graphCtrl.setLogScale((False,False))
641
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y/2,y/2))
641
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y/2,y/2))
642
                 self.graphCtrl.SetEnableGrid('Horizontal')
642
                 self.graphCtrl.SetEnableGrid('Horizontal')
643
                 self.graphCtrl.SetEnableLegend(False)
643
                 self.graphCtrl.SetEnableLegend(False)
644
                 
644
                 
645
   
645
   
646
             if self.graphTypeChoice.GetSelection() == 1:
646
             if self.graphTypeChoice.GetSelection() == 1:
647
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
647
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
648
                 xydata.shape = (nb, 2)
648
                 xydata.shape = (nb, 2)
649
                 xydata[:,1] = vibTest.getFilteredData()
649
                 xydata[:,1] = vibTest.getFilteredData()
650
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
650
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
651
       
651
       
652
                 title = "Filtered Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
652
                 title = "Filtered Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
653
                 self.graphCtrl.setLogScale((False,False))
653
                 self.graphCtrl.setLogScale((False,False))
654
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y/2,y/2))
654
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y/2,y/2))
655
                 self.graphCtrl.SetEnableGrid('Horizontal')
655
                 self.graphCtrl.SetEnableGrid('Horizontal')
656
                 self.graphCtrl.SetEnableLegend(False)
656
                 self.graphCtrl.SetEnableLegend(False)
657
   
657
   
658
             elif self.graphTypeChoice.GetSelection() == 2:
658
             elif self.graphTypeChoice.GetSelection() == 2:
659
                 xydata = _Numeric.linspace(0,FS/2,nb)
659
                 xydata = _Numeric.linspace(0,FS/2,nb)
660
                 xydata.shape = (nb/2, 2)
660
                 xydata.shape = (nb/2, 2)
661
                 
661
                 
662
                 xydata[:,1] = vibTest.getSpectrum()
662
                 xydata[:,1] = vibTest.getSpectrum()
663
                 
663
                 
664
                 #print xydata
664
                 #print xydata
665
   
665
   
666
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Spectrum', colour='red')
666
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Spectrum', colour='red')
667
                 markers = wx.lib.plot.PolyMarker(xydata, legend= '', colour='red', marker='circle',size=2)
667
                 markers = wx.lib.plot.PolyMarker(xydata, legend= '', colour='red', marker='circle',size=2)
668
                 
668
                 
669
                 fc = self.app.settings["hpf"].value
669
                 fc = self.app.settings["hpf"].value
670
                 filterLine1 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
670
                 filterLine1 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
671
                 fc = self.app.settings["lpf"].value
671
                 fc = self.app.settings["lpf"].value
672
                 filterLine2 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
672
                 filterLine2 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
673
       
673
       
674
                 title = "Spectrum: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
674
                 title = "Spectrum: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
675
                 self.graphCtrl.setLogScale((True,False))
675
                 self.graphCtrl.setLogScale((True,False))
676
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line,markers, filterLine1, filterLine2], title, "Freq (Hz)", "Acc"), xAxis=(20,500), yAxis= (0,y))
676
                 self.graphCtrl.Draw(wx.lib.plot.PlotGraphics([line,markers, filterLine1, filterLine2], title, "Freq (Hz)", "Acc"), xAxis=(20,500), yAxis= (0,y))
677
                 self.graphCtrl.SetEnableGrid(True)
677
                 self.graphCtrl.SetEnableGrid(True)
678
                 self.graphCtrl.SetEnableLegend(False)
678
                 self.graphCtrl.SetEnableLegend(False)
679
                 
679
                 
680
 
680
 
681
 
681
 
682
    def OnImport(self, event): # wxGlade: MainFrame.<event_handler>
682
    def OnImport(self, event): # wxGlade: MainFrame.<event_handler>
683
        dlg = wx.FileDialog(
683
        dlg = wx.FileDialog(
684
            self, message="Choose a file",
684
            self, message="Choose a file",
685
            defaultDir="%s/Data/" % os.getcwd(),
685
            defaultDir="%s/Data/" % os.getcwd(),
686
            defaultFile=".",
686
            defaultFile=".",
687
            wildcard="Text files (*.txt)|*.txt|All files (*.*)|*.*",
687
            wildcard="Text files (*.txt)|*.txt|All files (*.*)|*.*",
688
            style=wx.OPEN | wx.CHANGE_DIR
688
            style=wx.OPEN | wx.CHANGE_DIR
689
            )
689
            )
690
        if dlg.ShowModal() == wx.ID_OK:
690
        if dlg.ShowModal() == wx.ID_OK:
691
            paths = dlg.GetPaths();
691
            paths = dlg.GetPaths();
692
            self.app.loadTests(paths[0])
692
            self.app.loadTests(paths[0])
693
        dlg.Destroy()
693
        dlg.Destroy()
694
 
694
 
695
    def onExport(self, event): # wxGlade: MainFrame.<event_handler>
695
    def onExport(self, event): # wxGlade: MainFrame.<event_handler>
696
        dlg = wx.FileDialog(
696
        dlg = wx.FileDialog(
697
              self, message="Save file as ...",
697
              self, message="Save file as ...",
698
              defaultDir="%s/Data/" % os.getcwd(),
698
              defaultDir="%s/Data/" % os.getcwd(),
699
              defaultFile=".",
699
              defaultFile=".",
700
              wildcard="Text files (*.txt)|*.txt|All files (*.*)|*.*",
700
              wildcard="Text files (*.txt)|*.txt|All files (*.*)|*.*",
701
              style=wx.SAVE
701
              style=wx.SAVE
702
              )
702
              )
703
        if dlg.ShowModal() == wx.ID_OK:
703
        if dlg.ShowModal() == wx.ID_OK:
704
            paths = dlg.GetPaths();
704
            paths = dlg.GetPaths();
705
            self.app.saveTests(paths[0])
705
            self.app.saveTests(paths[0])
706
        dlg.Destroy()
706
        dlg.Destroy()
707
 
707
 
708
    def onYAxisChange(self, event): # wxGlade: MainFrame.<event_handler>
708
    def onYAxisChange(self, event): # wxGlade: MainFrame.<event_handler>
709
        self.drawGraph()
709
        self.drawGraph()
710
 
710
 
711
    def onGraphTypeChange(self, event): # wxGlade: MainFrame.<event_handler>
711
    def onGraphTypeChange(self, event): # wxGlade: MainFrame.<event_handler>
712
        self.drawGraph()
712
        self.drawGraph()
713
 
713
 
714
    def OnSettings(self, event): # wxGlade: MainFrame.<event_handler>
714
    def OnSettings(self, event): # wxGlade: MainFrame.<event_handler>
715
        dlg = SettingsDialog(self, -1, "Sample Dialog", size=(350, 200),
715
        dlg = SettingsDialog(self, -1, "Sample Dialog", size=(350, 200),
716
                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
716
                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
717
                         style=wx.DEFAULT_DIALOG_STYLE, # & ~wx.CLOSE_BOX
717
                         style=wx.DEFAULT_DIALOG_STYLE, # & ~wx.CLOSE_BOX
718
                         )
718
                         )
719
        dlg.CenterOnScreen()
719
        dlg.CenterOnScreen()
720
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
720
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
721
        dlg.Destroy()
721
        dlg.Destroy()
722
        self.app.onSettingsChanged(True)
722
        self.app.onSettingsChanged(True)
723
 
723
 
724
    def onStartMeasure(self, event): # wxGlade: MainFrame.<event_handler>
724
    def onStartMeasure(self, event): # wxGlade: MainFrame.<event_handler>
725
        # Collect measure parameters
725
        # Collect measure parameters
726
        mp = MeasureParameters()
726
        mp = MeasureParameters()
727
        decoding = ""
727
        decoding = ""
728
       
728
       
729
        try:
729
        try:
730
          decoding = "Description"
730
          decoding = "Description"
731
          mp.descr = self.descrCtrl.GetValue()
731
          mp.descr = self.descrCtrl.GetValue()
732
 
732
 
733
          decoding = "Motor(s)"
733
          decoding = "Motor(s)"
734
          mp.motors = map(int,self.motorsCtrl.GetValue().split(','))
734
          mp.motors = map(int,self.motorsCtrl.GetValue().split(','))
735
          for motor in mp.motors:
735
          for motor in mp.motors:
736
              if (motor<1) or (motor>MOTOR_MAX):
736
              if (motor<1) or (motor>MOTOR_MAX):
737
                  raise Exception("Motor number should be between 1 and %d" % MOTOR_MAX)
737
                  raise Exception("Motor number should be between 1 and %d" % MOTOR_MAX)
738
 
738
 
739
          decoding = "Channel(s)"
739
          decoding = "Channel(s)"
740
          mp.channels = []
740
          mp.channels = []
741
          if self.gyroYawCb.IsChecked(): mp.channels.append(0)
741
          if self.gyroYawCb.IsChecked(): mp.channels.append(0)
742
          if self.gyroRollCb.IsChecked(): mp.channels.append(1)
742
          if self.gyroRollCb.IsChecked(): mp.channels.append(1)
743
          if self.gyroNickCb.IsChecked(): mp.channels.append(2)
743
          if self.gyroNickCb.IsChecked(): mp.channels.append(2)
744
          if self.accTopCb.IsChecked(): mp.channels.append(5)
744
          if self.accTopCb.IsChecked(): mp.channels.append(5)
745
          if self.accRollCb.IsChecked(): mp.channels.append(6)
745
          if self.accRollCb.IsChecked(): mp.channels.append(6)
746
          if self.accNickCb.IsChecked(): mp.channels.append(7)
746
          if self.accNickCb.IsChecked(): mp.channels.append(7)
747
 
747
 
748
          decoding = "Speed(s)"
748
          decoding = "Speed(s)"
749
          mp.speeds = []
749
          mp.speeds = []
750
          for speedTxt in self.speedCtrl.GetValue().split(","):
750
          for speedTxt in self.speedCtrl.GetValue().split(","):
751
              if speedTxt.count("-") == 1:
751
              if speedTxt.count("-") == 1:
752
                  # assume from-to:step format
752
                  # assume from-to:step format
753
                  speedTxt = speedTxt.split("-")
753
                  speedTxt = speedTxt.split("-")
754
                  if len(speedTxt) != 2: raise Exception("Invalid format")
754
                  if len(speedTxt) != 2: raise Exception("Invalid format")
755
                  speedTxt[1] = speedTxt[1].split(":")
755
                  speedTxt[1] = speedTxt[1].split(":")
756
                  if len(speedTxt[1]) != 2: raise Exception("Invalid format")
756
                  if len(speedTxt[1]) != 2: raise Exception("Invalid format")
757
                  mp.speeds = range(int(speedTxt[0]),int(speedTxt[1][0])+int(speedTxt[1][1]),int(speedTxt[1][1]))
757
                  mp.speeds = range(int(speedTxt[0]),int(speedTxt[1][0])+int(speedTxt[1][1]),int(speedTxt[1][1]))
758
              else:
758
              else:
759
                  # assume s or s*n format
759
                  # assume s or s*n format
760
                  if speedTxt.count("*") == 1:
760
                  if speedTxt.count("*") == 1:
761
                      speedTxt = speedTxt.split("*")
761
                      speedTxt = speedTxt.split("*")
762
                      for i in range(int(speedTxt[0])):
762
                      for i in range(int(speedTxt[0])):
763
                        mp.speeds.append(int(speedTxt[1]))
763
                        mp.speeds.append(int(speedTxt[1]))
764
                  else:
764
                  else:
765
                      mp.speeds.append(int(speedTxt))
765
                      mp.speeds.append(int(speedTxt))
766
          for speed in mp.speeds:
766
          for speed in mp.speeds:
767
                if (speed<0) or (speed>255):
767
                if (speed<0) or (speed>255):
768
                    raise Exception("Speed values should be between 0 and 255")
768
                    raise Exception("Speed values should be between 0 and 255")
769
 
769
 
770
        except Exception,e:
770
        except Exception,e:
771
          dial = wx.MessageDialog(None, 'Invalid paramter \"%s\"\n\n%s' % (decoding, str(e)), 'Error', wx.OK |
771
          dial = wx.MessageDialog(None, 'Invalid paramter \"%s\"\n\n%s' % (decoding, str(e)), 'Error', wx.OK |
772
            wx.ICON_ERROR)
772
            wx.ICON_ERROR)
773
          dial.ShowModal()
773
          dial.ShowModal()
774
          raise e
774
          raise e
775
 
775
 
776
         
776
         
777
           
777
           
778
        print mp.descr
778
        print mp.descr
779
        print mp.motors
779
        print mp.motors
780
        print mp.channels
780
        print mp.channels
781
        print mp.speeds
781
        print mp.speeds
782
       
782
       
783
           
783
           
784
       
784
       
785
        # create the dialog that will show the satus
785
        # create the dialog that will show the satus
786
        dlg = MeasureDialog(self)
786
        dlg = MeasureDialog(self)
787
        dlg.CenterOnScreen()
787
        dlg.CenterOnScreen()
788
       
788
       
789
        # Signal the application
789
        # Signal the application
790
        self.app.startMeasure(mp, dlg)
790
        self.app.startMeasure(mp, dlg)
791
       
791
       
792
        # Show the dialog
792
        # Show the dialog
793
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
793
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
794
        dlg.Destroy()
794
        dlg.Destroy()
795
 
795
 
796
    def _removeTest(self, idx):
796
    def _removeTest(self, idx):
797
        print "Deleting test %d" % idx
797
        print "Deleting test %d" % idx
798
        self.app.removeTest(idx)
798
        self.app.removeTest(idx)
799
        self.TestListCtrl.DeleteItem(idx)
799
        self.TestListCtrl.DeleteItem(idx)
800
       
800
       
801
           
801
           
802
    def onClear(self, event): # wxGlade: MainFrame.<event_handler>
802
    def onClear(self, event): # wxGlade: MainFrame.<event_handler>
803
        dial = wx.MessageDialog(None, 'Clear ALL tests?', 'Question',
803
        dial = wx.MessageDialog(None, 'Clear ALL tests?', 'Question',
804
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
804
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
805
        if dial.ShowModal() == wx.ID_YES:
805
        if dial.ShowModal() == wx.ID_YES:
806
          print "Clear all tests"
806
          print "Clear all tests"
807
          for i in range(len(self.app.VibTests)-1, -1, -1):
807
          for i in range(len(self.app.VibTests)-1, -1, -1):
808
              self._removeTest(i)
808
              self._removeTest(i)
809
          self.drawGraph()
809
          self.drawGraph()
810
           
810
           
811
       
811
       
812
    def onClearSelected(self, event): # wxGlade: MainFrame.<event_handler>
812
    def onClearSelected(self, event): # wxGlade: MainFrame.<event_handler>
813
        dial = wx.MessageDialog(None, 'Clear Selected tests?', 'Question',
813
        dial = wx.MessageDialog(None, 'Clear Selected tests?', 'Question',
814
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
814
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
815
        if dial.ShowModal() == wx.ID_YES:
815
        if dial.ShowModal() == wx.ID_YES:
816
          while True:
816
          while True:
817
              idx = self.TestListCtrl.GetFirstSelected()
817
              idx = self.TestListCtrl.GetFirstSelected()
818
              if idx == -1: break
818
              if idx == -1: break
819
              self._removeTest(idx)
819
              self._removeTest(idx)
820
           
820
           
821
       
821
       
822
 
822
 
823
    def onAbout(self, event): # wxGlade: MainFrame.<event_handler>
823
    def onAbout(self, event): # wxGlade: MainFrame.<event_handler>
824
         # First we create and fill the info object
824
         # First we create and fill the info object
825
        print "about"
825
        print "about"
826
        info = wx.AboutDialogInfo()
826
        info = wx.AboutDialogInfo()
827
        info.Name = "MK Vibration Test - "
827
        info.Name = "MK Vibration Test - "
828
        info.Version = "v1.2 ($Rev: 701 $)".replace("$","")
828
        info.Version = "v1.2 ($Rev: 721 $)".replace("$","")
829
        info.Copyright = ""
829
        info.Copyright = ""
830
        info.Developers=["Frederic Goddeeris  (Frederic@rc-flight.be)"]
830
        info.Developers=["Frederic Goddeeris  (Frederic@rc-flight.be)"]
831
        info.Description = "Please consult the WIKI page for a complete description of the tool:"
831
        info.Description = "Please consult the WIKI page for a complete description of the tool:"
832
        info.WebSite = ("http://www.mikrokopter.de/ucwiki/en/VibrationTest", "VibrationTest WIKI page")
832
        info.WebSite = ("http://www.mikrokopter.de/ucwiki/en/VibrationTest", "VibrationTest WIKI page")
833
        wx.AboutBox(info)
833
        wx.AboutBox(info)
834
       
834
       
835
       
835
       
836
    def onExit(self, event): # wxGlade: MainFrame.<event_handler>
836
    def onExit(self, event): # wxGlade: MainFrame.<event_handler>
837
        self.Close(True)
837
        self.Close(True)
838
 
838
 
839
 
839
 
840
    def onSelectAll(self, event): # wxGlade: MainFrame.<event_handler>
840
    def onSelectAll(self, event): # wxGlade: MainFrame.<event_handler>
841
        for i in xrange(self.TestListCtrl.GetItemCount()):
841
        for i in xrange(self.TestListCtrl.GetItemCount()):
842
          self.TestListCtrl.Select(i)
842
          self.TestListCtrl.Select(i)
843
 
843
 
844
    def onCopyGraphData(self, event): # wxGlade: MainFrame.<event_handler>
844
    def onCopyGraphData(self, event): # wxGlade: MainFrame.<event_handler>
845
        clipdata = wx.TextDataObject()
845
        clipdata = wx.TextDataObject()
846
        txt = ""
846
        txt = ""
847
        idx = self.TestListCtrl.GetFirstSelected()
847
        idx = self.TestListCtrl.GetFirstSelected()
848
        while idx != -1:
848
        while idx != -1:
849
             txt += ("%d\n" % self.app.getTest(idx).getVibValue())
849
             txt += ("%d\n" % self.app.getTest(idx).getVibValue())
850
             idx = self.TestListCtrl.GetNextSelected(idx)
850
             idx = self.TestListCtrl.GetNextSelected(idx)
851
        clipdata.SetText(txt)
851
        clipdata.SetText(txt)
852
        wx.TheClipboard.Open()
852
        wx.TheClipboard.Open()
853
        wx.TheClipboard.SetData(clipdata)
853
        wx.TheClipboard.SetData(clipdata)
854
        wx.TheClipboard.Close()
854
        wx.TheClipboard.Close()
855
 
855
 
856
# end of class MainFrame
856
# end of class MainFrame
857
 
857
 
858
class Setting:
858
class Setting:
859
    def __init__(self, descr, defaultValue):
859
    def __init__(self, descr, defaultValue):
860
        self.descr = descr
860
        self.descr = descr
861
        self.value = defaultValue
861
        self.value = defaultValue
862
       
862
       
863
    def set(self, newValue):
863
    def set(self, newValue):
864
        if isinstance(self.value, int):
864
        if isinstance(self.value, int):
865
            self.value = int(newValue)
865
            self.value = int(newValue)
866
        else:
866
        else:
867
            self.value = str(newValue)
867
            self.value = str(newValue)
868
 
868
 
869
class MeasureParameters:
869
class MeasureParameters:
870
      pass
870
      pass
871
 
871
 
872
class MeasureThread:
872
class MeasureThread:
873
    def __init__(self, measureParameters, evtConsumer):
873
    def __init__(self, measureParameters, evtConsumer):
874
        self.mk = MkProtocol.MkComm()
874
        self.mk = MkProtocol.MkComm()
875
        self.param = measureParameters
875
        self.param = measureParameters
876
        self.evtConsumer = evtConsumer
876
        self.evtConsumer = evtConsumer
877
        self.cancel = False
877
        self.cancel = False
878
        self.running = False
878
        self.running = False
879
       
879
       
880
    def start(self):
880
    def start(self):
881
        thread.start_new_thread(self._run, ())
881
        thread.start_new_thread(self._run, ())
882
       
882
       
883
    def stop(self):
883
    def stop(self):
884
        self.cancel = True
884
        self.cancel = True
885
 
885
 
886
    def _testCancel(self):
886
    def _testCancel(self):
887
        if self.cancel:
887
        if self.cancel:
888
            raise Exception("Operation cancelled")
888
            raise Exception("Operation cancelled")
889
               
889
               
890
    def _sendEvent(self, msg=None, error=False, parVoltage=None, speed=None):
890
    def _sendEvent(self, msg=None, error=False, parVoltage=None, speed=None):
891
        evt = MeasStatusUpdateEvent(running=self.running, msg=msg, error=error, voltage=parVoltage, speed=speed)
891
        evt = MeasStatusUpdateEvent(running=self.running, msg=msg, error=error, voltage=parVoltage, speed=speed)
892
        wx.PostEvent(self.evtConsumer, evt)
892
        wx.PostEvent(self.evtConsumer, evt)
893
 
893
 
894
    def _setMotorSpeed(self, speed, settlingTime):
894
    def _setMotorSpeed(self, speed, settlingTime):
895
        speeds = [0]*MOTOR_MAX
895
        speeds = [0]*MOTOR_MAX
896
       
896
       
897
        for motor in self.param.motors:
897
        for motor in self.param.motors:
898
            speeds[motor-1] = speed
898
            speeds[motor-1] = speed
899
        for i in range(int(settlingTime*10)):
899
        for i in range(int(settlingTime*10)):
900
          self._testCancel()
900
          self._testCancel()
901
          self.mk.setMotorTest(speeds)
901
          self.mk.setMotorTest(speeds)
902
          time.sleep(.1)
902
          time.sleep(.1)
903
        self.currSpeed = speed
903
        self.currSpeed = speed
904
       
904
       
905
                   
905
                   
906
    def _run(self):
906
    def _run(self):
907
        self.running = True
907
        self.running = True
908
        self._sendEvent("Starting test \"%s\"" % self.param.descr)    
908
        self._sendEvent("Starting test \"%s\"" % self.param.descr)    
909
        self.currSpeed = 0
909
        self.currSpeed = 0
910
       
910
       
911
        try:
911
        try:
912
            self._sendEvent("Opening SerialPort \"%s\"" % self.param.serialPort)
912
            self._sendEvent("Opening SerialPort \"%s\"" % self.param.serialPort)
913
            self.mk.open(comPort=self.param.serialPort)
913
            self.mk.open(comPort=self.param.serialPort)
914
           
914
           
915
            print "Sending FC->NC forwarding",
915
            print "Sending FC->NC forwarding",
916
            self.mk.sendNCRedirectUartFromFC()
916
            self.mk.sendNCRedirectUartFromFC()
917
            print "Done"
917
            print "Done"
918
               
918
               
919
            msg = self.mk.getVersionMsg()
919
            msg = self.mk.getVersionMsg()
920
            version = msg.getVersion()
920
            version = msg.getVersion()
921
            self._sendEvent("Version: %d.%d" % version)
921
            self._sendEvent("Version: %d.%d" % version)
922
           
922
           
923
            msg = self.mk.getDebugMsg()
923
            msg = self.mk.getDebugMsg()
924
            voltage = msg.getVoltage()
924
            voltage = msg.getVoltage()
925
            if (voltage == 0):
925
            if (voltage == 0):
926
              # Board is probably fed by USB
926
              # Board is probably fed by USB
927
              minVoltage = 0
927
              minVoltage = 0
928
              maxVoltage = 1
928
              maxVoltage = 1
929
            else:
929
            else:
930
              # Determine the n umber of cells
930
              # Determine the n umber of cells
931
              if (voltage > 4.2*3):
931
              if (voltage > 4.2*3):
932
                nbCells = 4  
932
                nbCells = 4  
933
              else:
933
              else:
934
                nbCells = 3
934
                nbCells = 3
935
              # Set minimum and maximum voltages
935
              # Set minimum and maximum voltages
936
              if self.param.minVoltage > 0:
936
              if self.param.minVoltage > 0:
937
                minVoltage =  self.param.minVoltage
937
                minVoltage =  self.param.minVoltage
938
              else:
938
              else:
939
                minVoltage = nbCells*3.5  # auto
939
                minVoltage = nbCells*3.5  # auto
940
              if self.param.maxVoltage > 0:
940
              if self.param.maxVoltage > 0:
941
                maxVoltage =  self.param.maxVoltage
941
                maxVoltage =  self.param.maxVoltage
942
              else:
942
              else:
943
                maxVoltage = nbCells*3.9  
943
                maxVoltage = nbCells*3.9  
944
               
944
               
945
            self._sendEvent("Voltage: %2.1fV" % voltage)
945
            self._sendEvent("Voltage: %2.1fV" % voltage)
946
            self._sendEvent("Min/Max Voltage: %2.1fV-%2.1fV" % (minVoltage, maxVoltage), parVoltage=(minVoltage, maxVoltage, voltage))
946
            self._sendEvent("Min/Max Voltage: %2.1fV-%2.1fV" % (minVoltage, maxVoltage), parVoltage=(minVoltage, maxVoltage, voltage))
947
           
947
           
948
            self._sendEvent("Starting motor(s) (speed=%d)... " % self.param.motorStartupSpeed, speed=self.param.motorStartupSpeed)
948
            self._sendEvent("Starting motor(s) (speed=%d)... " % self.param.motorStartupSpeed, speed=self.param.motorStartupSpeed)
949
            self._setMotorSpeed(self.param.motorStartupSpeed, self.param.motorStartupSettlingTime)
949
            self._setMotorSpeed(self.param.motorStartupSpeed, self.param.motorStartupSettlingTime)
950
         
950
         
951
            for speed in self.param.speeds:
951
            for speed in self.param.speeds:
952
                if speed != self.currSpeed:
952
                if speed != self.currSpeed:
953
                    self._sendEvent("Changing motor speed to %d... " % speed, speed=speed)
953
                    self._sendEvent("Changing motor speed to %d... " % speed, speed=speed)
954
                    self._setMotorSpeed(speed, 1)
954
                    self._setMotorSpeed(speed, 1)
955
               
955
               
956
                for channel in self.param.channels:
956
                for channel in self.param.channels:
957
                    self._setMotorSpeed(speed, .1)
957
                    self._setMotorSpeed(speed, .1)
958
                    msg = self.mk.getDebugMsg()
958
                    msg = self.mk.getDebugMsg()
959
                    voltage = msg.getVoltage()
959
                    voltage = msg.getVoltage()
960
           
960
           
961
                    self._sendEvent("Getting data from channel %s" % CHANNEL_NAMES[channel], parVoltage=(minVoltage, maxVoltage, voltage))
961
                    self._sendEvent("Getting data from channel %s" % CHANNEL_NAMES[channel], parVoltage=(minVoltage, maxVoltage, voltage))
962
                    data = self.mk.doVibrationTest(1000, channel)
962
                    data = self.mk.doVibrationTest(1000, channel)
963
                   
963
                   
964
                    vt = VibTest(self.param.descr, voltage, self.param.motors, speed, CHANNEL_NAMES[channel], data)
964
                    vt = VibTest(self.param.descr, voltage, self.param.motors, speed, CHANNEL_NAMES[channel], data)
965
                    evt = MeasDataEvent(vibTest = vt)
965
                    evt = MeasDataEvent(vibTest = vt)
966
                    wx.PostEvent(self.evtConsumer, evt)
966
                    wx.PostEvent(self.evtConsumer, evt)
967
                   
967
                   
968
                    if voltage<minVoltage:
968
                    if voltage<minVoltage:
969
                        raise Exception("Voltage too low")
969
                        raise Exception("Voltage too low")
970
           
970
           
971
           
971
           
972
            self._setMotorSpeed(speed, .1)    
972
            self._setMotorSpeed(speed, .1)    
973
            time.sleep(1)
973
            time.sleep(1)
974
            msg = self.mk.getDebugMsg()
974
            msg = self.mk.getDebugMsg()
975
            voltage = msg.getVoltage()
975
            voltage = msg.getVoltage()
976
           
976
           
977
            self._sendEvent("Done !", parVoltage=(minVoltage, maxVoltage, voltage))            
977
            self._sendEvent("Done !", parVoltage=(minVoltage, maxVoltage, voltage))            
978
           
978
           
979
        except Exception, e:
979
        except Exception, e:
980
            self._sendEvent("Exception \"%s\"" % e, error=True)  
980
            self._sendEvent("Exception \"%s\"" % e, error=True)  
981
       
981
       
982
        try:        
982
        try:        
983
          self.mk.close()
983
          self.mk.close()
984
        except:
984
        except:
985
          print "Failure closing MK serial port"
985
          print "Failure closing MK serial port"
986
          pass
986
          pass
987
       
987
       
988
        self.running = False
988
        self.running = False
989
        self._sendEvent("", speed = 0)    
989
        self._sendEvent("", speed = 0)    
990
       
990
       
991
 
991
 
992
class VibTest:
992
class VibTest:
993
    useRms = True
993
    useRms = True
994
    fc1 = None
994
    fc1 = None
995
    fc2 = None
995
    fc2 = None
996
       
996
       
997
   
997
   
998
    def __init__(self, descr, voltage, motor, speed, channel, rawData):
998
    def __init__(self, descr, voltage, motor, speed, channel, rawData):
999
        self.descr = descr
999
        self.descr = descr
1000
        self.voltage = voltage
1000
        self.voltage = voltage
1001
        self.motor = motor
1001
        self.motor = motor
1002
        self.speed = speed
1002
        self.speed = speed
1003
        self.channel = channel
1003
        self.channel = channel
1004
 
1004
 
1005
        self.dataLen = len(rawData)
1005
        self.dataLen = len(rawData)
1006
 
1006
 
1007
        self.rawData = _Numeric.array(rawData)
1007
        self.rawData = _Numeric.array(rawData)
1008
        self.dc = self.rawData.mean()
1008
        self.dc = self.rawData.mean()
1009
        self.rawData -= self.dc
1009
        self.rawData -= self.dc
1010
 
1010
 
1011
        self.fft = _Numeric.fft.rfft(self.rawData)
1011
        self.fft = _Numeric.fft.rfft(self.rawData)
1012
 
1012
 
1013
        self.spectrum = None
1013
        self.spectrum = None
1014
        self.filteredData = None
1014
        self.filteredData = None
1015
       
1015
       
1016
        self.vibValue = None
1016
        self.vibValue = None
1017
       
1017
       
1018
    def getDescr(self):
1018
    def getDescr(self):
1019
        return self.Descr
1019
        return self.Descr
1020
 
1020
 
1021
    def getRawData(self):
1021
    def getRawData(self):
1022
        return self.rawData
1022
        return self.rawData
1023
 
1023
 
1024
    def getDataLen(self):
1024
    def getDataLen(self):
1025
        return self.dataLen
1025
        return self.dataLen
1026
 
1026
 
1027
    def getSpectrum(self):
1027
    def getSpectrum(self):
1028
        if self.spectrum == None:
1028
        if self.spectrum == None:
1029
            self.spectrum = _Numeric.absolute(self.fft[1:self.dataLen/2+1]) / (self.dataLen/2)
1029
            self.spectrum = _Numeric.absolute(self.fft[1:self.dataLen/2+1]) / (self.dataLen/2)
1030
        return self.spectrum
1030
        return self.spectrum
1031
       
1031
       
1032
    def refresh(self):
1032
    def refresh(self):
1033
        self.filteredData = None
1033
        self.filteredData = None
1034
        self.vibValue = None
1034
        self.vibValue = None
1035
 
1035
 
1036
    def getFilteredData(self):
1036
    def getFilteredData(self):
1037
        if self.filteredData == None:
1037
        if self.filteredData == None:
1038
            tmpfft = self.fft.copy()
1038
            tmpfft = self.fft.copy()
1039
            fc = (float(self.fc1))/(FS/2)*len(tmpfft)
1039
            fc = (float(self.fc1))/(FS/2)*len(tmpfft)
1040
            print "fc1=%d => fc=%f" % (self.fc1, fc)
1040
            print "fc1=%d => fc=%f" % (self.fc1, fc)
1041
            for i in range(0,int(fc)+2):
1041
            for i in range(0,int(fc)+2):
1042
                tmpfft[i] = 0
1042
                tmpfft[i] = 0
1043
            fc = (float(self.fc2))/(FS/2)*len(tmpfft)
1043
            fc = (float(self.fc2))/(FS/2)*len(tmpfft)
1044
            print "fc2=%d => fc=%f" % (self.fc2,fc)
1044
            print "fc2=%d => fc=%f" % (self.fc2,fc)
1045
            for i in range(int(fc)+2, len(tmpfft)):
1045
            for i in range(int(fc)+2, len(tmpfft)):
1046
                tmpfft[i] = 0
1046
                tmpfft[i] = 0
1047
            self.filteredData = _Numeric.fft.irfft(tmpfft)
1047
            self.filteredData = _Numeric.fft.irfft(tmpfft)
1048
           
1048
           
1049
        return self.filteredData
1049
        return self.filteredData
1050
       
1050
       
1051
    def getVibValue(self):
1051
    def getVibValue(self):
1052
      if self.vibValue == None:
1052
      if self.vibValue == None:
1053
        fd = self.getFilteredData()[100:-100];
1053
        fd = self.getFilteredData()[100:-100];
1054
        if self.useRms:
1054
        if self.useRms:
1055
            print "RMS"
1055
            print "RMS"
1056
            self.vibValue = math.sqrt(sum([x*x for x in fd])/len(fd))*2*math.sqrt(2)
1056
            self.vibValue = math.sqrt(sum([x*x for x in fd])/len(fd))*2*math.sqrt(2)
1057
        else:
1057
        else:
1058
            print "PP"
1058
            print "PP"
1059
            self.vibValue = max(fd)-min(fd)
1059
            self.vibValue = max(fd)-min(fd)
1060
      return self.vibValue
1060
      return self.vibValue
1061
 
1061
 
1062
 
1062
 
1063
 
1063
 
1064
class App(wx.App):
1064
class App(wx.App):
1065
 
1065
 
1066
    SETTINGSFILE = "settings.cfg"
1066
    SETTINGSFILE = "settings.cfg"
1067
 
1067
 
1068
    def __init__(self, par):
1068
    def __init__(self, par):
1069
        self.VibTests = []
1069
        self.VibTests = []
1070
        wx.App.__init__(self, par)
1070
        wx.App.__init__(self, par)
1071
 
1071
 
1072
        # Init settings
1072
        # Init settings
1073
        self.settings={}
1073
        self.settings={}
1074
        self.settings["serialport"] = Setting("Serial Port", "COM1")
1074
        self.settings["serialport"] = Setting("Serial Port", "COM1")
1075
        self.settings["startupspeed"] = Setting("Motor Startup Speed", 25)
1075
        self.settings["startupspeed"] = Setting("Motor Startup Speed", 25)
1076
        self.settings["startupsettling"] = Setting("Motor Startup Setting time (s)", 3)
1076
        self.settings["startupsettling"] = Setting("Motor Startup Setting time (s)", 3)
1077
        self.settings["serialport"] = Setting("Serial Port", "COM1")
1077
        self.settings["serialport"] = Setting("Serial Port", "COM1")
1078
        self.settings["hpf"] = Setting("HP Filter cutoff (Hz)", 40)
1078
        self.settings["hpf"] = Setting("HP Filter cutoff (Hz)", 40)
1079
        self.settings["lpf"] = Setting("LP Filter cutoff (Hz)", 400)
1079
        self.settings["lpf"] = Setting("LP Filter cutoff (Hz)", 400)
1080
        self.settings["calcmethod"] = Setting("Calculation Method", "rms")        
1080
        self.settings["calcmethod"] = Setting("Calculation Method", "rms")        
1081
        self.settings["minvoltage"] = Setting("Minimum Bettery Voltage (0=Automatic) (V) ", 0)
1081
        self.settings["minvoltage"] = Setting("Minimum Bettery Voltage (0=Automatic) (V) ", 0)
1082
        self.settings["maxvoltage"] = Setting("Maximum Bettery Voltage (0=Automatic) (V) ", 0)
1082
        self.settings["maxvoltage"] = Setting("Maximum Bettery Voltage (0=Automatic) (V) ", 0)
1083
 
1083
 
1084
 
1084
 
1085
        self.readSettings()
1085
        self.readSettings()
1086
 
1086
 
1087
        if len(sys.argv)>1:
1087
        if len(sys.argv)>1:
1088
            self.loadTests(sys.argv[1])
1088
            self.loadTests(sys.argv[1])
1089
 
1089
 
1090
 
1090
 
1091
    def readSettings(self):
1091
    def readSettings(self):
1092
        print "Reading settings"
1092
        print "Reading settings"
1093
        cp = ConfigParser.ConfigParser()
1093
        cp = ConfigParser.ConfigParser()
1094
 
1094
 
1095
        try:
1095
        try:
1096
            cp.read("%s/%s" % (rootPath, App.SETTINGSFILE))
1096
            cp.read("%s/%s" % (rootPath, App.SETTINGSFILE))
1097
            for setting in cp.items("DEFAULT"):
1097
            for setting in cp.items("DEFAULT"):
1098
                print " ",setting
1098
                print " ",setting
1099
                try:
1099
                try:
1100
                    self.settings[setting[0]].set(setting[1])
1100
                    self.settings[setting[0]].set(setting[1])
1101
                except:
1101
                except:
1102
                    print "WARNING, unknown setting"
1102
                    print "WARNING, unknown setting"
1103
        except:
1103
        except:
1104
            print "ERROR reading settingsfile"
1104
            print "ERROR reading settingsfile"
1105
        self.onSettingsChanged(False)
1105
        self.onSettingsChanged(False)
1106
 
1106
 
1107
    def storeSettings(self):
1107
    def storeSettings(self):
1108
        print "Storing settings"
1108
        print "Storing settings"
1109
 
1109
 
1110
        cp = ConfigParser.ConfigParser()
1110
        cp = ConfigParser.ConfigParser()
1111
        for setting in self.settings.iteritems():
1111
        for setting in self.settings.iteritems():
1112
            cp.set("", setting[0], setting[1].value)
1112
            cp.set("", setting[0], setting[1].value)
1113
 
1113
 
1114
        file = open("%s/%s" % (rootPath, App.SETTINGSFILE), "w")
1114
        file = open("%s/%s" % (rootPath, App.SETTINGSFILE), "w")
1115
        cp.write(file)
1115
        cp.write(file)
1116
        file.close()
1116
        file.close()
1117
 
1117
 
1118
 
1118
 
1119
    def onSettingsChanged(self, store):
1119
    def onSettingsChanged(self, store):
1120
        if store:
1120
        if store:
1121
            self.storeSettings()
1121
            self.storeSettings()
1122
           
1122
           
1123
        if self.settings["calcmethod"].value == "rms":
1123
        if self.settings["calcmethod"].value == "rms":
1124
            VibTest.useRms = True
1124
            VibTest.useRms = True
1125
        else:
1125
        else:
1126
            VibTest.useRms = False
1126
            VibTest.useRms = False
1127
           
1127
           
1128
        VibTest.fc1 = self.settings["hpf"].value
1128
        VibTest.fc1 = self.settings["hpf"].value
1129
        VibTest.fc2 = self.settings["lpf"].value
1129
        VibTest.fc2 = self.settings["lpf"].value
1130
       
1130
       
1131
        for test in self.VibTests:
1131
        for test in self.VibTests:
1132
            test.refresh()
1132
            test.refresh()
1133
        self.frame_1.refreshData()
1133
        self.frame_1.refreshData()
1134
     
1134
     
1135
    def AddTest2(self, vibTest):
1135
    def AddTest2(self, vibTest):
1136
        self.VibTests.append(vibTest)
1136
        self.VibTests.append(vibTest)
1137
        self.frame_1.onNewTest(vibTest)
1137
        self.frame_1.onNewTest(vibTest)
1138
         
1138
         
1139
    def AddTest(self, descr, voltage, motor, speed, channel, rawData):
1139
    def AddTest(self, descr, voltage, motor, speed, channel, rawData):
1140
        test = VibTest(descr, voltage, motor, speed, channel, rawData)
1140
        test = VibTest(descr, voltage, motor, speed, channel, rawData)
1141
        self.AddTest2(test)
1141
        self.AddTest2(test)
1142
 
1142
 
1143
    def removeTest(self, idx):
1143
    def removeTest(self, idx):
1144
        del(self.VibTests[idx])
1144
        del(self.VibTests[idx])
1145
   
1145
   
1146
    def getTest(self, testId):
1146
    def getTest(self, testId):
1147
        return self.VibTests[testId]
1147
        return self.VibTests[testId]
1148
 
1148
 
1149
    def OnInit(self):
1149
    def OnInit(self):
1150
        wx.InitAllImageHandlers()
1150
        wx.InitAllImageHandlers()
1151
        self.frame_1 = MainFrame(None, -1, "")
1151
        self.frame_1 = MainFrame(None, -1, "")
1152
        self.frame_1.setApp(self);
1152
        self.frame_1.setApp(self);
1153
        self.SetTopWindow(self.frame_1)
1153
        self.SetTopWindow(self.frame_1)
1154
 
1154
 
1155
        self.frame_1.CenterOnScreen()
1155
        self.frame_1.CenterOnScreen()
1156
        self.frame_1.Show()
1156
        self.frame_1.Show()
1157
        return 1
1157
        return 1
1158
 
1158
 
1159
    def saveTests(self, filePath):
1159
    def saveTests(self, filePath):
1160
        try:
1160
        try:
1161
          logfile = open(filePath, "r")
1161
          logfile = open(filePath, "r")
1162
          newFile = False
1162
          newFile = False
1163
          logfile.close()
1163
          logfile.close()
1164
        except:
1164
        except:
1165
          newFile = True
1165
          newFile = True
1166
         
1166
         
1167
        for test in self.VibTests:
1167
        for test in self.VibTests:
1168
          if newFile:
1168
          if newFile:
1169
            logfile = open(filePath, "w")
1169
            logfile = open(filePath, "w")
1170
            print "Writing result to %s ..." % filePath,
1170
            print "Writing result to %s ..." % filePath,
1171
            logfile.write("%s %d %s\n" % (test.descr, test.speed, test.channel))
1171
            logfile.write("%s %d %s\n" % (test.descr, test.speed, test.channel))
1172
            for value in test.rawData:
1172
            for value in test.rawData:
1173
              logfile.write("%d\n" % value)
1173
              logfile.write("%d\n" % value)
1174
            logfile.close()  
1174
            logfile.close()  
1175
            print "OK"
1175
            print "OK"
1176
          else:
1176
          else:
1177
            print "Appending result to %s ..." % filePath,
1177
            print "Appending result to %s ..." % filePath,
1178
            logfile = open(filePath, "r")
1178
            logfile = open(filePath, "r")
1179
            prevData = []
1179
            prevData = []
1180
            for line in logfile:
1180
            for line in logfile:
1181
              prevData.append(line[:-1])
1181
              prevData.append(line[:-1])
1182
            logfile.close()
1182
            logfile.close()
1183
            logfile = open(filePath, "w")
1183
            logfile = open(filePath, "w")
1184
            logfile.write("%s,%s %d %s\n" % (prevData[0], test.descr, test.speed, test.channel))
1184
            logfile.write("%s,%s %d %s\n" % (prevData[0], test.descr, test.speed, test.channel))
1185
            i = 1
1185
            i = 1
1186
            for value in test.rawData:
1186
            for value in test.rawData:
1187
              logfile.write("%s,%d\n" % (prevData[i], value))
1187
              logfile.write("%s,%d\n" % (prevData[i], value))
1188
              i += 1
1188
              i += 1
1189
            logfile.close()
1189
            logfile.close()
1190
            print "OK"
1190
            print "OK"
1191
          newFile = False
1191
          newFile = False
1192
           
1192
           
1193
           
1193
           
1194
    def loadTests(self, filePath):
1194
    def loadTests(self, filePath):
1195
       
1195
       
1196
        print "Importing file \"%s\"" % filePath
1196
        print "Importing file \"%s\"" % filePath
1197
 
1197
 
1198
        logfile = open(filePath, "r")
1198
        logfile = open(filePath, "r")
1199
        data = None
1199
        data = None
1200
 
1200
 
1201
        headers = (logfile.readline()[:-1]).split(',')
1201
        headers = (logfile.readline()[:-1]).split(',')
1202
        nbCols = len(headers)
1202
        nbCols = len(headers)
1203
        print "NbCols =", nbCols
1203
        print "NbCols =", nbCols
1204
 
1204
 
1205
        data = []
1205
        data = []
1206
        descr = []
1206
        descr = []
1207
        speed = []
1207
        speed = []
1208
        channel = []
1208
        channel = []
1209
        for c in range(nbCols):
1209
        for c in range(nbCols):
1210
            data.append([])
1210
            data.append([])
1211
            h = headers[c].split(' ')
1211
            h = headers[c].split(' ')
1212
            descr.append(h[0]);
1212
            descr.append(h[0]);
1213
            speed.append(h[1]);
1213
            speed.append(h[1]);
1214
            channel.append(h[2]);
1214
            channel.append(h[2]);
1215
 
1215
 
1216
        for line in logfile:
1216
        for line in logfile:
1217
            values = line.split(',')
1217
            values = line.split(',')
1218
            for i in range(nbCols):
1218
            for i in range(nbCols):
1219
                data[i].append(int(values[i]))
1219
                data[i].append(int(values[i]))
1220
        logfile.close()
1220
        logfile.close()
1221
 
1221
 
1222
        for c in range(nbCols):
1222
        for c in range(nbCols):
1223
            if (len(data[c]) % 2) != 0:
1223
            if (len(data[c]) % 2) != 0:
1224
                data[c].append(data[c][-1])
1224
                data[c].append(data[c][-1])
1225
            self.AddTest(descr[c], 0, 0, int(speed[c]), channel[c], data[c])
1225
            self.AddTest(descr[c], 0, 0, int(speed[c]), channel[c], data[c])
1226
           
1226
           
1227
    def startMeasure(self, measureParams, dialog):
1227
    def startMeasure(self, measureParams, dialog):
1228
        print "Start measuring"
1228
        print "Start measuring"
1229
       
1229
       
1230
        measureParams.serialPort = self.settings["serialport"].value
1230
        measureParams.serialPort = self.settings["serialport"].value
1231
        measureParams.motorStartupSpeed = self.settings["startupspeed"].value
1231
        measureParams.motorStartupSpeed = self.settings["startupspeed"].value
1232
        measureParams.motorStartupSettlingTime = self.settings["startupsettling"].value
1232
        measureParams.motorStartupSettlingTime = self.settings["startupsettling"].value
1233
        measureParams.minVoltage = self.settings["minvoltage"].value
1233
        measureParams.minVoltage = self.settings["minvoltage"].value
1234
        measureParams.maxVoltage = self.settings["maxvoltage"].value        
1234
        measureParams.maxVoltage = self.settings["maxvoltage"].value        
1235
       
1235
       
1236
        self.measureThread = MeasureThread(measureParams, dialog)
1236
        self.measureThread = MeasureThread(measureParams, dialog)
1237
        self.measureThread.start()
1237
        self.measureThread.start()
1238
       
1238
       
1239
    def cancelMeasurement(self):
1239
    def cancelMeasurement(self):
1240
        print "Measuring CANCEL"
1240
        print "Measuring CANCEL"
1241
       
1241
       
1242
        self.measureThread.stop()
1242
        self.measureThread.stop()
1243
       
1243
       
1244
       
1244
       
1245
       
1245
       
1246
       
1246
       
1247
       
1247
       
1248
           
1248
           
1249
 
1249
 
1250
       
1250
       
1251
# end of class App
1251
# end of class App
1252
 
1252
 
1253
if __name__ == "__main__":
1253
if __name__ == "__main__":
1254
 
1254
 
1255
    rootPath = os.path.abspath(os.path.dirname(sys.argv[0]))
1255
    rootPath = os.path.abspath(os.path.dirname(sys.argv[0]))
1256
   
1256
   
1257
    print rootPath
1257
    print rootPath
1258
 
1258
 
1259
    VibrationTestGui = App(0)
1259
    VibrationTestGui = App(0)
1260
    VibrationTestGui.MainLoop()
1260
    VibrationTestGui.MainLoop()
1261
 
1261