Subversion Repositories Projects

Rev

Rev 616 | Rev 623 | 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")
619 FredericG 333
        self.TestListCtrl.InsertColumn(1, "Voltage")
334
        self.TestListCtrl.InsertColumn(2, "Speed")
335
        self.TestListCtrl.InsertColumn(3, "Channel")
336
        self.TestListCtrl.InsertColumn(4, "Vibration Value")
337
        self.TestListCtrl.SetColumnWidth(4, 500)
586 FredericG 338
 
585 FredericG 339
    def DrawPointLabel(self, dc, mDataDict):
340
        """This is the fuction that defines how the pointLabels are plotted
341
            dc - DC that will be passed
342
            mDataDict - Dictionary of data that you want to use for the pointLabel
343
 
344
            As an example I have decided I want a box at the curve point
345
            with some text information about the curve plotted below.
346
            Any wxDC method can be used.
347
        """
348
        # ----------
349
        dc.SetPen(wx.Pen(wx.BLACK))
350
        dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
351
 
352
        sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point
353
        dc.DrawRectangle( sx-5,sy-5, 10, 10)  #10by10 square centered on point
354
        px,py = mDataDict["pointXY"]
355
        cNum = mDataDict["curveNum"]
356
        pntIn = mDataDict["pIndex"]
357
        legend = mDataDict["legend"]
358
        #make a string to display
359
        s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
360
        dc.DrawText(s, sx , sy+1)
361
        # -----------
362
 
596 FredericG 363
 
364
    def onNewTest(self, test):
365
        index = self.TestListCtrl.InsertStringItem(sys.maxint, test.descr)
619 FredericG 366
        self.TestListCtrl.SetStringItem(index, 1, "%.1f V" %test.voltage)
367
        self.TestListCtrl.SetStringItem(index, 2, str(test.speed))
368
        self.TestListCtrl.SetStringItem(index, 3, test.channel)
607 FredericG 369
 
615 FredericG 370
        vv = int(test.getVibValue(self.app.settings["hpf"].value, self.app.settings["lpf"].value))
607 FredericG 371
        vvs = "|%s| (%d)" % ("----------------------------------------------------------------------------------------------------"[0:min(vv,100)], vv)
619 FredericG 372
        self.TestListCtrl.SetStringItem(index, 4, vvs)
613 FredericG 373
        self.TestListCtrl.Select(index)
596 FredericG 374
 
375
 
590 FredericG 376
    def OnTestSelected(self, event):
377
         testId = event.m_itemIndex
378
         print "Test Selected id=%d" % (testId)
592 FredericG 379
         self.activeTestId = testId
380
         self.drawGraph()
590 FredericG 381
 
592 FredericG 382
    def drawGraph(self):
607 FredericG 383
 
600 FredericG 384
         y = int(self.yAxisChoice.GetStringSelection())
590 FredericG 385
 
607 FredericG 386
         nbSelected = self.TestListCtrl.SelectedItemCount
596 FredericG 387
 
616 FredericG 388
         if nbSelected == 0:
389
              self.client.Clear()
390
 
391
         elif nbSelected > 1:
607 FredericG 392
             self.graphTypeChoice.Disable()
393
             x = 1
394
             data = []
395
             idx = self.TestListCtrl.GetFirstSelected()
396
             while idx != -1:
615 FredericG 397
                 data.append([x,self.app.getTest(idx).getVibValue(self.app.settings["hpf"].value, self.app.settings["lpf"].value)])
607 FredericG 398
                 x += 1
399
                 idx = self.TestListCtrl.GetNextSelected(idx)
400
             line = wx.lib.plot.PolyLine(data, legend= 'Vibrations', colour='red', width=2)
401
             markers = wx.lib.plot.PolyMarker(data, legend= '', colour='red', marker='circle',size=2)
402
             title = "Comparing tests"
403
             self.client.Draw(wx.lib.plot.PlotGraphics([line, markers], title, "Test", "Vibration Value"), xAxis=(1,max(x,10)), yAxis=(0,y))
600 FredericG 404
             self.client.SetEnableGrid('Horizontal')
405
 
607 FredericG 406
         else:
407
             self.graphTypeChoice.Enable()
408
             vibTest = self.app.getTest(self.activeTestId)
