qgpib_plotter.py

changeset 32
59da528bc470
parent 31
c869766e25ff
child 33
61809bb871bf
equal deleted inserted replaced
31:c869766e25ff 32:59da528bc470
1 #
2
3 import os, sys
4 import time
5
6 from PyQt4 import QtGui, QtCore, uic
7 from PyQt4.QtCore import SIGNAL, Qt
8
9 if "-m" in sys.argv:
10 from gpib_plotter_mockup import GPIBplotter
11 else:
12 from gpib_plotter import GPIBplotter
13 from hpgl_qt import QHPGLPlotterWidget
14
15 form_class, base_class = uic.loadUiType(os.path.join(os.path.dirname(__file__), "qhpgl_plotter.ui"))
16
17 from qpreferences import PreferenceItem, AbstractPreferences, PreferencesEditor
18
19 class Preferences(AbstractPreferences):
20 ORGANISATION="Logilab"
21 APPLICATION="qgpib_plotter"
22
23 device = PreferenceItem('/dev/ttyUSB0', name=u'device', description=u'GPIB device')
24 address = PreferenceItem(5, name=u'GPIB address')
25 _pos = PreferenceItem(basetype=QtCore.QPoint)
26 _size = PreferenceItem(basetype=QtCore.QSize)
27 _appState = PreferenceItem(basetype=QtCore.QByteArray)
28
29
30 class QtHPGLPlotter(QtGui.QMainWindow, form_class):
31 def __init__(self, parent=None):
32 QtGui.QMainWindow.__init__(self, parent)
33 self._plots = {}
34 self._prefs = Preferences()
35 self.setupUi()
36 self.initializeGPIB()
37 if self._prefs._pos:
38 self.move(self._prefs._pos)
39 if self._prefs._size:
40 self.resize(self._prefs._size)
41 if self._prefs._appState:
42 self.restoreState(self._prefs._appState)
43
44 def setupUi(self):
45 form_class.setupUi(self, self) # call qtdesigner generated form creation
46 # actions defined in designer
47 self.connect(self.actionPreferences, SIGNAL('triggered(bool)'),
48 self.preferencesTriggered)
49 self.connect(self.actionQuit, SIGNAL('triggered(bool)'),
50 self.quitTriggered)
51 self.actionQuit.setShortcut(QtGui.QKeySequence(u'Ctrl+Q'))
52 self.connect(self.actionOpen, SIGNAL('triggered(bool)'),
53 self.openTriggered)
54 self.actionOpen.setShortcut(QtGui.QKeySequence(u'Ctrl+O'))
55 self.connect(self.actionSave, SIGNAL('triggered(bool)'),
56 self.saveTriggered)
57 self.actionSave.setShortcut(QtGui.QKeySequence(u'Ctrl+S'))
58 self.connect(self.actionSaveAs, SIGNAL('triggered(bool)'),
59 self.saveAsTriggered)
60
61 self.plotterWidget = QHPGLPlotterWidget(self)
62 self.setCentralWidget(self.plotterWidget)
63
64 self.connect(self.captureButton, SIGNAL("toggled(bool)"),
65 self.captureToggled)
66
67 self._plots_list = QtGui.QStringListModel()
68 self.plotsView.setModel(self._plots_list)
69 self.connect(self.plotsView, SIGNAL('activated(const QModelIndex&)'),
70 self.currentPlotChanged)
71 self.connect(self.plotsView.selectionModel(),
72 SIGNAL('currentChanged(const QModelIndex&, const QModelIndex&)'),
73 self.currentPlotChanged)
74
75 def currentPlotChanged(self, index, old_index=None):
76 if index.isValid():
77 value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString())
78
79 self.plotterWidget.clear()
80 self.plotterWidget.parse(self._plots[value])
81
82 def preferencesTriggered(self, checked=False):
83 PreferencesEditor(self._prefs, self).exec_()
84
85 def quitTriggered(self, checked=False):
86 self.close()
87
88 def closeEvent(self, event):
89 if 1:
90 #if self.promptForSave():
91 self._prefs._pos = self.pos()
92 self._prefs._size = self.size()
93 self._prefs._appState = self.saveState()
94 event.accept()
95 else:
96 event.ignore()
97
98 def openTriggered(self, checked=False):
99 filenames = QtGui.QFileDialog.getOpenFileNames(self, "Open a HPGL file to display", '.', 'HPGL files (*.plt)\nAll files (*)')
100 for filename in filenames:
101 filename = str(filename)
102 if os.path.exists(filename):
103 data = open(filename).read()
104 name = os.path.basename(filename)
105 name = os.path.splitext(name)[0]
106 lst = self.plotsView.model().stringList()
107 lst.append(name)
108 self._plots[name] = data
109 self.plotsView.model().setStringList(lst)
110
111 if not self.plotsView.currentIndex().isValid():
112 self.plotsView.setCurrentIndex(self.plotsView.model().index(0, 0))
113
114 def plotReceived(self, num):
115 self._receiving = False
116 self.setReceivingLed()
117 plot, timestamp = self.captureThread.getPlot(num)
118 name = "plot_%s"%(num)
119 lst = self.plotsView.model().stringList()
120 lst.append(name)
121 self._plots[name] = plot
122 self.plotsView.model().setStringList(lst)
123
124 def plotStarted(self):
125 self._receiving = True
126 self.setReceivingLed()
127
128 def saveTriggered(self, checked=False):
129 print "save"
130 def saveAsTriggered(self, checked=False):
131 print "saveAs"
132
133 def initializeGPIB(self):
134 self._online = False
135 try:
136 self.gpib_plotter = QGPIBplotter(device=self._prefs.device,
137 address=self._prefs.address,
138 )
139 self.captureThread = GPIBReceiver(self.gpib_plotter)
140 self.connect(self.captureThread, SIGNAL('plotReceived(int)'),
141 self.plotReceived)
142 self.connect(self.captureThread, SIGNAL('plotStarted()'),
143 self.plotStarted)
144 self.captureThread.start()
145 except Exception, e:
146 #print e
147 self.gpib_plotter = None
148 self.setCaptureLed()
149
150 def captureToggled(self, state):
151 if state:
152 if self.gpib_plotter is None:
153 self.initializeGPIB()
154 if self.gpib_plotter is None:
155 QtGui.QMessageBox.critical(self, self.tr("GPIB error"),
156 self.tr("<b>Unable to initialize GPIB connection</b>.<br>Please check your GPIB dongle and settings."))
157 self._online = False
158 self.setCaptureLed()
159 return
160 self._online = True
161 self.captureThread.startCapture()
162 else:
163 if self.captureThread:
164 self.captureThread.stopCapture()
165 self._online = False
166 self.setCaptureLed()
167
168 def setCaptureLed(self):
169 if self._online:
170 icn = QtGui.QIcon(':/icons/led_green.svg')
171 else:
172 icn = QtGui.QIcon(':/icons/led_green_off.svg')
173 self.captureButton.setIcon(icn)
174 self.captureButton.setChecked(self._online)
175
176 def setReceivingLed(self):
177 if self._receiving:
178 icn = QtGui.QIcon(':/icons/led_red.svg')
179 else:
180 icn = QtGui.QIcon(':/icons/led_red_off.svg')
181 self.receivingButton.setIcon(icn)
182
183 class QGPIBplotter(GPIBplotter):
184 def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
185 address=5):
186 GPIBplotter.__init__(self, device, baudrate, timeout, address)
187 self.emitter = None
188
189 def plotStarted(self):
190 if self.emitter:
191 self.emitter.emit(SIGNAL('plotStarted()'))
192 #self.emitter.msleep(1)
193
194 class GPIBReceiver(QtCore.QThread):
195 def __init__(self, cnx):
196 QtCore.QThread.__init__(self)
197 self.gpibplotter = cnx
198 self.gpibplotter.emitter = self
199
200 self._cancelmutex = QtCore.QMutex()
201 self._cancel = False
202 #self._nreceived = 0
203 self._plotsmutex = QtCore.QMutex()
204 self._plots = []
205 self._startstopmutex = QtCore.QMutex()
206 self._startstop = QtCore.QWaitCondition()
207 self._capturing = False
208
209 def cancel(self):
210 self._cancelmutex.lock()
211 self._cancel = True
212 self._cancelmutex.unlock()
213
214 def startCapture(self):
215 self._startstop.wakeOne()
216
217 def stopCapture(self):
218 self._startstopmutex.lock()
219 self._capturing = False
220 self._startstopmutex.unlock()
221
222 def run(self):
223 while 1:
224 self._cancelmutex.lock()
225 if self._cancel:
226 return
227 self._cancelmutex.unlock()
228 self._startstopmutex.lock()
229 if not self._capturing:
230 self._startstop.wait(self._startstopmutex)
231 self._capturing = True
232 self._startstopmutex.unlock()
233
234 plot = self.gpibplotter.load_plot(wait_timeout=0.1)
235 timestamp = time.time()
236 if plot:
237 self._plotsmutex.lock()
238 self._plots.append((plot, timestamp))
239 n = len(self._plots)
240 self._plotsmutex.unlock()
241 self.emit(SIGNAL('plotReceived(int)'), n-1)
242 self.msleep(10)
243
244 def getPlot(self, num):
245 self._plotsmutex.lock()
246 try:
247 return self._plots[num]
248 finally:
249 self._plotsmutex.unlock()
250
251
252
253
254 def main():
255 import optparse
256 opt = optparse.OptionParser('A simple PyQt4 HP7470A GPIB plotter emulator for USB-GPIB bundle (ProLogix)')
257 opt.add_option('-m', '--mockup', default=False,
258 action="store_true",
259 dest='mockup',
260 help='Use a pseudo GPIB connection (for test purpose)',
261 )
262 opt.add_option('-v', '--verbose', default=False,
263 action="store_true",
264 dest="verbose",
265 help="Verbose mode",)
266
267 options, argv = opt.parse_args(sys.argv)
268
269 if options.verbose:
270 sys.stderr.write('connection established\n')
271
272 a = QtGui.QApplication(argv)
273 w = QtHPGLPlotter()
274 w.show()
275 a.exec_()
276
277 if __name__ == '__main__':
278 main()

mercurial