Subversion Repositories Projects

Rev

Rev 615 | Rev 619 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
584 FredericG 1
#!/usr/bin/env python
2
# -*- coding: iso-8859-15 -*-
3
# generated by wxGlade 0.6.3 on Thu Sep 24 15:46:36 2009
4
 
586 FredericG 5
import sys
606 FredericG 6
import os
612 FredericG 7
import time
8
import thread
9
import ConfigParser
10
 
584 FredericG 11
import wx
585 FredericG 12
import wx.lib
13
import wx.lib.plot
612 FredericG 14
import wx.lib.newevent
584 FredericG 15
 
613 FredericG 16
import mkProto
17
 
18
 
19
 
20
CHANNEL_NAMES = ["GyroYaw", "GyroRoll", "GyroNick", "Pressure", "Batt", "AccTop", "AccRoll", "AccNick"]
615 FredericG 21
FS = 11111
613 FredericG 22
 
585 FredericG 23
# Needs Numeric or numarray or NumPy
24
try:
25
    import numpy.oldnumeric as _Numeric
26
except:
27
    try:
28
        import numarray as _Numeric  #if numarray is used it is renamed Numeric
29
    except:
30
        try:
31
            import Numeric as _Numeric
32
        except:
33
            msg= """
34
            This module requires the Numeric/numarray or NumPy module,
35
            which could not be imported.  It probably is not installed
36
            (it's not part of the standard Python distribution). See the
37
            Numeric Python site (http://numpy.scipy.org) for information on
38
            downloading source or binaries."""
39
            raise ImportError, "Numeric,numarray or NumPy not found. \n" + msg
40
 
584 FredericG 41
# begin wxGlade: extracode
42
# end wxGlade
43
 
44
 
612 FredericG 45
# This creates a new Event class and a EVT binder function
613 FredericG 46
(MeasStatusUpdateEvent, EVT_MEAS_STATUS_UPDATE) = wx.lib.newevent.NewEvent()  
47
(MeasDataEvent, EVT_MEAS_DATA) = wx.lib.newevent.NewEvent()  
584 FredericG 48
 
612 FredericG 49
class MeasureDialog(wx.Dialog):
50
    def __init__(self, *args, **kwds):
51
        # begin wxGlade: MeasureDialog.__init__
52
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME
53
        wx.Dialog.__init__(self, *args, **kwds)
54
        self.text_ctrl_1 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
55
        self.button = wx.Button(self, -1, "STOP")
56
 
57
        self.__set_properties()
58
        self.__do_layout()
59
 
60
        self.Bind(wx.EVT_BUTTON, self.onButton, self.button)
61
        # end wxGlade
62
 
63
        self.running = True
64
        self.Bind(EVT_MEAS_STATUS_UPDATE, self.OnUpdate)
613 FredericG 65
        self.Bind(EVT_MEAS_DATA, self.OnData)
66
        # The first argument that is passed to the constructor is the parent
67
        self.app = args[0].app
68
        self.error = False
612 FredericG 69
 
70
    def __set_properties(self):
71
        # begin wxGlade: MeasureDialog.__set_properties
72
        self.SetTitle("Measuring Status")
73
        self.text_ctrl_1.SetMinSize((400,300))
74
        # end wxGlade
75
 
76
    def __do_layout(self):
77
        # begin wxGlade: MeasureDialog.__do_layout
78
        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
79
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
80
        sizer_1.Add((20, 20), 0, 0, 0)
81
        sizer_2.Add((20, 20), 0, 0, 0)
82
        sizer_2.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
83
        sizer_2.Add((20, 20), 0, 0, 0)