409
             nb = vibTest.getDataLen()
590 FredericG 410
 
607 FredericG 411
             if self.graphTypeChoice.GetSelection() == 0:
412
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
413
                 xydata.shape = (nb, 2)
414
                 xydata[:,1] = vibTest.getRawData()
415
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
416
 
417
                 title = "Raw Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
418
                 self.client.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y,y))
419
                 self.client.SetEnableGrid('Horizontal')
599 FredericG 420
 
607 FredericG 421
             if self.graphTypeChoice.GetSelection() == 1:
422
                 xydata = _Numeric.linspace(0,0.09*nb,2*nb)
423
                 xydata.shape = (nb, 2)
615 FredericG 424
                 xydata[:,1] = vibTest.getFilteredData(self.app.settings["hpf"].value, self.app.settings["lpf"].value)
607 FredericG 425
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Raw Data', colour='red', width=2)
426
 
427
                 title = "Filtered Signal: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
428
                 self.client.Draw(wx.lib.plot.PlotGraphics([line], title, "Time (ms)", "Acc"), yAxis= (-y,y))
429
                 self.client.SetEnableGrid('Horizontal')
430
 
431
             elif self.graphTypeChoice.GetSelection() == 2:
615 FredericG 432
                 xydata = _Numeric.linspace(0,FS/2,nb)
607 FredericG 433
                 xydata.shape = (nb/2, 2)
434
 
435
                 xydata[:,1] = vibTest.getSpectrum()
436
 
437
                 line = wx.lib.plot.PolyLine(xydata, legend= 'Spectrum', colour='red')
438
                 markers = wx.lib.plot.PolyMarker(xydata, legend= '', colour='red', marker='circle',size=2)
615 FredericG 439
 
440
                 fc = self.app.settings["hpf"].value
441
                 filterLine1 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
442
                 fc = self.app.settings["lpf"].value
443
                 filterLine2 = wx.lib.plot.PolyLine(((fc,0),(fc,y)), legend='HP Filter', colour='Black', width=4)
607 FredericG 444
 
445
                 title = "Spectrum: %s %s %d" %(vibTest.descr, vibTest.channel, vibTest.speed)
615 FredericG 446
                 self.client.Draw(wx.lib.plot.PlotGraphics([line,markers, filterLine1, filterLine2], title, "Freq (Hz)", "Acc"), xAxis=(0,200), yAxis= (-0,y))
607 FredericG 447
                 self.client.SetEnableGrid(True)
590 FredericG 448
 
599 FredericG 449
 
587 FredericG 450
    def OnImport(self, event): # wxGlade: MainFrame.<event_handler>
606 FredericG 451
        dlg = wx.FileDialog(
452
            self, message="Choose a file",
619 FredericG 453
            defaultDir="%s/Data/" % os.getcwd(),
606 FredericG 454
            defaultFile="*.txt",
619 FredericG 455
            wildcard="*.txt",
606 FredericG 456
            style=wx.OPEN | wx.CHANGE_DIR
457
            )
458
        if dlg.ShowModal() == wx.ID_OK:
459
            paths = dlg.GetPaths();
619 FredericG 460
            self.app.loadTests(paths[0])
606 FredericG 461
        dlg.Destroy()
587 FredericG 462
 
619 FredericG 463
    def onExport(self, event): # wxGlade: MainFrame.<event_handler>
464
        dlg = wx.FileDialog(
465
              self, message="Save file as ...",
466
              defaultDir="%s/Data/" % os.getcwd(),
467
              defaultFile="*.txt",
468
              wildcard="",
469
              style=wx.SAVE
470
              )
471
        if dlg.ShowModal() == wx.ID_OK:
472
            paths = dlg.GetPaths();
473
            self.app.saveTests(paths[0])
474
        dlg.Destroy()
475
 
599 FredericG 476
    def onYAxisChange(self, event): # wxGlade: MainFrame.<event_handler>
592 FredericG 477
        self.drawGraph()
478
 
600 FredericG 479
    def onGraphTypeChange(self, event): # wxGlade: MainFrame.<event_handler>
599 FredericG 480
        self.drawGraph()
481
 
607 FredericG 482
    def OnSettings(self, event): # wxGlade: MainFrame.<event_handler>
