|
@@ -0,0 +1,1444 @@
|
|
|
+"""
|
|
|
+This is the interface to the backend.
|
|
|
+It is used to make the backend easily interchangable.
|
|
|
+All Functions that interface directly with the backend are prefixed with be_
|
|
|
+Functions only used internal in this module will be prefixed _bif_
|
|
|
+"""
|
|
|
+
|
|
|
+import logging
|
|
|
+import time
|
|
|
+from datetime import datetime as dt
|
|
|
+import os
|
|
|
+import copy
|
|
|
+from PyQt4 import QtGui, QtCore
|
|
|
+import numpy as np
|
|
|
+from backend import board
|
|
|
+from backend.board import available_boards
|
|
|
+from backend import io
|
|
|
+from backend import dataset
|
|
|
+from groupedelements import Buttons, Elements, live_plot_windows
|
|
|
+import storage
|
|
|
+from .. import config
|
|
|
+import kcgwidget as kcgw
|
|
|
+from kcgwidget import error
|
|
|
+from callbacks import callbacks
|
|
|
+from log import log
|
|
|
+from globals import glob as global_objects
|
|
|
+
|
|
|
+tr = kcgw.tr
|
|
|
+
|
|
|
+livePlotData = None
|
|
|
+
|
|
|
+
|
|
|
+def initStatus(st):
|
|
|
+ """
|
|
|
+ Initialize Status variables. These variables are used to transfer status variables over different modules.
|
|
|
+ :param st: variable to use (most likely a DummyStorage instance)
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ st.continuous_read = False
|
|
|
+ st.calibrated = False
|
|
|
+ st.synced = False
|
|
|
+ st.defaults_set = False
|
|
|
+ st.status_text = tr("sw", "Ready")
|
|
|
+ st.time_scan = False
|
|
|
+ st.wait = False
|
|
|
+ st.last_file = None
|
|
|
+ st.board_connected = True
|
|
|
+ st.continuous_interval = 1000
|
|
|
+
|
|
|
+
|
|
|
+# -----------[ Backend Interface ]----------------------
|
|
|
+def _bif_enable_wait_cursor():
|
|
|
+ """
|
|
|
+ Show the "Wait Cursor"
|
|
|
+ """
|
|
|
+ QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))
|
|
|
+
|
|
|
+
|
|
|
+def _bif_disable_wait_cursor():
|
|
|
+ """
|
|
|
+ Show the normal Cursor
|
|
|
+ """
|
|
|
+ QtGui.QApplication.restoreOverrideCursor()
|
|
|
+
|
|
|
+
|
|
|
+def _bif_continuous_read_is_enabled(board_id, popup_title_text=None):
|
|
|
+ """
|
|
|
+ Checks if continuous read is enabled and if yes shows a popup dialog to ask if it shall be disabled
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param popup_title_text: Text to display in the popup that asks to disable continuous read
|
|
|
+ :return: bool (True if continuous read is enabled and not disabled in popup else False)
|
|
|
+ """
|
|
|
+ if board.get_board_status(board_id).continuous_read:
|
|
|
+ if not available_boards.multi_board:
|
|
|
+ popup = PopupDialog(tr("Dialog", "Continuous read is currently active!\nStop continuous read and proceed?"),
|
|
|
+ title=popup_title_text)
|
|
|
+ else:
|
|
|
+ popup = PopupDialog(tr("Dialog", "Board {board_id}\nContinuous read is currently active!\nStop continuous read and proceed?").format(board_id=board_id),
|
|
|
+ title=popup_title_text)
|
|
|
+ popup.exec_()
|
|
|
+ popup.deleteLater()
|
|
|
+ if popup.get_return_value() is False:
|
|
|
+ return False
|
|
|
+ else:
|
|
|
+ _bif_set_continuous_read_inactive(board_id)
|
|
|
+ Elements.setChecked("continuousread_"+str(board_id), False)
|
|
|
+ return True
|
|
|
+ else:
|
|
|
+ return False
|
|
|
+
|
|
|
+
|
|
|
+def bk_status_readout():
|
|
|
+ for brd in available_boards.board_ids:
|
|
|
+ _bif_status_readout(brd)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_status_readout(board_id):
|
|
|
+ """
|
|
|
+ Read Status from board and update variables
|
|
|
+ as well as enable and disable corresponding Buttons
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ # part_TODO: NOTE: Problem with this is that certain buttons will be greyed out until other buttons are pressed
|
|
|
+ # part_TODO: even if only the gui is restarted and the board is in the same state
|
|
|
+ if kcgw.testing:
|
|
|
+ return
|
|
|
+ if board.is_active(board_id):
|
|
|
+ Buttons.setEnabled("after_start_{}".format(board_id), True)
|
|
|
+ Buttons.setEnabled("start_board_{}".format(board_id), False)
|
|
|
+ Buttons.setEnabled("continuous_read_{}".format(board_id), True)
|
|
|
+
|
|
|
+ # MenuItems.setEnabled("continuous_read", True)
|
|
|
+ else:
|
|
|
+ board.get_board_status(board_id).calibrated = False
|
|
|
+ board.get_board_status(board_id).synced = False
|
|
|
+ board.get_board_status(board_id).defaults_set = False
|
|
|
+ Buttons.setEnabled("after_start_{}".format(board_id), False)
|
|
|
+ Buttons.setEnabled("continuous_read_{}".format(board_id), False)
|
|
|
+ Buttons.setEnabled("synchronize_{}".format(board_id), board.get_board_status(board_id).calibrated)
|
|
|
+ Buttons.setEnabled("set_defaults_{}".format(board_id), board.get_board_status(board_id).synced)
|
|
|
+ Buttons.setEnabled("acquire_{}".format(board_id), board.get_board_status(board_id).synced)
|
|
|
+ Buttons.setEnabled("acquireTrigger_{}".format(board_id), board.get_board_status(board_id).synced)
|
|
|
+ Elements.setEnabled("timing_{}".format(board_id), board.get_board_status(board_id).synced)
|
|
|
+
|
|
|
+ storage.get_board_specific_storage(board_id).update_LED()
|
|
|
+
|
|
|
+
|
|
|
+backup_readout = bk_status_readout
|
|
|
+
|
|
|
+
|
|
|
+class PopupDialog(QtGui.QDialog):
|
|
|
+ """
|
|
|
+ Simple Class to show a popup dialog.
|
|
|
+ """
|
|
|
+
|
|
|
+ def __init__(self, text, title=None, parent=None):
|
|
|
+ QtGui.QDialog.__init__(self, parent)
|
|
|
+ self.text = text
|
|
|
+ self.setWindowTitle(title if title else tr("Dialog", "User action required"))
|
|
|
+ self.do_layout()
|
|
|
+ self.return_value = False
|
|
|
+
|
|
|
+ def do_layout(self):
|
|
|
+ size = QtCore.QSize(200, 200)
|
|
|
+ # self.setMaximumSize(size)
|
|
|
+ self.setMinimumSize(size)
|
|
|
+ box = QtGui.QVBoxLayout()
|
|
|
+ self.text_label = QtGui.QLabel(self.text)
|
|
|
+ self.text_label.setAlignment(QtCore.Qt.AlignCenter)
|
|
|
+ box.addWidget(self.text_label)
|
|
|
+ self.okay_btn = QtGui.QPushButton(tr("Button", "Ok"))
|
|
|
+ self.okay_btn.setStyleSheet("padding: 15px;")
|
|
|
+ self.okay_btn.clicked.connect(self.on_okay)
|
|
|
+ box.addWidget(self.okay_btn)
|
|
|
+ box.addSpacerItem(QtGui.QSpacerItem(1, 20))
|
|
|
+ self.cancel_btn = QtGui.QPushButton(tr("Button", "Cancel"))
|
|
|
+ self.cancel_btn.setStyleSheet("padding: 15px;")
|
|
|
+ self.cancel_btn.clicked.connect(self.on_cancel)
|
|
|
+ box.addWidget(self.cancel_btn)
|
|
|
+ self.setLayout(box)
|
|
|
+
|
|
|
+ def on_okay(self):
|
|
|
+ self.return_value = True
|
|
|
+ self.close()
|
|
|
+
|
|
|
+ def on_cancel(self):
|
|
|
+ self.close()
|
|
|
+
|
|
|
+ def get_return_value(self):
|
|
|
+ return self.return_value
|
|
|
+
|
|
|
+
|
|
|
+def bk_start_board(board_id):
|
|
|
+ """
|
|
|
+ Start the Board.
|
|
|
+ This will set initial Registers to power up the Board.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ _bif_enable_wait_cursor()
|
|
|
+ log(board_id=board_id, additional="Starting Board - following values are probably default values")
|
|
|
+
|
|
|
+ sequence = board.startup_sequence(board_id)
|
|
|
+ number = sequence.next()
|
|
|
+
|
|
|
+ if _bif_continuous_read_is_enabled(board_id, tr("Button", "Start Board")):
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ return False
|
|
|
+
|
|
|
+ try:
|
|
|
+ if board.is_active(board_id):
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+ return
|
|
|
+
|
|
|
+ logging.info("Activating Board")
|
|
|
+ sequence.next()
|
|
|
+ time.sleep(1.0)
|
|
|
+ dialog1 = PopupDialog(tr("Button", "Switch On the power supply --> FIRST <-- (on board {0})".format(board_id)))
|
|
|
+ dialog1.exec_()
|
|
|
+ dialog1.deleteLater()
|
|
|
+
|
|
|
+ if not dialog1.get_return_value():
|
|
|
+ logging.error("Starting procedure canceled")
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ return False
|
|
|
+
|
|
|
+ logging.info("Switch ON T/Hs")
|
|
|
+ sequence.next()
|
|
|
+ time.sleep(0.1)
|
|
|
+ dialog2 = PopupDialog(tr("Dialog", "Switch On the power supply --> SECOND <-- (on board {0})".format(board_id)))
|
|
|
+ dialog2.exec_()
|
|
|
+ dialog2.deleteLater()
|
|
|
+
|
|
|
+ if not dialog2.get_return_value():
|
|
|
+ logging.info("Starting procedure canceled")
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ return False
|
|
|
+
|
|
|
+ logging.info("Switch ON ADCs")
|
|
|
+ sequence.next()
|
|
|
+ time.sleep(0.1)
|
|
|
+
|
|
|
+ sequence.next()
|
|
|
+ time.sleep(1.0)
|
|
|
+
|
|
|
+ for step in sequence:
|
|
|
+ time.sleep(0.1)
|
|
|
+
|
|
|
+ logging.info("Board started successfully!")
|
|
|
+ except board.BoardError as e:
|
|
|
+ logging.error("Starting board failed: {}".format(str(e)))
|
|
|
+
|
|
|
+ bk_update_config(board_id, 'header', bk_get_config(board_id, 'header'))
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+
|
|
|
+
|
|
|
+class _bif_ProgressBar(QtGui.QProgressBar):
|
|
|
+ """
|
|
|
+ Simple Progressbar class.
|
|
|
+ """
|
|
|
+
|
|
|
+ def __init__(self, min, max, text):
|
|
|
+ super(_bif_ProgressBar, self).__init__()
|
|
|
+ self.setRange(min, max)
|
|
|
+ self.setMaximumHeight(18)
|
|
|
+ # kcgw.statusbar.clearMessage()
|
|
|
+ self.label = QtGui.QLabel(text)
|
|
|
+ global_objects.get_global('statusbar').insertWidget(0, self.label)
|
|
|
+ global_objects.get_global('statusbar').insertWidget(1, self)
|
|
|
+ self.setValue(0)
|
|
|
+ QtGui.qApp.processEvents()
|
|
|
+
|
|
|
+ def remove(self, timeout=None):
|
|
|
+ """
|
|
|
+ Remove this instance of a progressbar
|
|
|
+ :param timeout: the time from calling this function to wanishing of the progressbar
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+
|
|
|
+ def remove_progressbar():
|
|
|
+ global_objects.get_global('statusbar').removeWidget(self)
|
|
|
+ global_objects.get_global('statusbar').removeWidget(self.label)
|
|
|
+ # kcgw.statusbar.showMessage(board.status.status_text)
|
|
|
+ self.destroy()
|
|
|
+
|
|
|
+ if timeout:
|
|
|
+ QtCore.QTimer.singleShot(timeout, remove_progressbar)
|
|
|
+ else:
|
|
|
+ remove_progressbar()
|
|
|
+
|
|
|
+
|
|
|
+# thread = None
|
|
|
+# cal = None
|
|
|
+def bk_calibrate(board_id, do_the_rest=None):
|
|
|
+ """
|
|
|
+ Send commands to the board that will enable it to calibrate itself.
|
|
|
+ This function checks if a read command is still running. BUT: It does not check if
|
|
|
+ the board is acquiring or something like this.
|
|
|
+ So Another instance of KCG can still be acquiring or calibrating at the same time. This can be dangerous.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param do_the_rest: function to call after calibration. This is used when "Prepare Board" is pressed.
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ log(board_id=board_id, additional="Calibrate")
|
|
|
+ thread = storage.get_board_specific_storage(board_id).setdefault('CalibrateThread', storage.ThreadStorage())
|
|
|
+ if thread.running:
|
|
|
+ logging.info("Calibration already running")
|
|
|
+ return
|
|
|
+ _bif_enable_wait_cursor()
|
|
|
+ if _bif_continuous_read_is_enabled(board_id, tr("Button", "Calibrate Board")):
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ return
|
|
|
+
|
|
|
+ sequence = board.calibration_sequence(board_id)
|
|
|
+ number = sequence.next()
|
|
|
+ progressbar = _bif_ProgressBar(0, number, tr("sw", "Calibrating"))
|
|
|
+
|
|
|
+ class Calibrate(QtCore.QObject):
|
|
|
+ """
|
|
|
+ Class to use as thread class. NOTE: this is not used at the moment.
|
|
|
+ """
|
|
|
+ update_progressbar_signal = QtCore.pyqtSignal(int)
|
|
|
+ finished = QtCore.pyqtSignal()
|
|
|
+
|
|
|
+ def calibrate(self):
|
|
|
+ try:
|
|
|
+ logging.info('Started Board Calibration')
|
|
|
+ for idx, step in enumerate(sequence):
|
|
|
+ time.sleep(0.5)
|
|
|
+ self.update_progressbar_signal.emit(idx)
|
|
|
+ board.get_board_status(board_id).calibrated = True
|
|
|
+ except board.BoardError as e:
|
|
|
+ logging.error("Calibration failed: {}".format(str(e)))
|
|
|
+ # self.do_status_readout()
|
|
|
+ self.finished.emit()
|
|
|
+ return
|
|
|
+
|
|
|
+ logging.info("Board Calibration successful!")
|
|
|
+ self.finished.emit()
|
|
|
+
|
|
|
+ def thread_quit():
|
|
|
+ thread.stop()
|
|
|
+ bk_status_readout()
|
|
|
+ progressbar.remove(0)
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ if do_the_rest: # execute sync and set defaults (this is set if prepare board was pressed)
|
|
|
+ do_the_rest(board_id)
|
|
|
+
|
|
|
+ cal = Calibrate()
|
|
|
+ thread.register(cal)
|
|
|
+ thread.connect('update_progressbar_signal', progressbar.setValue)
|
|
|
+ thread.connect('finished', thread_quit)
|
|
|
+ thread.start('calibrate')
|
|
|
+
|
|
|
+def bk_sync_board(board_id):
|
|
|
+ """
|
|
|
+ Sends commands to the board to sync with triggers.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ _bif_enable_wait_cursor()
|
|
|
+ log(board_id=board_id, additional="Synchronize")
|
|
|
+ if _bif_continuous_read_is_enabled(board_id, tr("Dialog", "Synchronize Board")):
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ return
|
|
|
+
|
|
|
+ progressbar = _bif_ProgressBar(0, 100, tr("sw", "Synchronizing"))
|
|
|
+ sequence = board.synchronisation_sequence(board_id)
|
|
|
+ try:
|
|
|
+ sequence.next() # skip number
|
|
|
+ logging.info("Synchronize PLLs")
|
|
|
+ sequence.next()
|
|
|
+ for i in range(1, 101):
|
|
|
+ time.sleep(0.01)
|
|
|
+ progressbar.setValue(i)
|
|
|
+ sequence.next()
|
|
|
+ except board.BoardError as e:
|
|
|
+ logging.error("Synchronization failed: {}".format(str(e)))
|
|
|
+ progressbar.remove(0)
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+ return
|
|
|
+
|
|
|
+ progressbar.remove(0)
|
|
|
+
|
|
|
+ logging.info("Board synchronization successful!")
|
|
|
+ # self.set_defaults_button.setEnabled(True)
|
|
|
+ board.get_board_status(board_id).synced = True
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+
|
|
|
+
|
|
|
+def bk_write_values(board_id, defaults=False):
|
|
|
+ """
|
|
|
+ Write values to board.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param defaults: (bool) if True Writes default values
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ _bif_enable_wait_cursor()
|
|
|
+ if defaults:
|
|
|
+ log(board_id=board_id, additional="Set Default Values")
|
|
|
+ else:
|
|
|
+ log(board_id=board_id, additional="Update Values on board")
|
|
|
+ if _bif_continuous_read_is_enabled(board_id, tr("Dialog", "Update Values on Board")):
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ return
|
|
|
+
|
|
|
+ sequence = board.write_value_sequence(board_id)
|
|
|
+ number = sequence.next()
|
|
|
+ if defaults:
|
|
|
+ board.get_board_config(board_id)._set_defaults()
|
|
|
+ progressbar = _bif_ProgressBar(0, number, tr("sw", "Setting Defaults"))
|
|
|
+ logging.info("Setting default Values")
|
|
|
+ else:
|
|
|
+ progressbar = _bif_ProgressBar(0, number, tr("sw", "Updating Values on Board"))
|
|
|
+ logging.info("Updating Values")
|
|
|
+
|
|
|
+ try:
|
|
|
+ for idx, step in enumerate(sequence):
|
|
|
+ time.sleep(0.1)
|
|
|
+ progressbar.setValue(idx)
|
|
|
+ except board.BoardError as e:
|
|
|
+ logging.error("Updating Values failed: {}".format(str(e)))
|
|
|
+ progressbar.remove(0)
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+ return
|
|
|
+
|
|
|
+ board.get_board_status(board_id).defaults_set = True
|
|
|
+ progressbar.remove(0)
|
|
|
+
|
|
|
+ if defaults:
|
|
|
+ logging.info("Default values set successfully!")
|
|
|
+ else:
|
|
|
+ logging.info("Updated values successfully!")
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+ board.get_board_config(board_id).notify_all_observers()
|
|
|
+
|
|
|
+
|
|
|
+def bk_stop_board(board_id):
|
|
|
+ """
|
|
|
+ Stops the board and shuts it down
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ _bif_enable_wait_cursor()
|
|
|
+ log(board_id=board_id, additional="Stop Board")
|
|
|
+ if _bif_continuous_read_is_enabled(board_id, tr("Dialog", "Soft Reset Board")):
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ return
|
|
|
+
|
|
|
+ try:
|
|
|
+ logging.info("Switching Off Board {}".format(board_id))
|
|
|
+ board.pci.write('0x01', '0x9040')
|
|
|
+ board.pci.stop_dma(board_id)
|
|
|
+ board.stop_board(board_id)
|
|
|
+ time.sleep(0.5)
|
|
|
+ except board.BoardError as e:
|
|
|
+ logging.error("Sequence failed: {}".format(str(e)))
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+ return
|
|
|
+
|
|
|
+ logging.info("Board switched off successfully!")
|
|
|
+ Buttons.setEnabled("after_start_{}".format(board_id), False)
|
|
|
+ Buttons.setEnabled("start_board_{}".format(board_id), True)
|
|
|
+ board.get_board_status(board_id).calibrated = False
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+
|
|
|
+def bk_soft_reset(board_id):
|
|
|
+ """
|
|
|
+ Perform a soft reset.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ _bif_enable_wait_cursor()
|
|
|
+ log(board_id=board_id, additional="Soft Reset")
|
|
|
+ if _bif_continuous_read_is_enabled(board_id, tr("Dialog", "Soft Reset Board")):
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ return
|
|
|
+
|
|
|
+ try:
|
|
|
+ logging.info("Soft-Resetting Board {}...".format(board_id))
|
|
|
+ board.soft_reset(board_id)
|
|
|
+ except board.BoardError as e:
|
|
|
+ logging.error("Sequence failed: {}".format(str(e)))
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+ return
|
|
|
+
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+ bk_status_readout()
|
|
|
+ board.get_board_config(board_id).update('header', True) # reset header (might be reset by soft reset)
|
|
|
+ logging.info("Soft-Reset successful.")
|
|
|
+
|
|
|
+
|
|
|
+def bk_update_config(board_id, key, value, silent=False):
|
|
|
+ """
|
|
|
+ Interface to the update command of the BoardConfiguration class.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param key: Key to update
|
|
|
+ :param value: Value to set for key
|
|
|
+ :param silent: (bool) if True do not inform observers on update
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ if silent:
|
|
|
+ board.get_board_config(board_id).updateSilent(key, value)
|
|
|
+ else:
|
|
|
+ board.get_board_config(board_id).update(key, value)
|
|
|
+ except board.BoardError as e:
|
|
|
+ logging.error("Setting value of {} failed: {}".format(key, str(e)))
|
|
|
+
|
|
|
+
|
|
|
+def bk_get_config(board_id, key):
|
|
|
+ """
|
|
|
+ Interface to the get command of the BoardConfiguration class.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param key: Key to get the value for
|
|
|
+ :return: value stored for key
|
|
|
+ """
|
|
|
+ return board.get_board_config(board_id).get(key)
|
|
|
+
|
|
|
+
|
|
|
+def bk_get_board_status(board_id, status_variable):
|
|
|
+ """
|
|
|
+ Interface to the status class for each board.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param status_variable: Key to get the value for
|
|
|
+ :return: value stored for key
|
|
|
+ """
|
|
|
+ return getattr(board.get_board_status(board_id), status_variable, None)
|
|
|
+
|
|
|
+
|
|
|
+def bk_get_status(board_id):
|
|
|
+ """
|
|
|
+ Interface to the get_status of the board
|
|
|
+ NOTE: This is not get_board_status
|
|
|
+ :return: status dictionary
|
|
|
+ """
|
|
|
+ return board.get_status(board_id)
|
|
|
+
|
|
|
+
|
|
|
+def bk_get_board_config(board_id):
|
|
|
+ """
|
|
|
+ Get the board config instance
|
|
|
+ :param board_id: the id of the board
|
|
|
+ :return: the config instance
|
|
|
+ """
|
|
|
+ return board.get_board_config(board_id)
|
|
|
+
|
|
|
+def bk_change_num_of_orbits(board_id, value, silent=False):
|
|
|
+ """
|
|
|
+ Send new number of orbits to board and update in config
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param value: the value to send
|
|
|
+ :param silent: (bool) if True do not inform observers on update
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ bk_update_config(board_id, "orbits_observe", value, silent=silent)
|
|
|
+
|
|
|
+
|
|
|
+def bk_change_num_of_skipped_orbits(board_id, value, silent=False):
|
|
|
+ """
|
|
|
+ Send new number of orbits to skip to board and update in config
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param value: the value to send
|
|
|
+ :param silent: (bool) if True do not inform observers on update
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ bk_update_config(board_id, "orbits_skip", value, silent=silent)
|
|
|
+
|
|
|
+
|
|
|
+def bk_change_count(board_id, value, silent=False):
|
|
|
+ """
|
|
|
+ Change the number of acquisitions you want to make.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param value: (int) Number of acquisitions
|
|
|
+ :param silent: (bool) if True do not inform observers on update
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ bk_update_config(board_id, "acquisition_count", value, silent=silent)
|
|
|
+
|
|
|
+
|
|
|
+def bk_change_wait(board_id, value, silent=False):
|
|
|
+ """
|
|
|
+ Change the time between acquisitions.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param value: (bool) Time in seconds
|
|
|
+ :param silent: (bool) if True do not inform observers on update
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ bk_update_config(board_id, "orbits_wait_time", value, silent=silent)
|
|
|
+
|
|
|
+
|
|
|
+def bk_change_build_spectrograms(board_id, value, silent=False):
|
|
|
+ """
|
|
|
+ Change if spectrograms are built or not)
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param value: (bool) True or False built or not
|
|
|
+ :param silent: (bool) if True do not inform observers on update
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ bk_update_config(board_id, "build_spectrograms", value, silent=silent)
|
|
|
+
|
|
|
+
|
|
|
+def bk_change_pilot_bunch(board_id, value, silent=False):
|
|
|
+ """
|
|
|
+ Change if pilot bunch is simulated
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param value: (bool) True or False to simulate or not
|
|
|
+ :param silent: (bool) if True do not inform observers on update
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ bk_update_config(board_id, "pilot_bunch", value, silent=silent)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_iterate_spectrograms(board_id, path):
|
|
|
+ """
|
|
|
+ BROKEN (DOES NOT GET ANY DATA)
|
|
|
+ Built Spectrograms line by line
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param path: where to built the spectrogram
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ return # because it is broken
|
|
|
+ if not os.path.isdir(str(path)):
|
|
|
+ return
|
|
|
+
|
|
|
+ # how does this get data? dataset.data does not exist
|
|
|
+ transform = dataset.data.fft(1, frm=0, to=-1)
|
|
|
+ for i in range(config.bunches_per_turn - 1):
|
|
|
+ filename = os.path.join(storage.storage.save_location, storage.storage.subdirname, str(path), "%i.hsp" % i)
|
|
|
+ write_header = False
|
|
|
+ if not os.path.isfile(filename):
|
|
|
+ write_header = True
|
|
|
+ f = open(filename, 'ab')
|
|
|
+ if write_header:
|
|
|
+ f.write("#hsp\n") # heb spectrogram magic number
|
|
|
+ f.write("#"+str(board.get_board_config(board_id).get("orbits_skip")))
|
|
|
+ f.write("\n")
|
|
|
+ line = transform[i, :]
|
|
|
+ f.write('{:0.3f} '.format(time.time()))
|
|
|
+ for e in line:
|
|
|
+ f.write("%s " % np.absolute(e))
|
|
|
+ f.write("\n")
|
|
|
+ f.close()
|
|
|
+
|
|
|
+
|
|
|
+def _bif_read_data_and_save(board_id):
|
|
|
+ """
|
|
|
+ Tell the pci command to start acquisition and save data
|
|
|
+ Also generates the filename from settings
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ now = time.time()
|
|
|
+ if not os.path.isdir(str(storage.storage.save_location + '/' + storage.storage.subdirname)):
|
|
|
+ os.makedirs(str(storage.storage.save_location + '/' + storage.storage.subdirname))
|
|
|
+ filename = storage.storage.save_location + '/' + storage.storage.subdirname+'/{:0.3f}.out'.format(now)
|
|
|
+ board.get_board_status(board_id).last_file = filename
|
|
|
+
|
|
|
+ try:
|
|
|
+ simulate = board.get_board_config(board_id).get("pilot_bunch")
|
|
|
+ try:
|
|
|
+ board.acquire_data(board_id, filename, simulate=simulate)
|
|
|
+ if not os.path.isfile(filename):
|
|
|
+ error(0x001, "No File Created")
|
|
|
+ except IndexError:
|
|
|
+ error(0x002, "Unexpected output of pci for number of orbits to observe. Returning")
|
|
|
+ return
|
|
|
+ _bif_read_and_update_data_from_file(board_id, filename)
|
|
|
+ except board.BoardError as e:
|
|
|
+ logging.error("Reading failed: {}".format(str(e)))
|
|
|
+
|
|
|
+
|
|
|
+def _bif_read_and_update_data_from_file(board_id, filename):
|
|
|
+ """
|
|
|
+ Proxy function for _bif_read_and_update to call with correct read_func
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param filename: filename to read data from
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ _bif_read_and_update(board_id, io.read_from_file, str(filename))
|
|
|
+
|
|
|
+
|
|
|
+def _bif_read_and_update_data_from_string(board_id, raw_data):
|
|
|
+ """
|
|
|
+ Proxy function for _bif_read_and_update to call with correct read_func
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param raw_data: Data as string
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ _bif_read_and_update(board_id, io.read_from_string, raw_data)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_read_and_update(board_id, read_func, *args):
|
|
|
+ """
|
|
|
+ Function to read data from file or string (depending on read_func) and update plots etc.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param read_func: function to use to read data
|
|
|
+ :param args: filename or raw_data (see _bif_read_and_update_from_{filename, string}
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ _bif_enable_wait_cursor()
|
|
|
+
|
|
|
+ header = board.get_board_config(board_id).get('header')
|
|
|
+ # TODO: force_read: meaning ignore cache and read new -> in the old gui this was a commandline option
|
|
|
+ # TODO: cache_data: meaning cache already processed numpy data -> in the old gui this was a commandline option
|
|
|
+ if live_plot_windows.hasWindows(board_id):
|
|
|
+ data = read_func(*args, force=False, header=header, cache=False)
|
|
|
+
|
|
|
+ if not io.is_data_consistent(data):
|
|
|
+ callbacks.async_callback('update_consistency', False)
|
|
|
+ global_objects.get_global('statusbar').showMessage(tr("Dialog", "Data is inconsistent!"))
|
|
|
+ if read_func == io.read_from_string:
|
|
|
+ logging.info("Data is inconsistent")
|
|
|
+ else:
|
|
|
+ logging.info("Data is inconsistent - file: " + args[0])
|
|
|
+ else:
|
|
|
+ callbacks.async_callback('update_consistency', True)
|
|
|
+
|
|
|
+ for plotwin in live_plot_windows.getWindows(board_id):
|
|
|
+ plotwin.plot_live(data=data)
|
|
|
+ QtGui.qApp.processEvents()
|
|
|
+ else:
|
|
|
+ callbacks.async_callback('update_consistency', None)
|
|
|
+
|
|
|
+ _bif_disable_wait_cursor()
|
|
|
+
|
|
|
+
|
|
|
+def bk_acquire(board_id):
|
|
|
+ """
|
|
|
+ Toggle Acqisition
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ if not bk_get_config(board_id, 'use_trigger'):
|
|
|
+ if board.get_board_status(board_id).acquisition == True:
|
|
|
+ log(board_id=board_id, additional="Manually Stopped Acquisition\nPerformed Acquisitions: " + str(storage.storage.current_acquisition))
|
|
|
+ _bif_stop_acquisition(board_id)
|
|
|
+ else:
|
|
|
+ _bif_start_acquisition(board_id)
|
|
|
+ else:
|
|
|
+ bk_toggle_wait_on_trigger(board_id)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_stop_acquisition(board_id):
|
|
|
+ """
|
|
|
+ Stop acquisition
|
|
|
+ This does stop the timer started by _bif_start_acquisition()
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ board.get_board_status(board_id).acquisition = False
|
|
|
+ storage.get_board_specific_storage(board_id).acquisition_progressbar.remove(0)
|
|
|
+ storage.get_board_specific_storage(board_id).acquisition_timer.stop()
|
|
|
+ # for elem in Elements.getElements("acquireTrigger_{}".format(board_id)):
|
|
|
+ # if isinstance(elem, QtGui.QShortcut) or isinstance(elem, QtGui.QCheckBox):
|
|
|
+ # continue
|
|
|
+ # elem.setIcon(QtGui.QIcon(config.install_path + config.startIcon))
|
|
|
+ # elem.setText(tr("Button", "Start Acquisition"))
|
|
|
+ Elements.setEnabled('acquire_{}'.format(board_id), True)
|
|
|
+ callbacks.callback('acquisition_stopped', board_id)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_start_acquisition(board_id):
|
|
|
+ """
|
|
|
+ Start acquisition.
|
|
|
+ This will start a timer to automatically acquire data.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ log(board_id=board_id, additional="Started Acquisition")
|
|
|
+ board.get_board_status(board_id).acquisition = True
|
|
|
+ Elements.setEnabled('acquire_{}'.format(board_id), False)
|
|
|
+ # for elem in Elements.getElements("acquireTrigger_{}".format(board_id)):
|
|
|
+ # if isinstance(elem, QtGui.QShortcut) or isinstance(elem, QtGui.QCheckBox):
|
|
|
+ # continue
|
|
|
+ # elem.setIcon(QtGui.QIcon(config.install_path + config.stopIcon))
|
|
|
+ # elem.setText(tr("Button", "Stop Acquisition"))
|
|
|
+ callbacks.callback('acquisition_started', board_id)
|
|
|
+ storage.get_board_specific_storage(board_id).acquisition_timer = QtCore.QTimer()
|
|
|
+ num_acquisitions = board.get_board_config(board_id).get("acquisition_count")
|
|
|
+ storage.get_board_specific_storage(board_id).acquisition_progressbar = \
|
|
|
+ _bif_ProgressBar(0, num_acquisitions, tr("sw", "Acquiring with board ")+str(board_id))
|
|
|
+ # storage.storage.acquisition_progressbar = acquisition_progressbar
|
|
|
+
|
|
|
+ # We increase already once because we do a single acquisition before the
|
|
|
+ # timer is started, otherwise we have to wait until the timer fires the
|
|
|
+ # first time.
|
|
|
+ try:
|
|
|
+ if isinstance(storage.storage.current_acquisition, dict):
|
|
|
+ storage.storage.current_acquisition[board_id] = 1
|
|
|
+ else:
|
|
|
+ storage.storage.current_acquisition = {board_id: 1}
|
|
|
+ except storage.StorageError:
|
|
|
+ storage.storage.current_acquisition = {board_id: 1}
|
|
|
+ _bif_read_data_and_save(board_id)
|
|
|
+
|
|
|
+ if board.get_board_config(board_id).get("build_spectrograms"):
|
|
|
+ spectrogram_dir = storage.storage.save_location + '/' + storage.storage.subdirname+"/spectrograms_{:0.3f}".format(time.time())
|
|
|
+ os.makedirs(spectrogram_dir)
|
|
|
+ _bif_iterate_spectrograms(board_id, spectrogram_dir) # TODO: not here?
|
|
|
+
|
|
|
+ storage.get_board_specific_storage(board_id).acquisition_progressbar.setValue(storage.storage.current_acquisition[board_id])
|
|
|
+
|
|
|
+ def on_timeout():
|
|
|
+ if storage.storage.current_acquisition[board_id] < num_acquisitions:
|
|
|
+ storage.storage.current_acquisition[board_id] += 1
|
|
|
+ storage.get_board_specific_storage(board_id).acquisition_progressbar.setValue(storage.storage.current_acquisition[board_id])
|
|
|
+ _bif_read_data_and_save(board_id)
|
|
|
+ if board.get_board_config(board_id).get("build_spectrograms"):
|
|
|
+ _bif_iterate_spectrograms(board_id, spectrogram_dir) # TODO: not here ?
|
|
|
+ else:
|
|
|
+ log(board_id=board_id, additional="Stopped Acquisition")
|
|
|
+ _bif_stop_acquisition(board_id)
|
|
|
+ storage.get_board_specific_storage(board_id).acquisition_progressbar.remove(0)
|
|
|
+
|
|
|
+ storage.get_board_specific_storage(board_id).acquisition_timer.timeout.connect(on_timeout)
|
|
|
+ storage.get_board_specific_storage(board_id).acquisition_timer.start(board.get_board_config(board_id).get('orbits_wait_time') * 1000)
|
|
|
+
|
|
|
+
|
|
|
+def bk_single_read(board_id):
|
|
|
+ """
|
|
|
+ Perform a single read of data
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ Elements.setEnabled("acquire_{}".format(board_id), False)
|
|
|
+ _bif_read_data_and_save(board_id)
|
|
|
+ log(board_id=board_id, additional="Single Read\nFilename: "+board.get_board_status(board_id).last_file.split('/')[-1])
|
|
|
+ Elements.setEnabled("acquire_{}".format(board_id), True)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_set_continuous_read_active(board_id):
|
|
|
+ """
|
|
|
+ Enable continuous read
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ Elements.setEnabled("acquire_{}".format(board_id), False)
|
|
|
+ Elements.setEnabled("acquireTrigger_{}".format(board_id), False)
|
|
|
+ Elements.setEnabled("continuous_read_{}".format(board_id), True)
|
|
|
+ board.get_board_status(board_id).continuous_read = True
|
|
|
+
|
|
|
+
|
|
|
+def _bif_set_continuous_read_inactive(board_id):
|
|
|
+ """
|
|
|
+ Disable continuous read
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ if board.get_board_status(board_id).continuous_read:
|
|
|
+ board.get_board_status(board_id).continuous_read = False
|
|
|
+ storage.get_board_specific_storage(board_id).continuous_read_timer.stop()
|
|
|
+ Elements.setEnabled('acquire_{}'.format(board_id), True)
|
|
|
+ Elements.setEnabled('acquireTrigger_{}'.format(board_id), True)
|
|
|
+
|
|
|
+
|
|
|
+def bk_continuous_read(board_id, interval=100):
|
|
|
+ """
|
|
|
+ Toggle continuous read
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param interval: Time between two consecutive reads.
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ if not board.get_board_status(board_id).continuous_read:
|
|
|
+ _bif_set_continuous_read_active(board_id)
|
|
|
+ _bif_continuous_read(board_id, interval)
|
|
|
+ else:
|
|
|
+ _bif_set_continuous_read_inactive(board_id)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_continuous_read(board_id, interval=None):
|
|
|
+ """
|
|
|
+ Perform continuous read based on a timer.
|
|
|
+ :param interval:
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ if interval is not None:
|
|
|
+ # TODO: ueberall checken, dass der board specific storage verwendet wird
|
|
|
+ storage.get_board_specific_storage(board_id).continuous_interval = interval
|
|
|
+ storage.get_board_specific_storage(board_id).continuous_read_timer = QtCore.QTimer()
|
|
|
+ logging.info("Start continuous read")
|
|
|
+
|
|
|
+ def continuous_read_step():
|
|
|
+ if board.get_board_status(board_id).continuous_read:
|
|
|
+ _bif_read_data(board_id)
|
|
|
+ storage.get_board_specific_storage(board_id).continuous_read_timer.singleShot(storage.storage.continuous_interval, continuous_read_step)
|
|
|
+
|
|
|
+ storage.get_board_specific_storage(board_id).continuous_read_timer.singleShot(storage.storage.continuous_interval, continuous_read_step)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_read_data(board_id):
|
|
|
+ """
|
|
|
+ Reads data acquired by board.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ if board.get_board_config(board_id).get('pilot_bunch'):
|
|
|
+ board.start_pilot_bunch_emulator(board_id)
|
|
|
+
|
|
|
+ board.start_acquisition(board_id)
|
|
|
+ try:
|
|
|
+ board.wait_for_revolutions(board_id)
|
|
|
+ except IndexError:
|
|
|
+ error(0x002, "Unexpected output of pci for number of orbits to observe. Returning")
|
|
|
+ return
|
|
|
+ board.stop_acquisition(board_id)
|
|
|
+ board.enable_transfer(board_id)
|
|
|
+ data_raw = board.pci.read_data_to_variable(board_id)
|
|
|
+ _bif_read_and_update_data_from_string(board_id, data_raw)
|
|
|
+ except board.BoardError as e:
|
|
|
+ logging.error("Reading failed: {}".format(str(e))) # TODO: board id
|
|
|
+
|
|
|
+
|
|
|
+def bk_board_connected(board_id):
|
|
|
+ """
|
|
|
+ Interface to the board to check if it is connected.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ # return board.is_conneced(board_id)
|
|
|
+ if len(available_boards.board_ids) > 0:
|
|
|
+ return True
|
|
|
+ return False
|
|
|
+
|
|
|
+
|
|
|
+def bk_get_temperature(board_id):
|
|
|
+ """
|
|
|
+ Get Temperature from board and format it
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ fpga_temp_raw_hex = board.pci.read(board_id, 1, '0x9110')[0]
|
|
|
+ fpga_temp_raw_hex = fpga_temp_raw_hex[-3:]
|
|
|
+ fpga_temp_raw_bin = '{0:012b}'.format(int(fpga_temp_raw_hex, 16))
|
|
|
+ fpga_temp_encoded = board.get_dec_from_bits(fpga_temp_raw_bin, 9, 0)
|
|
|
+ fpga_temp_celsius = '{0:2.2f}'.format(((fpga_temp_encoded * 503.975) / 1024) - 273.15)
|
|
|
+ return fpga_temp_celsius
|
|
|
+
|
|
|
+
|
|
|
+backup_get_temp = bk_get_temperature
|
|
|
+
|
|
|
+
|
|
|
+def bk_time_scan(board_id, c_frm, c_to, f_frm, f_to, ts_pbar, plot_func, orbits_observe=None, orbits_skip=None):
|
|
|
+ """
|
|
|
+ Toggle Timescan.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param c_frm: (int) From value for Coarse scan
|
|
|
+ :param c_to: (int) To value for Coarse scan
|
|
|
+ :param f_frm: (int) From value for Fine scan
|
|
|
+ :param f_to: (int) To value for fine scan
|
|
|
+ :param ts_pbar: Handle to the Timescan Progressbar
|
|
|
+ :param plot_func: Function to plot when timescan ended.
|
|
|
+ :param orbits_observe: Number of orbits to observe for the timescan (original values will be restored after timescan)
|
|
|
+ :param orbits_skip: Number of orbits to skipfor the timescan (original values will be restored after timescan)
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ if board.get_board_status(board_id).time_scan:
|
|
|
+ _bif_stop_time_scan(board_id, ts_pbar)
|
|
|
+ else:
|
|
|
+ _bif_start_time_scan(board_id, c_frm, c_to, f_frm, f_to, ts_pbar, plot_func, orbits_observe, orbits_skip)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_stop_time_scan(board_id, ts_pbar):
|
|
|
+ """
|
|
|
+ Stop the timescan. This stops the timer.
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param ts_pbar: Timescan Progressbar handle
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ Elements.getElements("start_time_scan_{}".format(board_id))[0].setText(tr("Button", "Start time scan"))
|
|
|
+ board.get_board_status(board_id).time_scan = False
|
|
|
+ board.get_board_config(board_id).set_delay(storage.storage.th_old[board_id])
|
|
|
+ board.get_board_config(board_id).set_chip_delay(
|
|
|
+ [0, 1, 2, 3],
|
|
|
+ [
|
|
|
+ storage.storage.chip_1_old[board_id],
|
|
|
+ storage.storage.chip_2_old[board_id],
|
|
|
+ storage.storage.chip_3_old[board_id],
|
|
|
+ storage.storage.chip_4_old[board_id]
|
|
|
+ ]
|
|
|
+ )
|
|
|
+ ts_pbar.reset()
|
|
|
+
|
|
|
+
|
|
|
+# tst = None # Ugly but necessary for the thread not to be killed when function ends (which is almost immediately after start)
|
|
|
+# thread_ts = None
|
|
|
+
|
|
|
+
|
|
|
+def _bif_start_time_scan(board_id, c_frm, c_to, f_frm, f_to, timescan_progressbar, plot_func, orbits_observe, orbits_skip):
|
|
|
+ """
|
|
|
+ Start the timscan. This starts the timer
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param c_frm: From value for coarse scan
|
|
|
+ :param c_to: To value for coarse scan
|
|
|
+ :param f_frm: From value for fine scan
|
|
|
+ :param f_to: To value for fine scan
|
|
|
+ :param timescan_progressbar: Handle for the timescanprogressbar
|
|
|
+ :param plot_func: Function to use to plot the data
|
|
|
+ :param orbits_observe: Number of orbits to observe for the timescan (original values will be restored after timescan)
|
|
|
+ :param orbits_skip: Number of orbits to skipfor the timescan (original values will be restored after timescan)
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ thread = storage.get_board_specific_storage(board_id).setdefault("TimeScanThread", storage.ThreadStorage())
|
|
|
+ # if thread_ts is not None:
|
|
|
+ # logging.info("Time scan already running")
|
|
|
+ # return
|
|
|
+ if thread.running:
|
|
|
+ logging.info("Time scan already running")
|
|
|
+ return
|
|
|
+
|
|
|
+ board.get_board_status(board_id).time_scan = True
|
|
|
+ Elements.getElements("start_time_scan_{}".format(board_id))[0].setText(tr("Button", "Stop time scan"))
|
|
|
+ if c_frm > c_to:
|
|
|
+ logging.info('Coarse Scan Interval is invalid: (%i > %i)' % (c_frm, c_to))
|
|
|
+ return
|
|
|
+ if f_frm > f_to:
|
|
|
+ logging.info('Fine Scan Interval is invalid: (%i > %i)' % (f_frm, f_to))
|
|
|
+ return
|
|
|
+
|
|
|
+ # the following could be made nicer with the use of setdefault and the use of get_board_specific_storage
|
|
|
+ if not hasattr(storage.storage, 'th_old'):
|
|
|
+ storage.storage.th_old = {}
|
|
|
+ storage.storage.chip_1_old = {}
|
|
|
+ storage.storage.chip_2_old = {}
|
|
|
+ storage.storage.chip_3_old = {}
|
|
|
+ storage.storage.chip_4_old = {}
|
|
|
+
|
|
|
+ storage.storage.th_old[board_id] = board.get_board_config(board_id).get('th_delay')
|
|
|
+ storage.storage.chip_1_old[board_id] = board.get_board_config(board_id).get('chip_1_delay')
|
|
|
+ storage.storage.chip_2_old[board_id] = board.get_board_config(board_id).get('chip_2_delay')
|
|
|
+ storage.storage.chip_3_old[board_id] = board.get_board_config(board_id).get('chip_3_delay')
|
|
|
+ storage.storage.chip_4_old[board_id] = board.get_board_config(board_id).get('chip_4_delay')
|
|
|
+
|
|
|
+ minimum = [None, None, None, None]
|
|
|
+ maximum = np.zeros((4, 3))
|
|
|
+ heatmap = np.zeros((4, (f_to - f_frm + 1), (c_to - c_frm + 1)))
|
|
|
+ timescan_progressbar.setRange(1, ((f_to - f_frm) + 1) * ((c_to - c_frm) + 1))
|
|
|
+
|
|
|
+ class thread_time_scan(QtCore.QObject):
|
|
|
+ pbarSignal = QtCore.pyqtSignal(int)
|
|
|
+ stopSignal = QtCore.pyqtSignal()
|
|
|
+ finished = QtCore.pyqtSignal()
|
|
|
+
|
|
|
+ def __init__(self, c_frm, c_to, f_frm, f_to, timescan_progressbar):
|
|
|
+ super(thread_time_scan, self).__init__()
|
|
|
+ self.c_frm = c_frm
|
|
|
+ self.c_to = c_to
|
|
|
+ self.f_frm = f_frm
|
|
|
+ self.f_to = f_to
|
|
|
+ self.timescan_progressbar = timescan_progressbar
|
|
|
+
|
|
|
+ def time_scan(self):
|
|
|
+ Elements.setEnabled('acquire_{}'.format(board_id), False, exclude=Elements.getElements('start_time_scan_{}'.format(board_id)))
|
|
|
+ if orbits_observe:
|
|
|
+ if not hasattr(storage.storage, 'orbits_observe_before_timescan'):
|
|
|
+ storage.storage.orbits_observe_before_timescan = {}
|
|
|
+ storage.storage.orbits_observe_before_timescan[board_id] = board.get_board_config(board_id).get("orbits_observe") # save old values to restore after timescan
|
|
|
+ board.get_board_config(board_id).update("orbits_observe", orbits_observe)
|
|
|
+ bk_change_num_of_orbits(board_id, orbits_observe)
|
|
|
+ if orbits_skip:
|
|
|
+ if not hasattr(storage.storage, 'orbits_skip_before_timescan'):
|
|
|
+ storage.storage.orbits_skip_before_timescan = {}
|
|
|
+ storage.storage.orbits_skip_before_timescan[board_id] = board.get_board_config(board_id).get("orbits_skip")
|
|
|
+ board.get_board_config(board_id).update("orbits_skip", orbits_skip)
|
|
|
+ bk_change_num_of_skipped_orbits(board_id, orbits_skip)
|
|
|
+
|
|
|
+ c_step = 0
|
|
|
+ for coarse in range(self.c_frm, self.c_to + 1):
|
|
|
+ try:
|
|
|
+ board.get_board_config(board_id).set_delay(coarse)
|
|
|
+ except board.BoardError as e:
|
|
|
+ self.stopSignal.emit()
|
|
|
+ self.finished.emit()
|
|
|
+ return
|
|
|
+
|
|
|
+ f_step = 0
|
|
|
+ for fine in range(self.f_frm, self.f_to + 1):
|
|
|
+ board.get_board_config(board_id).set_chip_delay([0, 1, 2, 3], [fine, fine, fine, fine])
|
|
|
+
|
|
|
+ try:
|
|
|
+ if bk_get_config(board_id, 'pilot_bunch') is True:
|
|
|
+ board.start_pilot_bunch_emulator(board_id)
|
|
|
+
|
|
|
+ board.start_acquisition(board_id)
|
|
|
+ try:
|
|
|
+ board.wait_for_revolutions(board_id) # Wait before asking for data
|
|
|
+ except IndexError:
|
|
|
+ error(0x002, "Unexpected output of pci for number of orbits to observe. Stopping Timescan")
|
|
|
+ self.stopSignal.emit()
|
|
|
+ return
|
|
|
+ board.stop_acquisition(board_id)
|
|
|
+ board.enable_transfer(board_id)
|
|
|
+
|
|
|
+ # -----------[ IMPORTANT ]---------------------
|
|
|
+ if not kcgw.testing:
|
|
|
+ data_raw = board.pci.read_data_to_variable(board_id)
|
|
|
+ board.flush_dma(board_id)
|
|
|
+ # ----------------------------------------------
|
|
|
+ else:
|
|
|
+ f_name = "/home/blaxxun/Documents/Hiwi/KaptureSimulator/timescan/" + str(
|
|
|
+ coarse) + "_" + str(fine) + ".str"
|
|
|
+ f = open(f_name, 'r')
|
|
|
+ data_raw = f.read()
|
|
|
+
|
|
|
+ # The PCI software not only prints the desired data but also some additional information.
|
|
|
+ # This information has to be removed here.
|
|
|
+ # To do so we split the output string from PCI at "Writting" (Note: Writting is correct as
|
|
|
+ # this is a typo in the PCI driver)
|
|
|
+ # TODO: does this need board_id? (was there)
|
|
|
+ data = io.read_from_string(data_raw, force=True, cache=False)
|
|
|
+ except board.BoardError as e:
|
|
|
+ self.stopSignal.emit()
|
|
|
+ self.finished.emit()
|
|
|
+ return
|
|
|
+
|
|
|
+ for adc in range(4):
|
|
|
+ buckets = data.array[:, adc:adc + 1].reshape(-1)
|
|
|
+ heatmap[adc, f_step, c_step] = float(buckets.sum()) / buckets.shape[0]
|
|
|
+ if heatmap[adc, f_step, c_step] > maximum[adc, 0]:
|
|
|
+ maximum[adc, 0] = heatmap[adc, f_step, c_step]
|
|
|
+ maximum[adc, 1] = coarse
|
|
|
+ maximum[adc, 2] = fine
|
|
|
+ if minimum[adc] is None or minimum[adc] > heatmap[adc, f_step, c_step]:
|
|
|
+ minimum[adc] = heatmap[adc, f_step, c_step]
|
|
|
+
|
|
|
+ self.pbarSignal.emit(((c_step * (f_to - f_frm + 1)) + f_step) + 1)
|
|
|
+
|
|
|
+ #GUI is blocked in our tight loop. Give it an opportunity to handle events
|
|
|
+ # QtGui.QApplication.processEvents() # remove this if moved to thread again
|
|
|
+ if board.get_board_status(board_id).time_scan is False:
|
|
|
+ # Time Scan Stop is already performed by button press. Nothing else to do but leave
|
|
|
+ self.finished.emit()
|
|
|
+ return
|
|
|
+ f_step += 1
|
|
|
+ c_step += 1
|
|
|
+ self.finished.emit()
|
|
|
+
|
|
|
+ def finished(timescan_progressbar):
|
|
|
+ thread.stop()
|
|
|
+ _bif_stop_time_scan(board_id, timescan_progressbar)
|
|
|
+ Elements.setEnabled('acquire_{}'.format(board_id), True, exclude=Elements.getElements('start_time_scan_{}'.format(board_id)))
|
|
|
+ if orbits_observe:
|
|
|
+ board.get_board_config(board_id).update("orbits_observe", storage.storage.orbits_observe_before_timescan[board_id]) # restore values
|
|
|
+ bk_change_num_of_orbits(board_id, storage.storage.orbits_observe_before_timescan[board_id])
|
|
|
+ if orbits_skip:
|
|
|
+ board.get_board_config(board_id).update("orbits_skip", storage.storage.orbits_skip_before_timescan[board_id])
|
|
|
+ bk_change_num_of_skipped_orbits(board_id, storage.storage.orbits_skip_before_timescan[board_id])
|
|
|
+ board.get_board_config(board_id).set_delay(storage.storage.th_old[board_id])
|
|
|
+
|
|
|
+ board.get_board_config(board_id).set_chip_delay(
|
|
|
+ [0, 1, 2, 3],
|
|
|
+ [
|
|
|
+ storage.storage.chip_1_old[board_id],
|
|
|
+ storage.storage.chip_2_old[board_id],
|
|
|
+ storage.storage.chip_3_old[board_id],
|
|
|
+ storage.storage.chip_4_old[board_id]
|
|
|
+ ]
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+ m = [np.min(heatmap[heatmap != 0]), np.max(heatmap)] # this gives the same levels for all 4 adcs
|
|
|
+ plot_func(heatmap, levels=m, newTitle=str(tr("sw", "Coarserange:{c_f}-{c_t} ; Finerange:{f_f}-{f_t}")).format(
|
|
|
+ c_f=c_frm,
|
|
|
+ c_t=c_to,
|
|
|
+ f_f=f_frm,
|
|
|
+ f_t=f_to),
|
|
|
+ maxima=maximum
|
|
|
+ )
|
|
|
+
|
|
|
+ now = time.time()
|
|
|
+ if not os.path.isdir(str(storage.storage.save_location + '/' + storage.storage.subdirname + '/timescan')):
|
|
|
+ os.makedirs((storage.storage.save_location + '/' + storage.storage.subdirname + '/timescan'))
|
|
|
+ filename = storage.storage.save_location + '/' + storage.storage.subdirname + '/timescan/timescan_{:0.3f}.out'.format(
|
|
|
+ now)
|
|
|
+ f = open(filename, 'wr')
|
|
|
+
|
|
|
+ for adc in range(4):
|
|
|
+ f.write("#ADC_%s\n" % adc)
|
|
|
+ for coarse, curr_cor in enumerate(np.transpose(heatmap[adc])):
|
|
|
+ for fine, value in enumerate(curr_cor):
|
|
|
+ f.write("%i;%i;%f\n" % ((coarse + c_frm), (fine + f_frm), value))
|
|
|
+ f.write('\n')
|
|
|
+
|
|
|
+ f.close()
|
|
|
+ f = open(filename + '.gnuplot', 'wr')
|
|
|
+ f.write('set datafile separator ";"\n')
|
|
|
+ f.write('set multiplot layout 2,2\n')
|
|
|
+ f.write('unset key\n')
|
|
|
+ for i in range(4):
|
|
|
+ f.write('set label 1 "ADC_%i" at graph 0.7,0.95 font ",8"\n' % (i + 1))
|
|
|
+ f.write('plot "%s" every :::%i::%i using 3 with lines\n' % (filename, i, i))
|
|
|
+ f.write('unset multiplot\n')
|
|
|
+ f.close()
|
|
|
+
|
|
|
+ return
|
|
|
+
|
|
|
+ tst = thread_time_scan(c_frm, c_to, f_frm, f_to, timescan_progressbar)
|
|
|
+ thread.register(tst)
|
|
|
+ thread.connect('pbarSignal', timescan_progressbar.setValue)
|
|
|
+ thread.connect('finished', lambda: finished(timescan_progressbar))
|
|
|
+ thread.connect('stopSignal', lambda: _bif_stop_time_scan(board_id, timescan_progressbar))
|
|
|
+ thread.start('time_scan')
|
|
|
+
|
|
|
+
|
|
|
+def bk_check_for_board(board_id):
|
|
|
+ """
|
|
|
+ Check if board is connected
|
|
|
+ Also overrides the bk_status_readout function with a function that does nothing (suppresses read attempts that
|
|
|
+ generate errors - if no board is connected, there is nothing to read from)
|
|
|
+ Also overrides the bk_get_temperature function as of the same reasons
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ global bk_status_readout, bk_get_temperature
|
|
|
+ board_status = bk_board_connected(board_id)
|
|
|
+ if board_status:
|
|
|
+ if not hasattr(board.get_board_status(board_id), 'board_connected') or \
|
|
|
+ not board.get_board_status(board_id).board_connected:
|
|
|
+ bk_status_readout = backup_readout
|
|
|
+ bk_get_temperature = backup_get_temp
|
|
|
+ board.get_board_status(board_id).board_connected = True
|
|
|
+
|
|
|
+ else:
|
|
|
+ Elements.setEnabled('no_board_{}'.format(board_id), False)
|
|
|
+
|
|
|
+ def do_nothing():
|
|
|
+ pass
|
|
|
+
|
|
|
+ def no_temp(board_id):
|
|
|
+ return "-"
|
|
|
+
|
|
|
+ bk_status_readout = do_nothing
|
|
|
+ bk_get_temperature = no_temp
|
|
|
+ board.get_board_status(board_id).board_connected = False
|
|
|
+ if board_status == False:
|
|
|
+ board.get_board_status(board_id).status_text = tr("sw", "Board {} not connected".format(board_id))
|
|
|
+ elif board_status == None:
|
|
|
+ board.get_board_status(board_id).status_text = tr("sw", "Software Interface not found")
|
|
|
+
|
|
|
+
|
|
|
+def bk_toggle_wait_on_trigger(board_id, num_of_acquisitions=None, skip=None, timeout=None, method=None):
|
|
|
+ """
|
|
|
+ Toggle waiting for trigger signal to acquire
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param num_of_acquisitions: number of acquisitions to wait for
|
|
|
+ :param skip: how much trigger signals to skip between acquisitions
|
|
|
+ :param timeout: the timeout for the pci to wait for date
|
|
|
+ :param method: wait method to use
|
|
|
+ 1 for wait in pci command and 2 for waiting until register is set that KAPTURE has read data
|
|
|
+ NOTE: this also means that method 1 enables simultaneous read and write to dma and method 2 does write and
|
|
|
+ read sequentially
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+
|
|
|
+ thread = storage.get_board_specific_storage(board_id).setdefault('TriggerThread', storage.ThreadStorage())
|
|
|
+ if thread.running:
|
|
|
+ # Elements.getElements("acquireTrigger_{}".format(board_id))[0].setText(tr("Button", "Start Acquisition"))
|
|
|
+ log(board_id=board_id, additional="Stop wait on trigger on board {}".format(board_id))
|
|
|
+ thread.stop()
|
|
|
+ # for elem in Elements.getElements("acquire_{}".format(board_id)):
|
|
|
+ # if isinstance(elem, QtGui.QShortcut):
|
|
|
+ # continue
|
|
|
+ # elem.setText(tr("Button", "Stopping Acquisition"))
|
|
|
+ # elem.setEnabled(False)
|
|
|
+ else:
|
|
|
+ log(board_id=board_id, additional="Start wait on trigger on board {}".format(board_id))
|
|
|
+ # for elem in Elements.getElements("acquireTrigger_{}".format(board_id)):
|
|
|
+ # if isinstance(elem, QtGui.QShortcut):
|
|
|
+ # continue
|
|
|
+ # elem.setIcon(QtGui.QIcon(config.install_path + config.stopIcon))
|
|
|
+ # elem.setText(tr("Button", "Stop Acquisition"))
|
|
|
+ Elements.setEnabled('acquire_{}'.format(board_id), False)
|
|
|
+ callbacks.callback('acquisition_started', board_id)
|
|
|
+ _bif_start_wait_on_trigger(board_id, num_of_acquisitions, skip, timeout, method)
|
|
|
+
|
|
|
+
|
|
|
+def _bif_start_wait_on_trigger(board_id, num_of_acquisitions=None, skip=None, timeout=None, method=None):
|
|
|
+ """
|
|
|
+ Start waiting on external acquisition trigger. This starts the timer
|
|
|
+ :param board_id: id of the board do manipulate
|
|
|
+ :param num_of_acquisitions: number of acquisitions to do
|
|
|
+ :param count_label: Handle for the countlabel
|
|
|
+ :param method: wait method to use
|
|
|
+ 1 for wait in pci command and 2 for waiting until register is set that KAPTURE has read data
|
|
|
+ NOTE: this also means that method 1 enables simultaneous read and write to dma and method 2 does write and
|
|
|
+ read sequentially
|
|
|
+ :return: -
|
|
|
+ """
|
|
|
+ thread = storage.get_board_specific_storage(board_id).setdefault('TriggerThread', storage.ThreadStorage())
|
|
|
+ if thread.running:
|
|
|
+ logging.info("Wait already running on board {}".format(board_id))
|
|
|
+ return
|
|
|
+ log(board_id=board_id, additional="Start wait on trigger")
|
|
|
+ board.get_board_status(board_id).wait_on_trigger = True
|
|
|
+ if not os.path.isdir(str(storage.storage.save_location + '/' + storage.storage.subdirname)):
|
|
|
+ os.makedirs(str(storage.storage.save_location + '/' + storage.storage.subdirname))
|
|
|
+
|
|
|
+ if not num_of_acquisitions:
|
|
|
+ num_of_acquisitions = bk_get_config(board_id, 'acquisition_count')
|
|
|
+ if not skip:
|
|
|
+ skip = bk_get_config(board_id, 'trigger_skip')
|
|
|
+ if not timeout:
|
|
|
+ timeout = bk_get_config(board_id, 'trigger_timeout')
|
|
|
+ if not method:
|
|
|
+ method = bk_get_config(board_id, 'trigger_method')
|
|
|
+
|
|
|
+ storage.get_board_specific_storage(board_id).trigger_progressbar = \
|
|
|
+ _bif_ProgressBar(0, num_of_acquisitions, tr("sw", "Acquiring with board ")+str(board_id))
|
|
|
+ board.pci.write(board_id, hex(num_of_acquisitions), "9024")
|
|
|
+ time.sleep(0.1)
|
|
|
+ board.pci.write(board_id, hex(skip), "902C")
|
|
|
+ time.sleep(0.1)
|
|
|
+ board.pci.write(board_id, 'ff0', hex_mask='ff0') # TODO: This writes t/h 3/4 but enable_transfer etc do not
|
|
|
+
|
|
|
+ # This seems to sometimes lead to segfaults of python it self. An Idea to prevent this
|
|
|
+ # is to use copy.deepcopy in __init__. But there is no reason to think that that causes the problem. In fact
|
|
|
+ # I don't have an idea why it crashes.
|
|
|
+ # A possible reason could the os.rename be (or even the board.safe_call as that saves data to the disk) But I think
|
|
|
+ # this is rather unlikely
|
|
|
+ # ~~NOTE~~: the thread of calibration also triggered segfaults sometimes. But this seems to be miraculously solved.
|
|
|
+ # Something that is likely to cause the problem is the log.debug in board.safe_call
|
|
|
+ # Logging (using the logging module) is directly connected to the main thread and could cause problems
|
|
|
+ class thread_wait_on_signal(QtCore.QObject):
|
|
|
+ countUpdate = QtCore.pyqtSignal(int)
|
|
|
+ stopSignal = QtCore.pyqtSignal()
|
|
|
+ finished = QtCore.pyqtSignal()
|
|
|
+ liveplot = QtCore.pyqtSignal(str)
|
|
|
+
|
|
|
+ def __init__(self, num_of_acquisitions, path, timeout):
|
|
|
+ super(thread_wait_on_signal, self).__init__()
|
|
|
+ self.noa = num_of_acquisitions
|
|
|
+ self.path = path
|
|
|
+ self.timeout = timeout
|
|
|
+ self._quit = False
|
|
|
+
|
|
|
+ # Elements.setEnabled('acquireTrigger_{}'.format(board_id), False) # exclude=Elements.getElements('wait_on_trigger_{}'.format(board_id)))
|
|
|
+
|
|
|
+ def wait_rw_simul(self):
|
|
|
+ board.pci.write(board_id, 'ff0', hex_mask='ff0') # TODO: This writes t/h 3/4 but enable_transfer etc do not
|
|
|
+ for num_of_acq in xrange(self.noa):
|
|
|
+ # def step():
|
|
|
+ filename = self.path +'/{:0.3f}.out'.format(time.time())
|
|
|
+ board.pci.read_data_to_file(board_id, filename=filename, timeout=(self.timeout*1000000))
|
|
|
+ # rename with correct timestamp - last modified time
|
|
|
+ # TODO: Exception handling when pci does not create file
|
|
|
+ self.countUpdate.emit(num_of_acquisitions + 1)
|
|
|
+ if self._quit:
|
|
|
+ break
|
|
|
+
|
|
|
+ # file operations
|
|
|
+ if not os.path.isfile(filename):
|
|
|
+ error(0x001, "No File Created")
|
|
|
+ continue
|
|
|
+
|
|
|
+ newfile = '{path}/trigger_{num:05}_{htime}_{unixtime}.out'.format(
|
|
|
+ num=num_of_acquisitions,
|
|
|
+ htime=dt.fromtimestamp(os.path.getmtime(filename)).strftime('%Y-%m-%dT%Hh%Mm%Ss%f'),
|
|
|
+ unixtime=int(os.path.getmtime(filename)),
|
|
|
+ path=self.path
|
|
|
+ )
|
|
|
+ os.rename(filename, newfile)
|
|
|
+ if os.path.getsize(newfile) > 0:
|
|
|
+ self.liveplot.emit(newfile)
|
|
|
+ else:
|
|
|
+ logging.info("Acquired 0b, possible trigger timeout.")
|
|
|
+
|
|
|
+ self.finished.emit()
|
|
|
+
|
|
|
+ def wait_rw_seq(self):
|
|
|
+ for num_of_acq in xrange(self.noa):
|
|
|
+ board.pci.write(board_id, '00bf0', hex_mask='CF0') # enable readout
|
|
|
+ pre_acq_num = board.pci.read(board_id, 1, '9034')[0]
|
|
|
+ time_a = time.time()
|
|
|
+ timeout = False
|
|
|
+ while pre_acq_num == board.pci.read(board_id, 1, '9034')[0]:
|
|
|
+ if time.time() - time_a > self.timeout:
|
|
|
+ timeout = True
|
|
|
+ break
|
|
|
+ if self._quit:
|
|
|
+ self.finished.emit()
|
|
|
+ return
|
|
|
+ if not timeout:
|
|
|
+ board.pci.write(board_id, '000f0', hex_mask='8F0') # disable readout
|
|
|
+ board.pci.write(board_id, '007f0', hex_mask='CF0') # enable transfer
|
|
|
+ filename = self.path +'/{:0.3f}.out'.format(time.time())
|
|
|
+ board.pci.read_data_to_file(board_id, filename=filename, timeout=(self.timeout*1000000))
|
|
|
+ board.pci.write(board_id, '000f0', hex_mask='4F0') # disable transfer
|
|
|
+ self.countUpdate.emit(copy.deepcopy(num_of_acq+1))
|
|
|
+ if self._quit:
|
|
|
+ break
|
|
|
+
|
|
|
+ if not os.path.isfile(filename):
|
|
|
+ error(0x001, "No File Created")
|
|
|
+ continue
|
|
|
+
|
|
|
+ newfile = '{path}/trigger_{num:05}_{htime}_{unixtime}.out'.format(
|
|
|
+ num=num_of_acquisitions,
|
|
|
+ htime=dt.fromtimestamp(os.path.getmtime(filename)).strftime('%Y-%m-%dT%Hh%Mm%Ss%f'),
|
|
|
+ unixtime=int(os.path.getmtime(filename)),
|
|
|
+ path=self.path
|
|
|
+ )
|
|
|
+ os.rename(filename, newfile)
|
|
|
+ self.liveplot.emit(newfile)
|
|
|
+ else:
|
|
|
+ logging.info("Trigger timeout.")
|
|
|
+
|
|
|
+
|
|
|
+ self.finished.emit()
|
|
|
+
|
|
|
+ def quit(self):
|
|
|
+ self._quit = True
|
|
|
+
|
|
|
+ def __del__(self):
|
|
|
+ board.pci.write(board_id, '0', '9024')
|
|
|
+ time.sleep(0.1)
|
|
|
+ board.pci.write(board_id, '0', '902C')
|
|
|
+ time.sleep(0.1)
|
|
|
+ board.pci.write(board_id, '3f0', hex_mask='ff0') # TODO: This writes t/h 3/4 but enable_transfer etc do not
|
|
|
+
|
|
|
+ def finished():
|
|
|
+ board.pci.write(board_id, '0', '9024')
|
|
|
+ time.sleep(0.1)
|
|
|
+ board.pci.write(board_id, '0', '902C')
|
|
|
+ time.sleep(0.1)
|
|
|
+ board.pci.write(board_id, '3f0', hex_mask='ff0') # TODO: This writes t/h 3/4 but enable_transfer etc do not
|
|
|
+
|
|
|
+ thread.stop()
|
|
|
+ board.get_board_status(board_id).wait = False
|
|
|
+ storage.get_board_specific_storage(board_id).trigger_progressbar.remove(0)
|
|
|
+ log(board_id=board_id, additional="Stop wait on trigger")
|
|
|
+ Elements.setEnabled('acquire_{}'.format(board_id), True)
|
|
|
+ callbacks.callback('acquisition_stopped', board_id)
|
|
|
+
|
|
|
+ # for elem in Elements.getElements("acquire_{}".format(board_id)):
|
|
|
+ # if isinstance(elem, QtGui.QShortcut):
|
|
|
+ # continue
|
|
|
+ # elem.setIcon(QtGui.QIcon(config.install_path + config.startIcon))
|
|
|
+ # elem.setText(tr("Button", "Start Acquisition"))
|
|
|
+ # elem.setEnabled(True)
|
|
|
+
|
|
|
+ return
|
|
|
+
|
|
|
+ twt = thread_wait_on_signal(num_of_acquisitions, storage.storage.save_location + '/' + storage.storage.subdirname,
|
|
|
+ timeout)
|
|
|
+ thread.register(twt)
|
|
|
+ thread.connect('countUpdate', storage.get_board_specific_storage(board_id).trigger_progressbar.setValue)
|
|
|
+ thread.connect('finished', finished)
|
|
|
+ thread.connect('liveplot', _bif_read_and_update_data_from_file)
|
|
|
+ if method == 1:
|
|
|
+ thread.start('wait_rw_simul')
|
|
|
+ elif method == 2:
|
|
|
+ thread.start('wait_rw_seq')
|
|
|
+ else:
|
|
|
+ raise ValueError("Wrong method")
|