84
        sizer_2.Add(self.button, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
85
        sizer_2.Add((20, 20), 0, 0, 0)
86
        sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
87
        sizer_1.Add((20, 20), 0, 0, 0)
88
        self.SetSizer(sizer_1)
89
        sizer_1.Fit(self)
90
        self.Layout()
91
        # end wxGlade
613 FredericG 92
 
93
    def OnData(self, evt):
94
        print "Received Data"
95
        self.app.AddTest2(evt.vibTest)
612 FredericG 96
 
97
    def OnUpdate(self, evt):
613 FredericG 98
        print "Status update"
612 FredericG 99
        self.running = evt.running
613 FredericG 100
        if evt.error:
101
            self.error = True;
102
            self.text_ctrl_1.WriteText("ERROR: ")
103
            self.text_ctrl_1.SetBackgroundColour("Red")  
612 FredericG 104
        self.text_ctrl_1.WriteText("%s\n"%evt.msg)
105
        if (not self.running):
613 FredericG 106
            if (not self.error):
107
                self.text_ctrl_1.SetBackgroundColour("Green")
108
                self.text_ctrl_1.write(" ") # so that the background is redrawn
612 FredericG 109
            self.button.SetLabel("Close")  
613 FredericG 110
 
612 FredericG 111
 
112
    def onButton(self, event): # wxGlade: MeasureDialog.<event_handler>
113
        if (not self.running):
114
            self.Destroy()
613 FredericG 115
        else:
116
            self.app.cancelMeasurement()
612 FredericG 117
 
118
# end of class MeasureDialog
119
 
120
 
607 FredericG 121
class SettingsDialog(wx.Dialog):
601 FredericG 122
    def __init__(self, *args, **kwds):
607 FredericG 123
        # begin wxGlade: SettingsDialog.__init__
124
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
125
        wx.Dialog.__init__(self, *args, **kwds)
608 FredericG 126
        self.button_5 = wx.Button(self, wx.ID_CANCEL, "")
127
        self.button_6 = wx.Button(self, wx.ID_OK, "")
601 FredericG 128
 
129
        self.__set_properties()
130
        self.__do_layout()
611 FredericG 131
 
132
        self.Bind(wx.EVT_BUTTON, self.onOK, self.button_6)
601 FredericG 133
        # end wxGlade
134
 
608 FredericG 135
        # The first argument that is passed to the constructor is the parent
611 FredericG 136
        self.settings = args[0].app.settings
608 FredericG 137
        # Add text-boxes for all settings
611 FredericG 138
        self.tb = []
139
        self.grid_sizer_2.SetRows(len(self.settings))
140
        for setting in self.settings.iteritems():
608 FredericG 141
            lb = wx.StaticText(self, -1, setting[1].descr, style=wx.ALIGN_RIGHT)
142
            tb = wx.TextCtrl(self, -1, str(setting[1].value))
143
            self.grid_sizer_2.Add(lb, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
144
            self.grid_sizer_2.Add(tb, 0, 0, 0)
611 FredericG 145
            self.tb.append(tb)
608 FredericG 146
        self.sizer_5.Fit(self)
147
        self.Layout()
148
 
601 FredericG 149
    def __set_properties(self):
607 FredericG 150
        # begin wxGlade: SettingsDialog.__set_properties
601 FredericG 151
        self.SetTitle("Settings")
152
        # end wxGlade
153
 
154
    def __do_layout(self):
607 FredericG 155
        # begin wxGlade: SettingsDialog.__do_layout
608 FredericG 156
        sizer_5 = wx.BoxSizer(wx.VERTICAL)
157
        grid_sizer_3 = wx.GridSizer(1, 2, 0, 0)
158
        sizer_6 = wx.BoxSizer(wx.HORIZONTAL)
159
        grid_sizer_2 = wx.GridSizer(1, 2, 4, 4)
160
        sizer_5.Add((20, 20), 0, 0, 0)
161
        sizer_6.Add((20, 20), 0, 0, 0)
162
        sizer_6.Add(grid_sizer_2, 0, 0, 0)
163
        sizer_6.Add((20, 20), 0, 0, 0)
164
        sizer_5.Add(sizer_6, 1, wx.EXPAND, 0)
165
        sizer_5.Add((20, 20), 0, 0, 0)
166
        grid_sizer_3.Add(self.button_5, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 0)
167
        grid_sizer_3.Add(self.button_6, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 0)
168
        sizer_5.Add(grid_sizer_3, 0, wx.EXPAND, 0)
169
        sizer_5.Add((20, 20), 0, 0, 0)
170
        self.SetSizer(sizer_5)
171
        sizer_5.Fit(self)
601 FredericG 172
        self.Layout()
173
        # end wxGlade
174
 
608 FredericG 175
        # Store some of the items, we will need them later
176
        self.grid_sizer_2 = grid_sizer_2  
177
        self.sizer_5 = sizer_5
178
 
179
 
611 FredericG 180
    def onOK(self, event): # wxGlade: SettingsDialog.<event_handler>
181
        print "Updating parameters"
182
        try:
183
            i=0
184
            for setting in self.settings.iteritems():
185
              print setting[0], self.tb[i].GetValue()
186
              setting[1].set(self.tb[i].GetValue())
187
              i += 1
188
            event.Skip()
189
        except:
190
            wx.MessageBox("Invalid format for \"%s\" setting." % setting[1].descr)
191
 
607 FredericG 192
# end of class SettingsDialog
193
 
194
 
195
 
584 FredericG 196
class MainFrame(wx.Frame):
197
    def __init__(self, *args, **kwds):
198
        # begin wxGlade: MainFrame.__init__
199
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
200
        wx.Frame.__init__(self, *args, **kwds)
587 FredericG 201
 
202
        # Menu Bar
203
        self.frame_1_menubar = wx.MenuBar()
204
        wxglade_tmp_menu = wx.Menu()
607 FredericG 205
        wxglade_tmp_menu.Append(101, "Settings", "", wx.ITEM_NORMAL)
616 FredericG 206
        wxglade_tmp_menu.AppendSeparator()
607 FredericG 207
        wxglade_tmp_menu.Append(150, "Exit", "", wx.ITEM_NORMAL)
587 FredericG 208
        self.frame_1_menubar.Append(wxglade_tmp_menu, "File")
209
        wxglade_tmp_menu = wx.Menu()
616 FredericG 210
        wxglade_tmp_menu.Append(301, "Clear All", "", wx.ITEM_NORMAL)
211
        wxglade_tmp_menu.Append(302, "Clear Selected", "", wx.ITEM_NORMAL)
212
        wxglade_tmp_menu.AppendSeparator()
213
        wxglade_tmp_menu.Append(303, "Load", "", wx.ITEM_NORMAL)
214
        wxglade_tmp_menu.Append(304, "Save", "", wx.ITEM_NORMAL)
587 FredericG 215
        self.frame_1_menubar.Append(wxglade_tmp_menu, "TestSet")
216
        wxglade_tmp_menu = wx.Menu()
217
        self.frame_1_menubar.Append(wxglade_tmp_menu, "MK")
218
        wxglade_tmp_menu = wx.Menu()
219
        self.frame_1_menubar.Append(wxglade_tmp_menu, "Help")
220
        self.SetMenuBar(self.frame_1_menubar)
221
        # Menu Bar end
600 FredericG 222
        self.Description = wx.StaticText(self, -1, "Description")
613 FredericG 223
        self.tcDescr = wx.TextCtrl(self, -1, "Test")
600 FredericG 224
        self.label_37 = wx.StaticText(self, -1, "Speed(s)")
613 FredericG 225
        self.tcSpeeds = wx.TextCtrl(self, -1, "100-200:10")
600 FredericG 226
        self.label_35 = wx.StaticText(self, -1, "Motor(s)")
613 FredericG 227
        self.tcMotors = wx.TextCtrl(self, -1, "1")
600 FredericG 228
        self.label_38 = wx.StaticText(self, -1, "")
229
        self.text_ctrl_10 = wx.TextCtrl(self, -1, "")
613 FredericG 230
        self.label_36 = wx.StaticText(self, -1, "Channel(s)")
231
        self.tcChannels = wx.TextCtrl(self, -1, "6")
600 FredericG 232
        self.label_39 = wx.StaticText(self, -1, "")
233
        self.text_ctrl_11 = wx.TextCtrl(self, -1, "")
234
        self.button_4 = wx.Button(self, -1, "Start")
235
        self.GraphPanel = wx.Panel(self, -1)
236
        self.label_40 = wx.StaticText(self, -1, "Graph Type ")
237
        self.graphTypeChoice = wx.Choice(self, -1, choices=["Raw Signal", "Filtered Signal", "Spectrum"])
238
        self.label_41 = wx.StaticText(self, -1, "Y Axis Range ")
239
        self.yAxisChoice = wx.Choice(self, -1, choices=["25", "50", "100", "200"])
586 FredericG 240
        self.TestListCtrl = wx.ListCtrl(self, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
584 FredericG 241
 
242
        self.__set_properties()
243
        self.__do_layout()
587 FredericG 244
 
607 FredericG 245
        self.Bind(wx.EVT_MENU, self.OnSettings, id=101)
246
        self.Bind(wx.EVT_MENU, self.onClear, id=301)
616 FredericG 247
        self.Bind(wx.EVT_MENU, self.onClearSelected, id=302)
248
        self.Bind(wx.EVT_MENU, self.OnImport, id=303)
249
        self.Bind(wx.EVT_MENU, self.onExport, id=304)
612 FredericG 250
        self.Bind(wx.EVT_BUTTON, self.onStartMeasure, self.button_4)
600 FredericG 251
        self.Bind(wx.EVT_CHOICE, self.onGraphTypeChange, self.graphTypeChoice)
252
        self.Bind(wx.EVT_CHOICE, self.onYAxisChange, self.yAxisChoice)
584 FredericG 253
        # end wxGlade
254
 
587 FredericG 255
    def setApp(self, app):
256
        self.app = app
585 FredericG 257
 
584 FredericG 258
    def __set_properties(self):
259
        # begin wxGlade: MainFrame.__set_properties
587 FredericG 260
        self.SetTitle("VibrationTest")
600 FredericG 261
        self.SetSize((850, 700))
262
        self.Description.SetMinSize((53, 13))
601 FredericG 263
        self.button_4.SetMinSize((80, 80))
600 FredericG 264
        self.GraphPanel.SetMinSize((800,300))
265
        self.graphTypeChoice.SetSelection(0)
266
        self.yAxisChoice.SetSelection(1)
267
        self.TestListCtrl.SetMinSize((800,300))
584 FredericG 268
        # end wxGlade
269
 
270
    def __do_layout(self):
271
        # begin wxGlade: MainFrame.__do_layout
600 FredericG 272
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
273
        sizer_8 = wx.BoxSizer(wx.VERTICAL)
274
        sizer_11 = wx.BoxSizer(wx.VERTICAL)
275
        sizer_12 = wx.BoxSizer(wx.HORIZONTAL)
276
        sizer_9 = wx.BoxSizer(wx.HORIZONTAL)
277
        sizer_10 = wx.BoxSizer(wx.HORIZONTAL)
278
        grid_sizer_1 = wx.GridSizer(3, 4, 4, 5)
279
        sizer_3.Add((20, 20), 0, 0, 0)
280
        sizer_8.Add((20, 20), 0, 0, 0)
281
        grid_sizer_1.Add(self.Description, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
613 FredericG 282
        grid_sizer_1.Add(self.tcDescr, 0, 0, 0)
600 FredericG 283
        grid_sizer_1.Add(self.label_37, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
613 FredericG 284
        grid_sizer_1.Add(self.tcSpeeds, 0, 0, 0)
600 FredericG 285
        grid_sizer_1.Add(self.label_35, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
613 FredericG 286
        grid_sizer_1.Add(self.tcMotors, 0, 0, 0)
600 FredericG 287
        grid_sizer_1.Add(self.label_38, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
288
        grid_sizer_1.Add(self.text_ctrl_10, 0, 0, 0)
289
        grid_sizer_1.Add(self.label_36, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
613 FredericG 290
        grid_sizer_1.Add(self.tcChannels, 0, 0, 0)
600 FredericG 291
        grid_sizer_1.Add(self.label_39, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
292
        grid_sizer_1.Add(self.text_ctrl_11, 0, 0, 0)
293
        sizer_9.Add(grid_sizer_1, 0, 0, 0)
294
        sizer_10.Add((50, 20), 0, 0, 0)
295
        sizer_10.Add(self.button_4, 0, wx.ALIGN_CENTER_VERTICAL, 0)
296
        sizer_9.Add(sizer_10, 1, wx.EXPAND, 0)
297
        sizer_8.Add(sizer_9, 0, 0, 0)
298
        sizer_8.Add((20, 30), 0, 0, 0)
299
        sizer_11.Add(self.GraphPanel, 1, wx.EXPAND, 0)
300
        sizer_11.Add((20, 5), 0, 0, 0)
301
        sizer_12.Add(self.label_40, 0, wx.ALIGN_CENTER_VERTICAL, 0)
302
        sizer_12.Add(self.graphTypeChoice, 0, 0, 0)
303
        sizer_12.Add((40, 20), 0, 0, 0)
304
        sizer_12.Add(self.label_41, 0, wx.ALIGN_CENTER_VERTICAL, 0)
305
        sizer_12.Add(self.yAxisChoice, 0, 0, 0)
306
        sizer_11.Add(sizer_12, 0, 0, 0)
307
        sizer_8.Add(sizer_11, 0, 0, 0)
308
        sizer_8.Add((20, 30), 0, 0, 0)
309
        sizer_8.Add(self.TestListCtrl, 1, 0, 0)
310
        sizer_8.Add((20, 20), 0, 0, 0)
311
        sizer_3.Add(sizer_8, 1, wx.EXPAND, 0)
312
        self.SetSizer(sizer_3)
584 FredericG 313
        self.Layout()
600 FredericG 314
        self.SetSize((850, 700))
584 FredericG 315
        # end wxGlade
316
 
590 FredericG 317
        # List events
318
        self.TestListCtrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnTestSelected, self.TestListCtrl)
319
 
586 FredericG 320
        # Configure Graph
593 FredericG 321
        self.client = wx.lib.plot.PlotCanvas(self.GraphPanel, size=(800,300))
322
 
585 FredericG 323
        self.client.SetPointLabelFunc(self.DrawPointLabel)
324
 
325
        self.client.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.NORMAL))
326
        self.client.SetFontSizeAxis(10)
327
        self.client.SetFontSizeLegend(7)
328
        self.client.setLogScale((False,False))
329
 
586 FredericG 330
 
331
        # Configure TestListCtrl
594 FredericG 332
        self.TestListCtrl.InsertColumn(0, "Description")
333
        self.TestListCtrl.InsertColumn(1, "Speed")
334
        self.TestListCtrl.InsertColumn(2, "Channel")
607 FredericG 335
        self.TestListCtrl.InsertColumn(3, "Vibration Value")
336
        self.TestListCtrl.SetColumnWidth(3, 500)
586 FredericG 337
 
585 FredericG 338
    def DrawPointLabel(self, dc, mDataDict):
339
        """This is the fuction that defines how the pointLabels are plotted
340
            dc - DC that will be passed
341
            mDataDict - Dictionary of data that you want to use for the pointLabel
342
 
343
            As an example I have decided I want a box at the curve point
344
            with some text information about the curve plotted below.
345
            Any wxDC method can be used.
346
        """
347
        # ----------
348
        dc.SetPen(wx.Pen(wx.BLACK))
349
        dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
350
 
351
        sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point
352
        dc.DrawRectangle( sx-5,sy-5, 10, 10)  #10by10 square centered on point
353
        px,py = mDataDict["pointXY"]
354
        cNum = mDataDict["curveNum"]
355
        pntIn = mDataDict["pIndex"]
356
        legend = mDataDict["legend"]
357
        #make a string to display
358
        s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
359
        dc.DrawText(s, sx , sy+1)
360
        # -----------
361
 
596 FredericG 362
 
363
    def onNewTest(self, test):
364
        index = self.TestListCtrl.InsertStringItem(sys.maxint, test.descr)
365
        self.TestListCtrl.SetStringItem(index, 1, str(test.speed))
366
        self.TestListCtrl.SetStringItem(index, 2, test.channel)
607 FredericG 367
 
615 FredericG 368
        vv = int(test.getVibValue(self.app.settings["hpf"].value, self.app.settings["lpf"].value))
607 FredericG 369
        vvs = "|%s| (%d)" % ("----------------------------------------------------------------------------------------------------"[0:min(vv,100)], vv)
370
        self.TestListCtrl.SetStringItem(index, 3, vvs)
613 FredericG 371
        self.TestListCtrl.Select(index)
596 FredericG 372
 
373
 
590 FredericG 374
    def OnTestSelected(self, event):
375
         testId = event.m_itemIndex
376
         print "Test Selected id=%d" % (testId)
592 FredericG 377
         self.activeTestId = testId
378
         self.drawGraph()
590 FredericG 379
 
592 FredericG 380
    def drawGraph(self):
607 FredericG 381
 
600 FredericG 382
         y = int(self.yAxisChoice.GetStringSelection())
590 FredericG 383
 
607 FredericG 384
         nbSelected = self.TestListCtrl.SelectedItemCount
596 FredericG 385
 
616 FredericG 386
         if nbSelected == 0:
387
              self.client.Clear()
388
 
389
         elif nbSelected > 1:
607 FredericG 390
             self.graphTypeChoice.Disable()
391
             x = 1
392
             data = []
393
             idx = self.TestListCtrl.GetFirstSelected()
394
             while idx != -1:
615 FredericG 395
                 data.append([x,self.app.getTest(idx).getVibValue(self.app.settings["hpf"].value, self.app.settings["lpf"].value)])
607 FredericG 396
                 x += 1
397
                 idx = self.TestListCtrl.GetNextSelected(idx)
398
             line = wx.lib.plot.PolyLine(data, legend= 'Vibrations', colour='red', width=2)
399
             markers = wx.lib.plot.PolyMarker(data, legend= '', colour='red', marker='circle',size=2)
400
             title = "Comparing tests"
401
             self.client.Draw(wx.lib.plot.PlotGraphics([line, markers], title, "Test", "Vibration Value"), xAxis=(1,max(x,10)), yAxis=(0,y))
600 FredericG 402
             self.client.SetEnableGrid('Horizontal')
403
 
607 FredericG 404
         else:
405
             self.graphTypeChoice.Enable()
406
             vibTest = self.app.getTest(self.activeTestId)
407
             nb = vibTest.getDataLen()
590 FredericG 408
 
607 FredericG 409
             if self.graphTypeChoice.GetSelection() == 0:
410
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
411
                 xydata.shape = (nb, 2)
412
                 xydata[:,1] = vibTest.getRawData()
413
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
414
 
415
                 title = "Raw Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
416
                 self.client.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y,y))
417
                 self.client.SetEnableGrid('Horizontal')
599 FredericG 418
 
607 FredericG 419
             if self.graphTypeChoice.GetSelection() == 1:
420
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
421
                 xydata.shape = (nb, 2)
615 FredericG 422
                 xydata[:,1] = vibTest.getFilteredData(self.app.settings["hpf"].value, self.app.settings["lpf"].value)
607 FredericG 423
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
424
 
425
                 title = "Filtered Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
426
                 self.client.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y,y))
427
                 self.client.SetEnableGrid('Horizontal')
428
 
429
             elif self.graphTypeChoice.GetSelection() == 2:
615 FredericG 430
                 xydata = _Numeric.linspace(0,FS/2,nb)
607 FredericG 431
                 xydata.shape = (nb/2, 2)
432
 
433
                 xydata[:,1] = vibTest.getSpectrum()
434
 
435
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Spectrum', colour='red')
436
                 markers = wx.lib.plot.PolyMarker(xydata, legend= '', colour='red', marker='circle',size=2)
615 FredericG 437
 
438
                 fc = self.app.settings["hpf"].value
439
                 filterLine1 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
440
                 fc = self.app.settings["lpf"].value
441
                 filterLine2 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
607 FredericG 442
 
443
                 title = "Spectrum: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
615 FredericG 444
                 self.client.Draw(wx.lib.plot.PlotGraphics([line,markers, filterLine1, filterLine2], title, "Freq (Hz)", "Acc"), xAxis=(0,200), yAxis= (-0,y))
607 FredericG 445
                 self.client.SetEnableGrid(True)
590 FredericG 446
 
599 FredericG 447
 
587 FredericG 448
    def OnImport(self, event): # wxGlade: MainFrame.<event_handler>
606 FredericG 449
        dlg = wx.FileDialog(
450
            self, message="Choose a file",
451
            defaultDir=os.getcwd(),
452
            defaultFile="*.txt",
453
            wildcard="",
454
            style=wx.OPEN | wx.CHANGE_DIR
455
            )
456
        if dlg.ShowModal() == wx.ID_OK:
457
            paths = dlg.GetPaths();
458
            self.app.Import(paths[0])
459
        dlg.Destroy()
587 FredericG 460
 
599 FredericG 461
    def onYAxisChange(self, event): # wxGlade: MainFrame.<event_handler>
592 FredericG 462
        self.drawGraph()
463
 
600 FredericG 464
    def onGraphTypeChange(self, event): # wxGlade: MainFrame.<event_handler>
599 FredericG 465
        self.drawGraph()
466
 
607 FredericG 467
    def OnSettings(self, event): # wxGlade: MainFrame.<event_handler>
468
        dlg = SettingsDialog(self, -1, "Sample Dialog", size=(350, 200),
469
                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
470
                         style=wx.DEFAULT_DIALOG_STYLE, # & ~wx.CLOSE_BOX
471
                         )
472
        dlg.CenterOnScreen()
611 FredericG 473
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
607 FredericG 474
        dlg.Destroy()
611 FredericG 475
        self.app.onSettingsChanged()
607 FredericG 476
 
612 FredericG 477
    def onStartMeasure(self, event): # wxGlade: MainFrame.<event_handler>
613 FredericG 478
        # Collect measure parameters
479
        mp = MeasureParameters()
480
        mp.descr = self.tcDescr.GetValue()
481
        mp.motors = map(int,self.tcMotors.GetValue().split(','))
482
        mp.channels = map(int,self.tcChannels.GetValue().split(','))
483
        s = self.tcSpeeds.GetValue()
484
        if s.count("-") == 1:
485
            # assume from-to:step format
486
            s = s.split("-")
487
            if len(s) != 2: raise Exception("Invalid format")
488
            s[1] = s[1].split(":")
489
            if len(s[1]) != 2: raise Exception("Invalid format")
490
            mp.speeds = range(int(s[0]),int(s[1][0])+int(s[1][1]),int(s[1][1]))
491
        else:
614 FredericG 492
            mp.speeds = map(int,s.split(','))
493
 
613 FredericG 494
 
612 FredericG 495
        # create the dialog that will show the satus
496
        dlg = MeasureDialog(self)
497
        dlg.CenterOnScreen()
613 FredericG 498
 
499
        # Signal the application
500
        self.app.startMeasure(mp, dlg)
501
 
612 FredericG 502
        # Show the dialog
503
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
504
        dlg.Destroy()
505
 
616 FredericG 506
    def _removeTest(self, idx):
507
        print "Deleting test %d" % idx
508
        self.app.removeTest(idx)
509
        self.TestListCtrl.DeleteItem(idx)
510
 
511
 
512
    def onClear(self, event): # wxGlade: MainFrame.<event_handler>
513
        print "Clear all tests"
514
        for i in range(len(self.app.VibTests)-1, -1, -1):
515
            self._removeTest(i)
516
        self.drawGraph()
517
 
518
 
519
    def onClearSelected(self, event): # wxGlade: MainFrame.<event_handler>
520
        while True:
521
            idx = self.TestListCtrl.GetFirstSelected()
522
            if idx == -1: break
523
            self._removeTest(idx)
524
 
525
    def onExport(self, event): # wxGlade: MainFrame.<event_handler>
526
        print "Event handler `onExport' not implemented"
527
        event.Skip()
528
 
584 FredericG 529
# end of class MainFrame
530
 
607 FredericG 531
class Setting:
532
    def __init__(self, descr, defaultValue):
533
        self.descr = descr
534
        self.value = defaultValue
611 FredericG 535
 
536
    def set(self, newValue):
537
        if isinstance(self.value, int):
538
            self.value = int(newValue)
539
        else:
540
            self.value = str(newValue)
584 FredericG 541
 
613 FredericG 542
class MeasureParameters:
543
      pass
612 FredericG 544
 
545
class MeasureThread:
613 FredericG 546
    def __init__(self, measureParameters, evtConsumer):
547
        self.mk = mkProto.MkComm()
548
        self.param = measureParameters
612 FredericG 549
        self.evtConsumer = evtConsumer
613 FredericG 550
        self.cancel = False
551
        self.running = False
612 FredericG 552
 
553
    def start(self):
554
        thread.start_new_thread(self._run, ())
555
 
613 FredericG 556
    def stop(self):
557
        self.cancel = True
558
 
559
    def _testCancel(self):
560
        if self.cancel:
561
            raise Exception("Operation cancelled")
562
 
563
    def _sendEvent(self, msg, error=False):
564
        evt = MeasStatusUpdateEvent(running=self.running, msg=msg, error=error)
565
        wx.PostEvent(self.evtConsumer, evt)
566
 
567
    def _setMotorSpeed(self, speed, settlingTime):
568
        speeds = [0,0,0,0]
569
        for motor in self.param.motors:
570
            speeds[motor-1] = speed
571
        for i in range(int(settlingTime*10)):
572
          self._testCancel()
573
          self.mk.setMotorTest(speeds)
574
          time.sleep(.1)
575
 
576
 
612 FredericG 577
    def _run(self):
613 FredericG 578
        self.running = True
579
        self._sendEvent("Starting test \"%s\"" % self.param.descr)    
580
 
581
        try:
582
            self._sendEvent("Opening SerialPort \"%s\"" % self.param.serialPort)
583
            self.mk.open(comPort=self.param.serialPort)
612 FredericG 584
 
613 FredericG 585
            msg = self.mk.getVersionMsg()
586
            version = msg.getVersion()
587
            self._sendEvent("Version: %d.%d" % version)
588
 
589
            msg = self.mk.getDebugMsg()
590
            voltage = msg.getVoltage()
591
            if (voltage == 0):
592
              minVoltage = 0
593
            else:
594
              if (voltage > 4.2*3):
595
                minVoltage = 4*3.5
596
              else:
597
                minVoltage = 3*3.5
598
 
599
            self._sendEvent("Voltage: %2.1fV" % voltage)
600
            self._sendEvent("Minimum Voltage: %2.1fV" % minVoltage)
601
 
602
            self._sendEvent("Starting motor(s) (speed=%d)... " % self.param.motorStartupSpeed)
603
            self._setMotorSpeed(self.param.motorStartupSpeed, self.param.motorStartupSettlingTime)
604
 
605
            for speed in self.param.speeds:
606
                self._sendEvent("Changing motor speed to %d... " % speed)
607
                self._setMotorSpeed(speed, 1)
608
 
609
                for channel in self.param.channels:
610
                    self._setMotorSpeed(speed, .1)
611
                    self._sendEvent("Getting data from channel %s" % CHANNEL_NAMES[channel])
612
                    data = self.mk.doVibrationTest(1000, channel)
613
 
614
                    vt = VibTest(self.param.descr, self.param.motors, speed, CHANNEL_NAMES[channel], data)
615
                    evt = MeasDataEvent(vibTest = vt)
616
                    wx.PostEvent(self.evtConsumer, evt)
617
 
618
            self._sendEvent("Done !")            
612 FredericG 619
 
613 FredericG 620
        except Exception, e:
621
            self._sendEvent("Exception \"%s\"" % e, error=True)  
622
 
623
        self.running = False
624
        self._sendEvent("")    
625
 
612 FredericG 626
 
586 FredericG 627
class VibTest:
596 FredericG 628
    def __init__(self, descr, motor, speed, channel, rawData):
594 FredericG 629
        self.descr = descr
630
        self.motor = motor
631
        self.speed = speed
596 FredericG 632
        self.channel = channel
599 FredericG 633
 
634
        self.dataLen = len(rawData)
635
 
590 FredericG 636
        self.rawData = _Numeric.array(rawData)
637
        self.dc = self.rawData.mean()
638
        self.rawData -= self.dc
586 FredericG 639
 
600 FredericG 640
        self.fft = _Numeric.fft.rfft(self.rawData)
641
 
642
        self.spectrum = None
643
        self.filteredData = None
615 FredericG 644
        self.fc1 = None
645
        self.fc2 = None
599 FredericG 646
 
602 FredericG 647
        self.vibValue = None
648
 
594 FredericG 649
    def getDescr(self):
650
        return self.Descr
587 FredericG 651
 
590 FredericG 652
    def getRawData(self):
653
        return self.rawData
654
 
655
    def getDataLen(self):
656
        return self.dataLen
657
 
599 FredericG 658
    def getSpectrum(self):
600 FredericG 659
        if self.spectrum == None:
660
            self.spectrum = _Numeric.absolute(self.fft[1:self.dataLen/2+1]) / (self.dataLen/2)
661
        return self.spectrum
590 FredericG 662
 
615 FredericG 663
    def getFilteredData(self, fc1, fc2):
664
        if self.fc1 != fc1 or self.fc2 != fc2:
665
            self.filteredData = None  
666
 
600 FredericG 667
        if self.filteredData == None:
668
            tmpfft = self.fft.copy()
615 FredericG 669
            fc = (float(fc1))/(FS/2)*len(tmpfft)
670
            print "fc1=%d => fc=%d" % (fc1,fc)
671
            for i in range(0,int(fc)):
600 FredericG 672
                tmpfft[i] = 0
615 FredericG 673
            fc = (float(fc2))/(FS/2)*len(tmpfft)
674
            print "fc2=%d => fc=%d" % (fc2,fc)
675
            for i in range(int(fc), len(tmpfft)):
600 FredericG 676
                tmpfft[i] = 0
677
            self.filteredData = _Numeric.fft.irfft(tmpfft)
615 FredericG 678
            self.fc1 = fc1
679
            self.fc2 = fc2
680
 
600 FredericG 681
        return self.filteredData
602 FredericG 682
 
615 FredericG 683
    def getVibValue(self, fc1, fc2):
684
      if self.fc1 != fc1 or self.fc2 != fc2:
685
        self.vibValue = None  
602 FredericG 686
      if self.vibValue == None:
615 FredericG 687
        fd = self.getFilteredData(fc1, fc2)[100:-100];
602 FredericG 688
        self.vibValue = max(fd)-min(fd)
689
      return self.vibValue
599 FredericG 690
 
607 FredericG 691
 
692
 
584 FredericG 693
class App(wx.App):
607 FredericG 694
 
695
    SETTINGSFILE = "settings.cfg"
696
 
586 FredericG 697
    def __init__(self, par):
698
        self.VibTests = []
699
        wx.App.__init__(self, par)
700
 
607 FredericG 701
        # Init settings
702
        self.settings={}
611 FredericG 703
        self.settings["serialport"] = Setting("Serial Port", "COM1")
613 FredericG 704
        self.settings["startupspeed"] = Setting("Motor Startup Speed", 25)
705
        self.settings["startupsettling"] = Setting("Motor Startup Setting time (s)", 3)
706
        self.settings["serialport"] = Setting("Serial Port", "COM1")
607 FredericG 707
        self.settings["hpf"] = Setting("HP Filter cutoff (Hz)", 50)
615 FredericG 708
        self.settings["lpf"] = Setting("LP Filter cutoff (Hz)", 180)
607 FredericG 709
 
710
        self.readSettings()
711
 
606 FredericG 712
        if len(sys.argv)>1:
713
            self.Import(sys.argv[1])
586 FredericG 714
 
606 FredericG 715
 
607 FredericG 716
    def readSettings(self):
717
        print "Reading settings"
718
        cp = ConfigParser.ConfigParser()
719
 
720
        try:
721
            cp.read(App.SETTINGSFILE)
722
            for setting in cp.items("DEFAULT"):
723
                print " ",setting
724
                try:
613 FredericG 725
                    self.settings[setting[0]].set(setting[1])
607 FredericG 726
                except:
727
                    print "WARNING, unknown setting"
728
        except:
729
            print "ERROR reading settingsfile"
730
 
731
 
732
    def storeSettings(self):
733
        print "Storing settings"
734
 
735
        cp = ConfigParser.ConfigParser()
736
        for setting in self.settings.iteritems():
737
            cp.set("", setting[0], setting[1].value)
738
 
739
        file = open(App.SETTINGSFILE, "w")
740
        cp.write(file)
741
        file.close()
742
 
611 FredericG 743
 
744
    def onSettingsChanged(self):
745
        self.storeSettings()
613 FredericG 746
 
747
    def AddTest2(self, vibTest):
748
        self.VibTests.append(vibTest)
749
        self.frame_1.onNewTest(vibTest)
611 FredericG 750
 
596 FredericG 751
    def AddTest(self, descr, motor, speed, channel, rawData):
752
        test = VibTest(descr, motor, speed, channel, rawData)
613 FredericG 753
        self.AddTest2(test)
586 FredericG 754
 
616 FredericG 755
    def removeTest(self, idx):
756
        del(self.VibTests[idx])
757
 
590 FredericG 758
    def getTest(self, testId):
759
        return self.VibTests[testId]
760
 
584 FredericG 761
    def OnInit(self):
762
        wx.InitAllImageHandlers()
586 FredericG 763
        self.frame_1 = MainFrame(None, -1, "")
587 FredericG 764
        self.frame_1.setApp(self);
586 FredericG 765
        self.SetTopWindow(self.frame_1)
766
 
607 FredericG 767
        self.frame_1.CenterOnScreen()
587 FredericG 768
        self.frame_1.Show()
769
        return 1
770
 
606 FredericG 771
    def Import(self, filePath):
596 FredericG 772
 
606 FredericG 773
        print "Importing file \"%s\"" % filePath
596 FredericG 774
 
775
        logfile = open(filePath, "r")
590 FredericG 776
        data = None
596 FredericG 777
 
778
        headers = (logfile.readline()).split(',')
779
        nbCols = len(headers)
780
        print "NbCols =", nbCols
781
 
782
        data = []
783
        descr = []
784
        speed = []
785
        channel = []
786
        for c in range(nbCols):
787
            data.append([])
788
            h = headers[c].split(' ')
789
            descr.append(h[0]);
790
            speed.append(h[1]);
791
            channel.append(h[2]);
792
 
590 FredericG 793
        for line in logfile:
794
            values = line.split(',')
596 FredericG 795
            for i in range(nbCols):
796
                data[i].append(int(values[i]))
590 FredericG 797
        logfile.close()
596 FredericG 798
 
799
        for c in range(nbCols):
599 FredericG 800
            if (len(data[c]) % 2) != 0:
801
                data[c].append(data[c][-1])
596 FredericG 802
            self.AddTest(descr[c], 0, int(speed[c]), channel[c], data[c])
612 FredericG 803
 
613 FredericG 804
    def startMeasure(self, measureParams, dialog):
612 FredericG 805
        print "Start measuring"
590 FredericG 806
 
613 FredericG 807
        measureParams.serialPort = self.settings["serialport"].value
808
        measureParams.motorStartupSpeed = self.settings["startupspeed"].value
809
        measureParams.motorStartupSettlingTime = self.settings["startupsettling"].value
810
 
811
        self.measureThread = MeasureThread(measureParams, dialog)
612 FredericG 812
        self.measureThread.start()
590 FredericG 813
 
613 FredericG 814
    def cancelMeasurement(self):
815
        print "Measuring CANCEL"
816
 
817
        self.measureThread.stop()
818
 
612 FredericG 819
 
820
 
821
 
822
 
590 FredericG 823
 
586 FredericG 824
 
590 FredericG 825
 
584 FredericG 826
# end of class App
827
 
828
if __name__ == "__main__":
829
    VibrationTestGui = App(0)
830
    VibrationTestGui.MainLoop()