483
        dlg = SettingsDialog(self, -1, "Sample Dialog", size=(350, 200),
484
                         #style=wx.CAPTION | wx.SYSTEM_MENU | wx.THICK_FRAME,
485
                         style=wx.DEFAULT_DIALOG_STYLE, # & ~wx.CLOSE_BOX
486
                         )
487
        dlg.CenterOnScreen()
611 FredericG 488
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
607 FredericG 489
        dlg.Destroy()
611 FredericG 490
        self.app.onSettingsChanged()
607 FredericG 491
 
612 FredericG 492
    def onStartMeasure(self, event): # wxGlade: MainFrame.<event_handler>
613 FredericG 493
        # Collect measure parameters
494
        mp = MeasureParameters()
495
        mp.descr = self.tcDescr.GetValue()
496
        mp.motors = map(int,self.tcMotors.GetValue().split(','))
497
        mp.channels = map(int,self.tcChannels.GetValue().split(','))
498
        s = self.tcSpeeds.GetValue()
619 FredericG 499
        if s=="test":
500
          mp.speeds = (100,100,100,100,100, 150,150,150,150,150, 200,200,200,200,200, 100,150,200, 100,150,200, 100,150,200, 100,150,200)
501
        elif s.count("-") == 1:
613 FredericG 502
            # assume from-to:step format
503
            s = s.split("-")
504
            if len(s) != 2: raise Exception("Invalid format")
505
            s[1] = s[1].split(":")
506
            if len(s[1]) != 2: raise Exception("Invalid format")
507
            mp.speeds = range(int(s[0]),int(s[1][0])+int(s[1][1]),int(s[1][1]))
508
        else:
614 FredericG 509
            mp.speeds = map(int,s.split(','))
510
 
613 FredericG 511
 
612 FredericG 512
        # create the dialog that will show the satus
513
        dlg = MeasureDialog(self)
514
        dlg.CenterOnScreen()
613 FredericG 515
 
516
        # Signal the application
517
        self.app.startMeasure(mp, dlg)
518
 
612 FredericG 519
        # Show the dialog
520
        val = dlg.ShowModal()  # this does not return until the dialog is closed.
521
        dlg.Destroy()
522
 
616 FredericG 523
    def _removeTest(self, idx):
524
        print "Deleting test %d" % idx
525
        self.app.removeTest(idx)
526
        self.TestListCtrl.DeleteItem(idx)
527
 
528
 
529
    def onClear(self, event): # wxGlade: MainFrame.<event_handler>
530
        print "Clear all tests"
531
        for i in range(len(self.app.VibTests)-1, -1, -1):
532
            self._removeTest(i)
533
        self.drawGraph()
534
 
535
 
536
    def onClearSelected(self, event): # wxGlade: MainFrame.<event_handler>
537
        while True:
538
            idx = self.TestListCtrl.GetFirstSelected()
539
            if idx == -1: break
540
            self._removeTest(idx)
541
 
619 FredericG 542
 
584 FredericG 543
# end of class MainFrame
544
 
607 FredericG 545
class Setting:
546
    def __init__(self, descr, defaultValue):
547
        self.descr = descr
548
        self.value = defaultValue
611 FredericG 549
 
550
    def set(self, newValue):
551
        if isinstance(self.value, int):
552
            self.value = int(newValue)
553
        else:
554
            self.value = str(newValue)
584 FredericG 555
 
613 FredericG 556
class MeasureParameters:
557
      pass
612 FredericG 558
 
559
class MeasureThread:
613 FredericG 560
    def __init__(self, measureParameters, evtConsumer):
561
        self.mk = mkProto.MkComm()
562
        self.param = measureParameters
612 FredericG 563
        self.evtConsumer = evtConsumer
613 FredericG 564
        self.cancel = False
565
        self.running = False
612 FredericG 566
 
567
    def start(self):
568
        thread.start_new_thread(self._run, ())
569
 
613 FredericG 570
    def stop(self):
571
        self.cancel = True
572
 
573
    def _testCancel(self):
574
        if self.cancel:
575
            raise Exception("Operation cancelled")
576
 
577
    def _sendEvent(self, msg, error=False):
578
        evt = MeasStatusUpdateEvent(running=self.running, msg=msg, error=error)
579
        wx.PostEvent(self.evtConsumer, evt)
