acquiresettings.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. """
  2. This Module Is the Acquiresettings subWindow.
  3. """
  4. from PyQt4 import QtGui, QtCore
  5. from collections import OrderedDict
  6. from ..base import kcgwidget as kcgw
  7. from ..base.backend import board
  8. from ..base.backend.board import available_boards
  9. from ..base import backendinterface as bif
  10. from ..base.groupedelements import Elements
  11. from .. import config
  12. from ..base.globals import glob as global_objects
  13. tr = kcgw.tr
  14. __widget_id__ = None
  15. class AcquireSettingsTab(kcgw.KCGWidgets):
  16. """
  17. A single tab in the acquire settings window
  18. """
  19. available_for_same_as = OrderedDict()
  20. def __init__(self, board_id, same_as_widgets, parent=None):
  21. super(AcquireSettingsTab, self).__init__()
  22. self.available_for_same_as[board_id] = True
  23. self.widgets = None # IMPORTANT: THIS WIDGET NEEDS A LIST OF ALL THE OTHER WIDGETS
  24. self.same_as_widgets = same_as_widgets
  25. self.parent = parent
  26. self.board_id = board_id
  27. self.layout = QtGui.QGridLayout()
  28. self.outerLayout = QtGui.QVBoxLayout()
  29. self.outerLayout.addLayout(self.layout)
  30. self.outerLayout.addStretch(1)
  31. self.setLayout(self.outerLayout)
  32. self.sameAsLabel = self.createLabel("Same as")
  33. self.sameAsCombo = QtGui.QComboBox()
  34. self.sameAsTick = self.createCheckbox("", connect=self.same_as)
  35. self.sameAs = QtGui.QHBoxLayout()
  36. self.sameAs.addWidget(self.sameAsCombo)
  37. self.sameAs.addWidget(self.sameAsTick)
  38. if available_boards.multi_board:
  39. self.layout.addWidget(self.sameAsLabel, 0, 0)
  40. self.layout.addLayout(self.sameAs, 0, 1)
  41. else:
  42. self.sameAsLabel.hide()
  43. # ---------[ Create Labels and corresponding Fields ]---------
  44. self.numOfOrbitsLabel = self.createLabel(tr("Label", "Number of orbits to observe"))
  45. self.numOfSkipOrbitsLabel = self.createLabel(tr("Label", "Number of orbits to skip"))
  46. self.numOfOrbitsSpinbox = self.createSpinbox(1, 10000000, connect=self.on_number_of_orbits_changed)
  47. self.numOfSkipOrbitsSpinbox = self.createSpinbox(0, 100, connect=self.on_number_of_skipped_orbits_changed)
  48. self.countLabel = self.createLabel(tr("Label", "Number of acquisitions"))
  49. self.countSpinbox = self.createSpinbox(1, 10000000, start_value=10, connect=self.on_count_changed)
  50. self.waitLabel = self.createLabel(tr("Label", "Wait(s)"))
  51. self.waitSpinbox = self.createSpinbox(0, 60, start_value=15, connect=self.on_wait_changed)
  52. self.simulatePilotBunch = self.createCheckbox(tr("Button", "Simulate Pilot Bunch"),
  53. connect=self.on_simulate_pilot_bunch_changed)
  54. self.buildSpectrogrammTickbox = self.createCheckbox(tr("Button", "Build Spectograms"),
  55. connect=self.on_build_spectrograms_changed)
  56. # ----------[ Trigger part ]--------------------
  57. self.trigger_skip_label = self.createLabel(tr("Label", "Number of trigger signals to skip"))
  58. self.trigger_skip_signals = self.createSpinbox(0, 1000, 1, start_value=0,
  59. connect=self.on_trigger_skip_signals_changed)
  60. self.timeout_label = self.createLabel(tr("Label", "Timeout (s)"))
  61. self.timeout = self.createSpinbox(0, 10000000, start_value=12, connect=self.on_trigger_timeout_changed)
  62. self.method_label = self.createLabel(tr("Label", "Method"))
  63. self.method = kcgw.Switch("1", "2")
  64. self.method.clicked.connect(self.on_trigger_method_changed)
  65. self.trigger_skip_label.hide()
  66. self.trigger_skip_signals.hide()
  67. self.timeout_label.hide()
  68. self.timeout.hide()
  69. self.method_label.hide()
  70. self.method.hide()
  71. self.trigger_tick = self.createCheckbox(tr("Label", "Use External Trigger"), connect=self.use_external_trigger)
  72. # -------[ register observers ]------
  73. board.get_board_config(board_id).observe(self.numOfOrbitsSpinbox,
  74. lambda x: self.set_value_silent(self.numOfOrbitsSpinbox, x),
  75. 'orbits_observe')
  76. board.get_board_config(board_id).observe(self.numOfSkipOrbitsSpinbox,
  77. lambda x: self.set_value_silent(self.numOfSkipOrbitsSpinbox, x),
  78. 'orbits_skip')
  79. board.get_board_config(board_id).observe(self.countSpinbox,
  80. lambda x: self.set_value_silent(self.countSpinbox, x),
  81. 'acquisition_count')
  82. board.get_board_config(board_id).observe(self.waitSpinbox,
  83. lambda x: self.set_value_silent(self.waitSpinbox, x),
  84. 'orbits_wait_time')
  85. board.get_board_config(board_id).observe(self.simulatePilotBunch,
  86. lambda x: self.tick_silent(self.simulatePilotBunch, x),
  87. 'pilot_bunch')
  88. board.get_board_config(board_id).observe(self.buildSpectrogrammTickbox,
  89. lambda x: self.tick_silent(self.buildSpectrogrammTickbox, x),
  90. 'build_spectrograms')
  91. board.get_board_config(board_id).observe(self.trigger_skip_signals,
  92. lambda x: self.set_value_silent(self.trigger_skip_signals, x),
  93. 'trigger_skip')
  94. board.get_board_config(board_id).observe(self.timeout,
  95. lambda x: self.set_value_silent(self.timeout, x), 'trigger_timeout')
  96. board.get_board_config(board_id).observe(self.trigger_tick, self.update_external_trigger, 'use_trigger')
  97. # -------[ register elements ]-------
  98. Elements.addItem(["acquire", "no_board", "acquire_"+str(board_id)],
  99. [
  100. self.numOfOrbitsSpinbox,
  101. self.numOfSkipOrbitsSpinbox,
  102. self.countSpinbox,
  103. self.waitSpinbox,
  104. self.buildSpectrogrammTickbox,
  105. self.simulatePilotBunch,
  106. self.trigger_skip_signals,
  107. self.timeout,
  108. self.method,
  109. self.trigger_tick
  110. ])
  111. # -------[ Add to grid ]-------------
  112. self.layout.addWidget(self.numOfOrbitsLabel, 1, 0)
  113. self.layout.addWidget(self.numOfOrbitsSpinbox, 1, 1)
  114. self.layout.addWidget(self.numOfSkipOrbitsLabel, 2, 0)
  115. self.layout.addWidget(self.numOfSkipOrbitsSpinbox, 2, 1)
  116. self.layout.addWidget(self.countLabel, 3, 0)
  117. self.layout.addWidget(self.countSpinbox, 3, 1)
  118. self.layout.addWidget(self.waitLabel, 4, 0)
  119. self.layout.addWidget(self.waitSpinbox, 4, 1)
  120. self.layout.addWidget(self.simulatePilotBunch, 9, 0)
  121. self.layout.addWidget(self.buildSpectrogrammTickbox, 9, 1)
  122. self.layout.addWidget(self.trigger_tick, 7, 0)
  123. line = QtGui.QFrame()
  124. line.setFrameShape(QtGui.QFrame.HLine)
  125. self.layout.addWidget(line, 8, 0, 1, 2)
  126. def build_same_as_list(self):
  127. """
  128. Build the list to show in the same-as drop down menu
  129. :return:
  130. """
  131. for wid_id, wid in self.widgets.iteritems():
  132. wid.sameAsCombo.clear()
  133. for key, value in self.available_for_same_as.iteritems():
  134. if value:
  135. if key is not wid_id:
  136. wid.sameAsCombo.addItem(available_boards.get_board_name_from_id(key))
  137. def same_as(self):
  138. """
  139. Toggle SameAs functionality
  140. :return: -
  141. """
  142. # This only does the ui
  143. bif._bif_enable_wait_cursor()
  144. QtGui.qApp.processEvents()
  145. c_t = available_boards.get_board_id_from_name(str(self.sameAsCombo.currentText()))
  146. if self.sameAsTick.isChecked():
  147. self.available_for_same_as[self.board_id] = False
  148. self.sameAsCombo.setEnabled(False)
  149. board.get_board_config(c_t).observe_all(
  150. board.get_board_config(self.board_id).update)
  151. self.widgets[c_t].sameAsTick.setEnabled(False)
  152. self.widgets[c_t].sameAsCombo.setEnabled(False)
  153. Elements.setEnabled('acquire_{}'.format(self.board_id), False)
  154. board.get_board_config(c_t).notify_all_observers()
  155. else:
  156. self.available_for_same_as[self.board_id] = True
  157. self.sameAsCombo.setEnabled(True)
  158. board.get_board_config(c_t).unobserve_all_observer(
  159. board.get_board_config(self.board_id).update)
  160. self.widgets[c_t].sameAsTick.setEnabled(True)
  161. self.widgets[c_t].sameAsCombo.setEnabled(True)
  162. Elements.setEnabled('acquire_{}'.format(self.board_id), True)
  163. # actual changes on board
  164. if c_t in self.same_as_widgets:
  165. self.same_as_widgets[c_t].append(self.board_id)
  166. else:
  167. self.same_as_widgets[c_t] = [self.board_id, ]
  168. self.build_same_as_list()
  169. bif._bif_disable_wait_cursor()
  170. def update_external_trigger(self, state):
  171. """
  172. Update the use external trigger tick
  173. :param state: the state to set the tick to
  174. """
  175. self.tick_silent(self.trigger_tick, state)
  176. self.use_external_trigger(state, update_config=False)
  177. def use_external_trigger(self, state, update_config=True):
  178. """
  179. Set use external trigger to state
  180. :param state: the state to set to
  181. :param update_config: true to update the board config
  182. """
  183. if state:
  184. if update_config:
  185. board.get_board_config(self.board_id).update('use_trigger', True)
  186. self.layout.removeWidget(self.waitLabel)
  187. self.layout.removeWidget(self.waitSpinbox)
  188. self.waitLabel.hide()
  189. self.waitSpinbox.hide()
  190. self.layout.addWidget(self.timeout_label, 4, 0)
  191. self.layout.addWidget(self.timeout, 4, 1)
  192. self.layout.addWidget(self.trigger_skip_label, 5, 0)
  193. self.layout.addWidget(self.trigger_skip_signals, 5, 1)
  194. self.layout.addWidget(self.method_label, 6, 0)
  195. self.layout.addWidget(self.method, 6, 1)
  196. self.timeout_label.show()
  197. self.timeout.show()
  198. self.trigger_skip_label.show()
  199. self.trigger_skip_signals.show()
  200. self.method_label.show()
  201. self.method.show()
  202. else:
  203. if update_config:
  204. board.get_board_config(self.board_id).update('use_trigger', False)
  205. self.layout.addWidget(self.waitLabel, 4, 0)
  206. self.layout.addWidget(self.waitSpinbox, 4, 1)
  207. self.waitLabel.show()
  208. self.waitSpinbox.show()
  209. self.layout.removeWidget(self.timeout_label)
  210. self.layout.removeWidget(self.timeout)
  211. self.layout.removeWidget(self.trigger_skip_label)
  212. self.layout.removeWidget(self.trigger_skip_signals)
  213. self.layout.removeWidget(self.method_label)
  214. self.layout.removeWidget(self.method)
  215. self.timeout_label.hide()
  216. self.timeout.hide()
  217. self.trigger_skip_label.hide()
  218. self.trigger_skip_signals.hide()
  219. self.method_label.hide()
  220. self.method.hide()
  221. QtCore.QCoreApplication.processEvents()
  222. try:
  223. self.parent.parent().adjustSize()
  224. except AttributeError: # when widget is opened with external trigger activated parent.parent() is None
  225. pass
  226. def set_value_silent(self, element, value):
  227. """
  228. Set a Value silent without notifying observers
  229. :param element: what element
  230. :param value: set to what value
  231. :return: -
  232. """
  233. element.blockSignals(True)
  234. element.setValue(value)
  235. element.blockSignals(False)
  236. def tick_silent(self, element, state):
  237. """
  238. Tick a tickbox without notifying observers
  239. :param element: what tickbox
  240. :param state: (bool) to what state
  241. :return: -
  242. """
  243. element.blockSignals(True)
  244. element.setChecked(state)
  245. element.blockSignals(False)
  246. def set_values(self):
  247. """
  248. Set Initial Values when creating this Window.
  249. This will read the appropriate Values from the base.backend.board.BoardConfiguration instance used in the gui.
  250. :return: -
  251. """
  252. # bk_get_config has to be done for each widget seperately (get dientifier by widget.board_id)
  253. self.set_value_silent(self.numOfOrbitsSpinbox, bif.bk_get_config(self.board_id, 'orbits_observe'))
  254. self.set_value_silent(self.numOfSkipOrbitsSpinbox, bif.bk_get_config(self.board_id, 'orbits_skip'))
  255. self.set_value_silent(self.countSpinbox, bif.bk_get_config(self.board_id, 'acquisition_count'))
  256. self.set_value_silent(self.waitSpinbox, bif.bk_get_config(self.board_id, 'orbits_wait_time'))
  257. self.tick_silent(self.buildSpectrogrammTickbox, bif.bk_get_config(self.board_id, 'build_spectrograms'))
  258. self.tick_silent(self.simulatePilotBunch, bif.bk_get_config(self.board_id, 'pilot_bunch'))
  259. self.update_external_trigger(bif.bk_get_config(self.board_id, 'use_trigger'))
  260. # -----------------[ Value Change Handlers ]---------------------------
  261. def on_number_of_orbits_changed(self):
  262. """
  263. Handle the change of the number of orbits
  264. """
  265. bif.bk_change_num_of_orbits(self.board_id, self.numOfOrbitsSpinbox.value())
  266. for b_id in self.same_as_widgets[self.board_id]:
  267. wid = self.widgets[b_id]
  268. bif.bk_change_num_of_orbits(wid.board_id, wid.numOfOrbitsSpinbox.value())
  269. def on_number_of_skipped_orbits_changed(self):
  270. """
  271. Handle the change of the number of skipped orbits
  272. """
  273. bif.bk_change_num_of_skipped_orbits(self.board_id, self.numOfSkipOrbitsSpinbox.value())
  274. for b_id in self.same_as_widgets[self.board_id]:
  275. wid = self.widgets[b_id]
  276. bif.bk_change_num_of_skipped_orbits(wid.board_id, wid.numOfSkipOrbitsSpinbox.value())
  277. def on_count_changed(self):
  278. """
  279. Handle the change of the count value
  280. """
  281. bif.bk_change_count(self.board_id, self.countSpinbox.value())
  282. for b_id in self.same_as_widgets[self.board_id]:
  283. wid = self.widgets[b_id]
  284. bif.bk_change_count(wid.board_id, wid.countSpinbox.value())
  285. def on_wait_changed(self):
  286. """
  287. Handle the change of the wait time
  288. """
  289. bif.bk_change_wait(self.board_id, self.waitSpinbox.value())
  290. for b_id in self.same_as_widgets[self.board_id]:
  291. wid = self.widgets[b_id]
  292. bif.bk_change_wait(wid.board_id, wid.waitSpinbox.value())
  293. def on_build_spectrograms_changed(self):
  294. """
  295. Handle the change of the build_spectrograms checkbox
  296. """
  297. bif.bk_change_build_spectrograms(self.board_id, self.buildSpectrogrammTickbox.checkState())
  298. for b_id in self.same_as_widgets[self.board_id]:
  299. wid = self.widgets[b_id]
  300. bif.bk_change_build_spectrograms(wid.board_id, wid.buildSpectrogrammTickbox.checkState())
  301. def on_simulate_pilot_bunch_changed(self):
  302. """
  303. Handle the change of the simulate_pilot_bunch checkbox
  304. """
  305. bif.bk_change_pilot_bunch(self.board_id, self.simulatePilotBunch.checkState())
  306. for b_id in self.same_as_widgets[self.board_id]:
  307. wid = self.widgets[b_id]
  308. bif.bk_change_pilot_bunch(wid.board_id, wid.simulatePilotBunch.checkState())
  309. def on_trigger_skip_signals_changed(self, value):
  310. """
  311. Handle change of trigger skip signal spinbox
  312. :param int value: the value to set trigger_skip to (the number of trigger signals to skip between acquisitions
  313. """
  314. bif.bk_update_config(self.board_id, 'trigger_skip', value)
  315. for b_id in self.same_as_widgets[self.board_id]:
  316. wid = self.widgets[b_id]
  317. bif.bk_update_config(wid.board_id, 'trigger_skip', value)
  318. def on_trigger_method_changed(self):
  319. """
  320. Handle change of trigger method.
  321. """
  322. bif.bk_update_config(self.board_id, 'trigger_method', 2 if self.method.state() else 1)
  323. for b_id in self.same_as_widgets[self.board_id]:
  324. wid = self.widgets[b_id]
  325. bif.bk_update_config(wid.board_id, 'trigger_method', 2 if self.method.satate() else 1)
  326. def on_trigger_timeout_changed(self, value):
  327. """
  328. Handle change of trigger timeout spinbox
  329. :param int value: the value to set the trigger_timout to
  330. """
  331. bif.bk_update_config(self.board_id, 'trigger_timeout', value)
  332. for b_id in self.same_as_widgets[self.board_id]:
  333. wid = self.widgets[b_id]
  334. bif.bk_update_config(wid.board_id, 'trigger_timeout', value)
  335. def closeEvent(self, event):
  336. """
  337. Event handler to handle the event of closing this window and gracefully delete resources and such
  338. :param event: the event to handle (gets passed to by PyQt)
  339. """
  340. board.get_board_config(self.board_id).unobserve(self.numOfOrbitsSpinbox, 'orbits_observe')
  341. board.get_board_config(self.board_id).unobserve(self.numOfSkipOrbitsSpinbox, 'orbits_skip')
  342. board.get_board_config(self.board_id).unobserve(self.countSpinbox, 'acquisition_count')
  343. board.get_board_config(self.board_id).unobserve(self.waitSpinbox, 'orbits_wait_time')
  344. board.get_board_config(self.board_id).unobserve(self.simulatePilotBunch, 'pilot_bunch')
  345. board.get_board_config(self.board_id).unobserve(self.buildSpectrogrammTickbox, 'build_spectrograms')
  346. board.get_board_config(self.board_id).unobserve(self.trigger_skip_signals, 'trigger_skip')
  347. board.get_board_config(self.board_id).unobserve(self.timeout, 'trigger_timeout')
  348. board.get_board_config(self.board_id).unobserve(self.trigger_tick, 'use_trigger')
  349. Elements.removeItem(["acquire_{}".format(self.board_id), "no_board_{}".format(self.board_id)],
  350. [
  351. self.numOfOrbitsSpinbox,
  352. self.numOfSkipOrbitsSpinbox,
  353. self.countSpinbox,
  354. self.waitSpinbox,
  355. self.buildSpectrogrammTickbox,
  356. self.simulatePilotBunch,
  357. self.trigger_skip_signals,
  358. self.timeout,
  359. self.method,
  360. self.trigger_tick
  361. ]
  362. )
  363. class AcquireSettings(kcgw.KCGWidgets):
  364. """
  365. This is the actual Acquire Settings Window.
  366. """
  367. def __init__(self, unique_id, parent=None):
  368. """
  369. Initialise the acquire settings window
  370. :param unique_id: the id for thiw widget
  371. :param parent: parent object
  372. :return: -
  373. """
  374. super(AcquireSettings, self).__init__()
  375. self.id = unique_id
  376. self.par = parent
  377. self.layout = QtGui.QHBoxLayout()
  378. self.setLayout(self.layout)
  379. self.setWindowTitle(tr("Heading", "Acquire Settings"))
  380. self.same_as_widgets = {i: [] for i in available_boards}
  381. self.widgets = OrderedDict({i: AcquireSettingsTab(i, self.same_as_widgets, self) for i in available_boards})
  382. if available_boards.multi_board:
  383. self.tabs = QtGui.QTabWidget()
  384. self.layout.addWidget(self.tabs)
  385. for wid in self.widgets.values():
  386. self.tabs.addTab(wid, available_boards.get_board_name_from_id(wid.board_id))
  387. wid.sameAsCombo.addItems([available_boards.get_board_name_from_id(i) for i in available_boards if i != wid.board_id])
  388. wid.widgets = self.widgets
  389. else:
  390. self.single_widget = self.widgets.values()[0]
  391. self.layout.addWidget(self.single_widget)
  392. for wid in self.widgets.values():
  393. wid.set_values()
  394. def show_tab(self, board_id):
  395. """
  396. Show the tab for the given board
  397. :param board_id: the id of the board to show
  398. """
  399. if not available_boards.multi_board:
  400. return
  401. self.tabs.setCurrentIndex(self.widgets.keys().index(board_id))
  402. def closeEvent(self, event):
  403. global __widget_id__
  404. for wid in self.widgets.values():
  405. wid.closeEvent(event)
  406. __widget_id__ = None
  407. del self.par.widgets[self.id]
  408. super(AcquireSettings, self).closeEvent(event)
  409. def add_acquire_settings_widget(board_id=None):
  410. """
  411. Add this widget to the gui.
  412. This function will actually open the subwindow.
  413. :return: -
  414. """
  415. global __widget_id__
  416. if __widget_id__:
  417. global_objects.get_global('area').widgets[__widget_id__].setFocus()
  418. if board_id is not None:
  419. global_objects.get_global('area').widgets[__widget_id__].show_tab(board_id)
  420. else:
  421. nid = kcgw.idg.genid()
  422. __widget_id__ = nid
  423. w = AcquireSettings(nid, global_objects.get_global('area'))
  424. global_objects.get_global('area').newWidget(w, "Acquire", nid, widget_type=4, minSize=True) # TODO: proper type
  425. if board_id is not None:
  426. global_objects.get_global('area').widgets[__widget_id__].show_tab(board_id)
  427. def setValueSilent(key, value):
  428. """
  429. Set values without notifying observers
  430. :param key: the key
  431. :param value: the value to set
  432. :return: -
  433. """
  434. if not __widget_id__:
  435. return
  436. global_objects.get_global('area').widgets[__widget_id__].blockSignals(True)
  437. if key == "orbits_observe":
  438. global_objects.get_global('area').widgets[__widget_id__].numOfOrbitsSpinbox.setValue(value)
  439. if key == "orbits_skip":
  440. global_objects.get_global('area').widgets[__widget_id__].numOfSkipOrbitsSpinbox.setValue(value)
  441. global_objects.get_global('area').widgets[__widget_id__].blockSignals(False)
  442. kcgw.register_widget(QtGui.QIcon(config.install_path + config.acquireSettingsIcon), tr("Heading", "Acquire Settings"), add_acquire_settings_widget, "Ctrl+A")