1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444 |
- """
- 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")
|