580
 
581
    def _setMotorSpeed(self, speed, settlingTime):
582
        speeds = [0,0,0,0]
583
        for motor in self.param.motors:
584
            speeds[motor-1] = speed
585
        for i in range(int(settlingTime*10)):
586
          self._testCancel()
587
          self.mk.setMotorTest(speeds)
588
          time.sleep(.1)
589
 
590
 
612 FredericG 591
    def _run(self):
613 FredericG 592
        self.running = True
593
        self._sendEvent("Starting test \"%s\"" % self.param.descr)    
594
 
595
        try:
596
            self._sendEvent("Opening SerialPort \"%s\"" % self.param.serialPort)
597
            self.mk.open(comPort=self.param.serialPort)
612 FredericG 598
 
613 FredericG 599
            msg = self.mk.getVersionMsg()
600
            version = msg.getVersion()
601
            self._sendEvent("Version: %d.%d" % version)
602
 
603
            msg = self.mk.getDebugMsg()
604
            voltage = msg.getVoltage()
605
            if (voltage == 0):
606
              minVoltage = 0
607
            else:
608
              if (voltage > 4.2*3):
609
                minVoltage = 4*3.5
610
              else:
611
                minVoltage = 3*3.5
612
 
613
            self._sendEvent("Voltage: %2.1fV" % voltage)
614
            self._sendEvent("Minimum Voltage: %2.1fV" % minVoltage)
615
 
616
            self._sendEvent("Starting motor(s) (speed=%d)... " % self.param.motorStartupSpeed)
617
            self._setMotorSpeed(self.param.motorStartupSpeed, self.param.motorStartupSettlingTime)
618
 
619
            for speed in self.param.speeds:
620
                self._sendEvent("Changing motor speed to %d... " % speed)
621
                self._setMotorSpeed(speed, 1)
622
 
623
                for channel in self.param.channels:
624
                    self._setMotorSpeed(speed, .1)
619 FredericG 625
                    msg = self.mk.getDebugMsg()
626
                    voltage = msg.getVoltage()
627
 
613 FredericG 628
                    self._sendEvent("Getting data from channel %s" % CHANNEL_NAMES[channel])
629
                    data = self.mk.doVibrationTest(1000, channel)
630
 
619 FredericG 631
                    vt = VibTest(self.param.descr, voltage, self.param.motors, speed, CHANNEL_NAMES[channel], data)
613 FredericG 632
                    evt = MeasDataEvent(vibTest = vt)
633
                    wx.PostEvent(self.evtConsumer, evt)
634
 
619 FredericG 635
                    if voltage<minVoltage:
636
                        raise Exception("Voltage too low")
637
 
613 FredericG 638
            self._sendEvent("Done !")            
612 FredericG 639
 
613 FredericG 640
        except Exception, e:
641
            self._sendEvent("Exception \"%s\"" % e, error=True)  
642
 
643
        self.running = False
644
        self._sendEvent("")    
645
 
612 FredericG 646
 
586 FredericG 647
class VibTest:
619 FredericG 648
    def __init__(self, descr, voltage, motor, speed, channel, rawData):
594 FredericG 649
        self.descr = descr
619 FredericG 650
        self.voltage = voltage
594 FredericG 651
        self.motor = motor
652
        self.speed = speed
596 FredericG 653
        self.channel = channel
599 FredericG 654
 
655
        self.dataLen = len(rawData)
656
 
590 FredericG 657
        self.rawData = _Numeric.array(rawData)
658
        self.dc = self.rawData.mean()
659
        self.rawData -= self.dc
586 FredericG 660
 
600 FredericG 661
        self.fft = _Numeric.fft.rfft(self.rawData)
662
 
663
        self.spectrum = None
664
        self.filteredData = None
615 FredericG 665
        self.fc1 = None
666
        self.fc2 = None
599 FredericG 667
 
602 FredericG 668
        self.vibValue = None
669
 
594 FredericG 670
    def getDescr(self):
671
        return self.Descr
587 FredericG 672
 
590 FredericG 673
    def getRawData(self):
674
        return self.rawData
675
 
676
    def getDataLen(self):
677
        return self.dataLen
678
 
599 FredericG 679
    def getSpectrum(self):
600 FredericG 680
        if self.spectrum == None:
681
            self.spectrum = _Numeric.absolute(self.fft[1:self.dataLen/2+1]) / (self.dataLen/2)
682
        return self.spectrum
590 FredericG 683
 
615 FredericG 684
    def getFilteredData(self, fc1, fc2):
685
        if self.fc1 != fc1 or self.fc2 != fc2:
686
            self.filteredData = None  
687
 
600 FredericG 688
        if self.filteredData == None:
689
            tmpfft = self.fft.copy()
615 FredericG 690
            fc = (float(fc1))/(FS/2)*len(tmpfft)
691
            print "fc1=%d => fc=%d" % (fc1,fc)
692
            for i in range(0,int(fc)):
600 FredericG 693
                tmpfft[i] = 0
615 FredericG 694
            fc = (float(fc2))/(FS/2)*len(tmpfft)
695
            print "fc2=%d => fc=%d" % (fc2,fc)
696
            for i in range(int(fc), len(tmpfft)):
600 FredericG 697
                tmpfft[i] = 0
698
            self.filteredData = _Numeric.fft.irfft(tmpfft)
615 FredericG 699
            self.fc1 = fc1
700
            self.fc2 = fc2
701
 
600 FredericG 702
        return self.filteredData
602 FredericG 703
 
615 FredericG 704
    def getVibValue(self, fc1, fc2):
705
      if self.fc1 != fc1 or self.fc2 != fc2:
706
        self.vibValue = None  
602 FredericG 707
      if self.vibValue == None:
615 FredericG 708
        fd = self.getFilteredData(fc1, fc2)[100:-100];
602 FredericG 709
        self.vibValue = max(fd)-min(fd)
710
      return self.vibValue
599 FredericG 711
 
607 FredericG 712
 
713
 
584 FredericG 714
class App(wx.App):
607 FredericG 715
 
716
    SETTINGSFILE = "settings.cfg"
717
 
586 FredericG 718
    def __init__(self, par):
719
        self.VibTests = []
720
        wx.App.__init__(self, par)
721
 
607 FredericG 722
        # Init settings
723
        self.settings={}
611 FredericG 724
        self.settings["serialport"] = Setting("Serial Port", "COM1")
613 FredericG 725
        self.settings["startupspeed"] = Setting("Motor Startup Speed", 25)
726
        self.settings["startupsettling"] = Setting("Motor Startup Setting time (s)", 3)
727
        self.settings["serialport"] = Setting("Serial Port", "COM1")
607 FredericG 728
        self.settings["hpf"] = Setting("HP Filter cutoff (Hz)", 50)
615 FredericG 729
        self.settings["lpf"] = Setting("LP Filter cutoff (Hz)", 180)
607 FredericG 730
 
731
        self.readSettings()
732
 
606 FredericG 733
        if len(sys.argv)>1:
619 FredericG 734
            self.loadTests(sys.argv[1])
586 FredericG 735
 
606 FredericG 736
 
607 FredericG 737
    def readSettings(self):
738
        print "Reading settings"
739
        cp = ConfigParser.ConfigParser()
740
 
741
        try:
742
            cp.read(App.SETTINGSFILE)
743
            for setting in cp.items("DEFAULT"):
744
                print " ",setting
745
                try:
613 FredericG 746
                    self.settings[setting[0]].set(setting[1])
607 FredericG 747
                except:
748
                    print "WARNING, unknown setting"
749
        except:
750
            print "ERROR reading settingsfile"
751
 
752
 
753
    def storeSettings(self):
754
        print "Storing settings"
755
 
756
        cp = ConfigParser.ConfigParser()
757
        for setting in self.settings.iteritems():
758
            cp.set("", setting[0], setting[1].value)
759
 
760
        file = open(App.SETTINGSFILE, "w")
761
        cp.write(file)
762
        file.close()
763
 
611 FredericG 764
 
765
    def onSettingsChanged(self):
766
        self.storeSettings()
613 FredericG 767
 
768
    def AddTest2(self, vibTest):
769
        self.VibTests.append(vibTest)
770
        self.frame_1.onNewTest(vibTest)
611 FredericG 771
 
619 FredericG 772
    def AddTest(self, descr, voltage, motor, speed, channel, rawData):
773
        test = VibTest(descr, voltage, motor, speed, channel, rawData)
613 FredericG 774
        self.AddTest2(test)
586 FredericG 775
 
616 FredericG 776
    def removeTest(self, idx):
777
        del(self.VibTests[idx])
778
 
590 FredericG 779
    def getTest(self, testId):
780
        return self.VibTests[testId]
781
 
584 FredericG 782
    def OnInit(self):
783
        wx.InitAllImageHandlers()
586 FredericG 784
        self.frame_1 = MainFrame(None, -1, "")
587 FredericG 785
        self.frame_1.setApp(self);
586 FredericG 786
        self.SetTopWindow(self.frame_1)
787
 
607 FredericG 788
        self.frame_1.CenterOnScreen()
587 FredericG 789
        self.frame_1.Show()
790
        return 1
791
 
619 FredericG 792
    def saveTests(self, filePath):
793
        try:
794
          logfile = open(filePath, "r")
795
          newFile = False
796
          logfile.close()
797
        except:
798
          newFile = True
799
 
800
        for test in self.VibTests:
801
          if newFile:
802
            logfile = open(filePath, "w")
803
            print "Writing result to %s ..." % filePath,
804
            logfile.write("%s %d %s\n" % (test.descr, test.speed, test.channel))
805
            for value in test.rawData:
806
              logfile.write("%d\n" % value)
807
            logfile.close()  
808
            print "OK"
809
          else:
810
            print "Appending result to %s ..." % filePath,
811
            logfile = open(filePath, "r")
812
            prevData = []
813
            for line in logfile:
814
              prevData.append(line[:-1])
815
            logfile.close()
816
            logfile = open(filePath, "w")
817
            logfile.write("%s,%s %d %s\n" % (prevData[0], test.descr, test.speed, test.channel))
818
            i = 1
819
            for value in test.rawData:
820
              logfile.write("%s,%d\n" % (prevData[i], value))
821
              i += 1
822
            logfile.close()
823
            print "OK"
824
          newFile = False
825
 
826
 
827
    def loadTests(self, filePath):
596 FredericG 828
 
606 FredericG 829
        print "Importing file \"%s\"" % filePath
596 FredericG 830
 
831
        logfile = open(filePath, "r")
590 FredericG 832
        data = None
596 FredericG 833
 
619 FredericG 834
        headers = (logfile.readline()[:-1]).split(',')
596 FredericG 835
        nbCols = len(headers)
836
        print "NbCols =", nbCols
837
 
838
        data = []
839
        descr = []
840
        speed = []
841
        channel = []
842
        for c in range(nbCols):
843
            data.append([])
844
            h = headers[c].split(' ')
845
            descr.append(h[0]);
846
            speed.append(h[1]);
847
            channel.append(h[2]);
848
 
590 FredericG 849
        for line in logfile:
850
            values = line.split(',')
596 FredericG 851
            for i in range(nbCols):
852
                data[i].append(int(values[i]))
590 FredericG 853
        logfile.close()
596 FredericG 854
 
855
        for c in range(nbCols):
599 FredericG 856
            if (len(data[c]) % 2) != 0:
857
                data[c].append(data[c][-1])
619 FredericG 858
            self.AddTest(descr[c], 0, 0, int(speed[c]), channel[c], data[c])
612 FredericG 859
 
613 FredericG 860
    def startMeasure(self, measureParams, dialog):
612 FredericG 861
        print "Start measuring"
590 FredericG 862
 
613 FredericG 863
        measureParams.serialPort = self.settings["serialport"].value
864
        measureParams.motorStartupSpeed = self.settings["startupspeed"].value
865
        measureParams.motorStartupSettlingTime = self.settings["startupsettling"].value
866
 
867
        self.measureThread = MeasureThread(measureParams, dialog)
612 FredericG 868
        self.measureThread.start()
590 FredericG 869
 
613 FredericG 870
    def cancelMeasurement(self):
871
        print "Measuring CANCEL"
872
 
873
        self.measureThread.stop()
874
 
612 FredericG 875
 
876
 
877
 
878
 
590 FredericG 879
 
586 FredericG 880
 
590 FredericG 881
 
584 FredericG 882
# end of class App
883
 
884
if __name__ == "__main__":
885
    VibrationTestGui = App(0)
886
    VibrationTestGui.MainLoop()