From d625fbdfbd3ee06779c6c80ed1ae60b53a0af29b Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Wed, 24 Aug 2022 13:49:09 +0200 Subject: [PATCH] major restructuring but no code change: prefix functions with _OLD_ --- PrelocatedCoordinatesModel.py | 2 +- swissmx.py | 2995 ++++++++++++++++----------------- swissmx.ui | 2 +- 3 files changed, 1497 insertions(+), 1502 deletions(-) diff --git a/PrelocatedCoordinatesModel.py b/PrelocatedCoordinatesModel.py index c87a406..2b5ea99 100644 --- a/PrelocatedCoordinatesModel.py +++ b/PrelocatedCoordinatesModel.py @@ -688,7 +688,7 @@ class MainWindow(QMainWindow): super(MainWindow, self).__init__(parent) self.centralWidget = QWidget() - self.markwi = PrelocatedCoordinates(title="Prelocated Coordinates", parent=self) + self.markwi = PrelocatedCoordinates(parent=self) self.setCentralWidget(self.centralWidget) mainLayout = QVBoxLayout() diff --git a/swissmx.py b/swissmx.py index 3ae63df..3311e8d 100755 --- a/swissmx.py +++ b/swissmx.py @@ -162,9 +162,15 @@ def tdstamp(): def datestamp(): return time.strftime("%Y%m%d") +def sigint_handler(*args): + """Handler for the SIGINT signal.""" + app=QApplication.instance() + app.quit() + class AcquisitionAbortedException(Exception): pass + class Sequencer(QObject): finished = pyqtSignal() timeoutExpired = pyqtSignal() @@ -182,14 +188,37 @@ class Sequencer(QObject): _log.info("emiting finished") self.finished.emit() + +class StartupSplash: + + def __init__(self): + splash_pix = QPixmap("artwork/logo/256x256.png") + self._wnd=splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) + splash.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) + splash.setEnabled(False) + + self._prgsBar=prgs=QProgressBar(splash) + prgs.setMaximum(100) + prgs.setGeometry(0, splash_pix.height() - 50, splash_pix.width(), 20) + + splash.show() + + def set(self,i,msg): + self._prgsBar.setValue(i) + self._wnd.showMessage(f"{msg}", int(Qt.AlignBottom|Qt.AlignCenter), Qt.black) + app=QApplication.instance() + app.processEvents() + time.sleep(.1) + + Ui_MainWindow, QMainWindow = loadUiType("swissmx.ui") -class Main(QMainWindow, Ui_MainWindow): +class SwissMxWnd(QMainWindow, Ui_MainWindow): #pixelsPerMillimeter = pyqtSignal(float) #beamCameraCoordinatesChanged = pyqtSignal(float, float) addGridRequest = pyqtSignal(float, float) #zoomChanged = pyqtSignal(float) - folderChanged = pyqtSignal(str) + #folderChanged = pyqtSignal(str) prefixChanged = pyqtSignal(str) projectChanged = pyqtSignal(str) gridUpdated = pyqtSignal(int) # index in self._grids @@ -205,7 +234,7 @@ class Main(QMainWindow, Ui_MainWindow): daqAborted = pyqtSignal() def __init__(self,): - super(Main, self).__init__() + super(SwissMxWnd, self).__init__() self.setupUi(self) app=QApplication.instance() @@ -289,20 +318,17 @@ class Main(QMainWindow, Ui_MainWindow): self.load_stylesheet() - self.folderChanged.connect(lambda t: print("folder now: {}".format(t))) # FIXME + #self.folderChanged.connect(lambda t: print("folder now: {}".format(t))) # FIXME self.init_actions() - self.prepare_microscope_page() - self.prepare_embl_gui() + #self.prepare_microscope_page() self.prepare_left_tabs() #self.update_beam_marker(qoptic_zoom.get_sp()) #ZAC: orig. code self._centerpiece_stack.setCurrentIndex(0) self._centerpiece_stack.currentChanged.connect(self.center_piece_update) - self.init_validators() + self._OLD_init_validators() #self.init_settings_tracker() ? not needed, was for TELL ? - self.wire_storage() - - self.create_helical_widgets() #ZAC: orig. code + self._OLD_wire_storage() self.center_piece_update(0) # start camera updater curzoom = app._zoom.get_val() @@ -311,6 +337,37 @@ class Main(QMainWindow, Ui_MainWindow): self._tabs_daq_methods.currentChanged.connect(self.switch_task) self.switch_task() + def init_settings(self): + app = QApplication.instance() + cfg = app._cfg + keys = cfg.allKeys() + + #if EXPERIMENT_PGROUP not in keys: + # self.update_user_and_storage() + + if cfg.WINDOW_GEOMETRY in keys: + self.restoreGeometry(cfg.value(cfg.WINDOW_GEOMETRY, "")) + self.restoreState(cfg.value(cfg.WINDOW_STATE, "")) + + if cfg.WINDOW_SPLITTER in keys: + sz = [int(s) for s in cfg.value(cfg.WINDOW_SPLITTER)] + else: + sz=(500, 1200) + self._main_splitter.setSizes(sz) + + #if AppCfg.BEAM_MARKER_POSITIONS in keys: + # self._beam_markers = s.value(AppCfg.BEAM_MARKER_POSITIONS) + # self.update_beam_marker_fitters() + # _log.info("read beam markers {}".format(self._beam_markers)) + + #if AppCfg.CAMERA_TRANSFORMATIONS in keys: + # app._camera.set_transformations(s.value(AppCfg.CAMERA_TRANSFORMATIONS)) + + #if AppCfg.CAMERA_ZOOM_TO_PPM in keys: + # self._zoom_to_ppm = s.value(AppCfg.CAMERA_ZOOM_TO_PPM) + # _log.info(f"{AppCfg.CAMERA_ZOOM_TO_PPM} updated: {self._zoom_to_ppm}") + # self.update_ppm_fitters() + def init_graphics(self): app = QApplication.instance() cfg = app._cfg @@ -373,217 +430,190 @@ class Main(QMainWindow, Ui_MainWindow): self.track_objects() #tracking now the objects #UsrGO.obj_tree(vb) - - def create_helical_widgets(self): - tbox = self._helical_tablebox - htab = self._helical_scan_table = HelicalTableWidget() - htab.gonioMoveRequest.connect(self.move_gonio_to_position) - tbox.setLayout(QVBoxLayout()) - - grp = QWidget() - grp.setLayout(QFormLayout()) - le = QSpinBox() - le.setRange(1, 100) - le.setValue(htab.scanHorizontalCount()) - le.valueChanged.connect(lambda cnt: htab.setScanHorizontalCount(cnt)) - grp.layout().addRow("Horizontal Count", le) - - le = QSpinBox() - le.setRange(1, 100) - le.setValue(htab.scanVerticalCount()) - le.valueChanged.connect(lambda cnt: htab.setScanVerticalCount(cnt)) - grp.layout().addRow("Vertical Count", le) - - le = QDoubleSpinBox() - le.setRange(-180.0, 180.0) - le.setSingleStep(5.0) - le.setSuffix(" degrees") - le.valueChanged.connect(htab.setStartAngle) - grp.layout().addRow("Start angle", le) - - tbox.layout().addWidget(grp) - widgi = QWidget() - widgi.setLayout(QHBoxLayout()) - tbox.layout().addWidget(widgi) - - but = QPushButton("Add Crystal") - but.clicked.connect(htab.add_xtal) - widgi.layout().addWidget(but) - - but = QPushButton("Set START") - but.clicked.connect(lambda: htab.set_xtal_start(self.get_gonio_positions())) - widgi.layout().addWidget(but) - - but = QPushButton("Set END") - but.clicked.connect(lambda: htab.set_xtal_end(self.get_gonio_positions())) - widgi.layout().addWidget(but) - - tbox.layout().addWidget(htab) - - def add_beam_marker(self): + def init_actions(self): app = QApplication.instance() cfg = app._cfg - w, h = cfg.value(AppCfg.GEO_BEAM_SZ) - self._beammark = bm = CstROI.BeamMark([100, 100], (int(w), int(h)), parent=self) - tr=QtGui.QTransform() # prepare ImageItem transformation: - tr.rotate(30) - bm.setTransform(tr) # assign transform - self.vb.addItem(self._beammark) - bm=UsrGO.BeamMark([50, 120], [30, 20]) - self.vb.addItem(bm) - vi=UsrGO.Grid((120, -100), (200, 150), (30, 20), 2) - self.vb.addItem(vi) + self.toolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) - def camera_pause_toggle(self): - app=QApplication.instance() - app._camera.pause() + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_S), self) + self.shortcut.activated.connect(self.saveSampleCameraScreenshot) - def new_frame_sim_cb(self, **kwargs): - app=QApplication.instance() - sim=app._camera._sim - imgSeq=sim['imgSeq'] - idx=sim['imgIdx'] - sim['imgIdx']=(idx+1)%imgSeq.shape[0] - # _log.info('simulated idx:{}'.format(idx)) - pic=imgSeq[idx] - self._goImg.setImage(pic) + self.shortcut = QShortcut(QKeySequence(Qt.Key_F2), self) + self.shortcut.activated.connect(self.saveSampleCameraScreenshot) - delay=500 # ms -> 2fps - QtCore.QTimer.singleShot(delay, self.new_frame_sim_cb) + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_S), self) + self.shortcut.activated.connect(self.saveSampleCameraScreenshotView) - def new_frame_pv_cb(self, **kwargs): - #_log.debug('new_frame_pv_cb count {}'.format(kwargs['count'])) - app=QApplication.instance() - sz=app._camera._sz - if kwargs['count']==sz[0]*sz[1]: - pic=kwargs['value'].reshape(sz[::-1]) - else: - sz=app._camera.update_size() - pic=kwargs['value'].reshape(sz[::-1]) - if pic.dtype==np.int16: - pic.dtype=np.uint16 - camera.epics_cam.set_fiducial(pic, 255) - self._goImg.setImage(pic) + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_T), self) + self.shortcut.activated.connect(lambda: qutilities.toggle_warn(SKIP_ESCAPE_TRANSITIONS_IF_SAFE)) - def init_settings_tracker(self): - app=QApplication.instance() - cfg=app._cfg - _log.info("configuring widget persistence") - fields = { - # 'folder': (self._label_folder, str), - "project": (self._le_project, str), - "prefix": (self._le_prefix, str), - "actual_prefix": (self._label_actual_prefix, str), - "exposureTime": (self._dsb_exposure_time, float), - "oscillationAngle": (self._dsb_oscillation_step, float), - "blastRadius": (self._dsb_blast_radius, float), - } - for key, f_config in fields.items(): - widget, conv = f_config - value = cfg.value(key) + for k in range(10): + qkey = k + Qt.Key_0 + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + qkey), self) + self.shortcut.activated.connect(lambda key=k: self.saveBookmark(key)) + + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + qkey), self) + self.shortcut.activated.connect(lambda key=k: self.gotoBookmark(key)) + + self._button_collect.clicked.connect(self.execute_collection) + + # Toolbar buttons + icon_size = QSize(50, 50) + + icon = qtawesome.icon("material.photo_camera") + action = QAction(icon, "Save View", self) + action.setToolTip("(Ctrl+S) Take a screenshot of the currently visible sample image, including markers. Saves in current folder.") + action.triggered.connect(self.saveSampleCameraScreenshotView) + self.toolBar.addAction(action) + + action = QAction(icon, "Save Original", self) + action.setToolTip("(Ctrl+Shift+S) Take a screenshot of the sample image, without markers. Saves in current folder.") + action.triggered.connect(self.saveSampleCameraScreenshot) + self.toolBar.addAction(action) + + if os.getenv("DEVELOPMENT_VERSION"): + icon = qtawesome.icon("material.style") + action = QAction(icon, "Reload Stylesheet", self) + action.triggered.connect(self.load_stylesheet) + self.toolBar.addAction(action) + + # icon = qtawesome.icon("material.shutter_speed") + action = QAction("Use Pulse Picker", self) + action.setCheckable(True) + action.setChecked(cfg.option(AppCfg.ACTIVATE_PULSE_PICKER)) + action.triggered.connect(lambda: cfg.toggle_option(AppCfg.ACTIVATE_PULSE_PICKER)) + self.toolBar.addAction(action) + + icon = qtawesome.icon("material.timeline") + action = QAction(icon, "Add Line", self) + action.triggered.connect(self._OLD_roi_add_line) + self.toolBar.addAction(action) + + icon = qtawesome.icon("material.tab_unselected") + action = QAction(icon, "Add Rect", self) + action.triggered.connect(self._OLD_roi_add_rect) + self.toolBar.addAction(action) + + icon = qtawesome.icon("material.play_for_work") + action = QAction(icon, "TELL Mount", self) + action.setToolTip("BookMark(0) => Move stages CZ, CX, FX, FY, and Omega to Tell sample changer mount position") + action.triggered.connect(self._OLD_escape_goToTellMountPosition) + self.toolBar.addAction(action) + + self.toolBar.addWidget(qutilities.horiz_spacer()) + + icon = qtawesome.icon("material.sync") + action = QAction(icon, "Sample\nExchange", self) + action.setToolTip("Move devices so a sample can be exchanged.") + action.setObjectName("action_SampleExchange") + action.triggered.connect(self.escape_goToSampleExchange) + self.toolBar.addAction(action) + self.toolBar.widgetForAction(action).setAccessibleName("action_SampleExchange") + + icon = qtawesome.icon("material.my_location") + action = QAction(icon, "Sample\nAlignment", self) + action.setToolTip("Move devices so a sample can be aligned.") + action.triggered.connect(self.escape_goToSampleAlignment) + self.toolBar.addAction(action) + self.toolBar.widgetForAction(action).setAccessibleName("action_SampleAlignment") + + icon = qtawesome.icon("material.fingerprint") + action = QAction(icon, "Data\nCollection", self) + action.setToolTip("Move devices so a sample can be collected.") + action.triggered.connect(self.escape_goToDataCollection) + self.toolBar.addAction(action) + self.toolBar.widgetForAction(action).setAccessibleName("action_DataCollection") + + self.actionQuit.triggered.connect(self.really_quit) + self.actionPreferences.triggered.connect(self._OLD_openPreferencesDialog) + self.actionHome_Fast_Stages.triggered.connect(self.home_deltatau_faststages) + self.actionUser_Storage.triggered.connect(self._OLD_update_user_and_storage) + + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_L), self) + self.shortcut.activated.connect(self._OLD_roi_add_line) + + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_R), self) + self.shortcut.activated.connect(self._OLD_roi_add_rect) + + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_M), self) + self.shortcut.activated.connect(self._OLD_toggle_mouse_tracking) + + self.shortcut = QShortcut(QKeySequence(Qt.Key_F11), self) + self.shortcut.activated.connect(self._OLD_toggle_maximized) + + self.shortcut = QShortcut(QKeySequence(Qt.Key_F12), self) + self.shortcut.activated.connect(self._OLD_show_window_configuration) + + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_B), self) + self.shortcut.activated.connect(lambda: self._OLD_beammark.toggle_handle()) + + self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_P), self) + self.shortcut.activated.connect(self._OLD_camera_pause_toggle) + + # adding a menu entry to one of the menus + action = QAction("geometry", self) + action.setToolTip("Update optical center, beam marker size etc.") + action.setStatusTip("Update optical center, beam marker size etc.") + action.triggered.connect(lambda x: cfg.dlg_geometry(self)) + self.menuAdvanced.addAction(action) + + action = QAction("Backlight Reference Positions", self) + action.setToolTip("Update the reference positions for the backlight") + action.setStatusTip("Update the reference positions for the backlight") + action.triggered.connect(cfg.dlg_backlight_positions) + self.menuAdvanced.addAction(action) + + action = QAction("Collimator Reference Positions", self) + action.setToolTip("Update the reference positions for the collimator") + action.setStatusTip("Update the reference positions for the collimator") + action.triggered.connect(cfg.dlg_collimator_reference_positions) + self.menuAdvanced.addAction(action) + + action = QAction("Post sample tube Reference Positions", self) + action.setToolTip("Update the reference positions for the post tube") + action.setStatusTip("Update the reference positions for the post tube") + action.triggered.connect(cfg.dlg_posttube_references) + self.menuAdvanced.addAction(action) + + action = QAction("Delta Tau Parameters", self) + action.setToolTip("Parameters affecting the Delta Tau") + action.setStatusTip("Parameters affecting the Delta Tau") + action.triggered.connect(cfg.dlg_deltatau_parameters) + self.menuAdvanced.addAction(action) + + #action = QAction("Cryojet Reference Positions", self) + #action.setToolTip("Update the reference positions for the cryojet nozzle position") + #action.setStatusTip("Update the reference positions for the cryojet nozzle position") + #action.triggered.connect(self.set_cryojet_positions_dialog) + #self.menuAdvanced.addAction(action) + + #action = QAction("Tell Mount Positions", self) + #action.setToolTip("Mount positions for TELL sample changer") + #action.setStatusTip("Parameters affecting the Delta Tau") + #action.triggered.connect(cfg.dlg_tell_mount_positions) + #self.menuAdvanced.addAction(action) + + def closeEvent(self, event): #overloaded function + """this is called when the user clicks the window's cross icon""" + if (self._do_quit or QMessageBox.question( self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes): + app=QApplication.instance() + cfg=app._cfg try: - wset, wget = widget.setText, widget.text - _log.debug("tracking text field {}".format(key)) + pv=app._camera._pv['pic'] + pv.clear_auto_monitor() # disconnect PV monitor callback -> program exit faster. except AttributeError: - _log.debug("tracking {} number field {}".format(conv, key)) - wset, wget = widget.setValue, lambda fget=widget.value: conv(fget()) - except Exception as e: - _log.error(e) + _log.warning('disconnect PV callback failed.') - try: - wset(conv(value)) - except Exception as e: - _log.debug(e) - _log.warning('failed for "{}" updating field of type {} with {}'.format( key, type(widget), value)) - finally: - # _log.debug('wget = {}; wset = {}'.format(wget, wset)) - widget.editingFinished.connect(lambda w=widget, k=key, func_get=wget: self.persist_setting(k, func_get() ) ) - #self.storage_cascade_prefix(None) #ZAC: orig. code - - def init_validators(self): - identifier_regex = QRegExp("[a-z-A-Z_0-9%]+") - self._le_project.setValidator(QRegExpValidator(identifier_regex, self._le_project)) - self._le_prefix.setValidator(QRegExpValidator(identifier_regex, self._le_prefix)) - - def wire_storage(self): - self._le_prefix.textChanged.connect(self.storage_cascade_prefix) - self._le_prefix.textChanged.connect(lambda newtext: self.prefixChanged.emit(newtext)) - self._le_project.textChanged.connect(self.storage_cascade_prefix) - self._le_project.textChanged.connect(lambda newtext: self.projectChanged.emit(newtext)) - self._le_prefix.editingFinished.connect(self.prepare_daq_folder) - self._le_project.editingFinished.connect(self.prepare_daq_folder) - self.increaseRunNumberRequest.connect(self.increase_run_number) - - def storage_cascade_prefix(self, val): - prefix = self._le_prefix.text() - if 0 == len(prefix): - _log.warning("empty prefix is not accepted") - self._le_prefix.setAccessibleName("invalid_input") - self._le_prefix.blockSignals(True) - self._le_prefix.setText("INVALID=>" + prefix) - QMessageBox.warning(self, "prefix is not valid", "Prefix is not valid!") - self._le_prefix.blockSignals(False) - - return + _log.info('disconnect PV callback') + cfg.setValue(cfg.WINDOW_GEOMETRY, self.saveGeometry()) + cfg.setValue(cfg.WINDOW_STATE, self.saveState()) + cfg.setValue(cfg.WINDOW_SPLITTER, self._main_splitter.sizes()) + cfg.setValue('last_active', time.time()) + _log.info('save settings') + #QMainWindow.closeEvent(self, event) + _log.info('closeEvent done') else: - self._le_prefix.setAccessibleName("") - project = self._le_project.text() - folders.set_prefix(prefix) - folders.set_project(project) - folders.run = settings.value("run_number", type=int) - self._label_runnumber.setText(f"{folders.run:04d}") - self._data_folder = folders.raw_folder - self.folderChanged.emit(folders.raw_folder) - self._label_actual_prefix.setText(folders.prefix) - self._label_folder.setText(folders.raw_folder) - - def increase_run_number(self): - run = settings.value("run_number", type=int) - run += 1 - settings.setValue("run_number", run) - folders.run = run - self._label_runnumber.setText(f"{run:04d}") - - def prepare_daq_folder(self): - global home, folders - prefix = folders.prefix - folder = folders.res_folder - if 0 == len(prefix): - return - - try: - os.makedirs(folder, 0o750, exist_ok=True) - except: - msg = "Failed to create folder: {}".format(folder) - _log.warning(msg) - QMessageBox.warning(self, "Screenshot: failed to create folder", "Failed to create output folder for screenshot!\n\n\tScreenshot not taken!",) - raise - - fname = os.path.join(folders.pgroup_folder, ".latest_raw") - try: - with open(fname, "w") as f: - f.write(folders.raw_folder) - _log.info("wrote: {}".format(fname)) - except: - _log.warning("failed writing {}".format(fname)) - - fname = os.path.join(folders.pgroup_folder, ".latest_res") - try: - with open(fname, "w") as f: - f.write(folders.res_folder) - _log.info("wrote: {}".format(fname)) - except: - _log.warning("failed writing {}".format(fname)) - - def persist_setting(self, s, v): - app=QApplication.instance() - cfg=app._cfg - _log.debug("persisting {} = {}".format(s, v)) - cfg.setValue(s, v) - - def method_changed(self, index): - method = self._tabs_daq_methods.currentWidget().accessibleName() - _log.info("method now => {}".format(method)) + event.ignore() def center_piece_update(self, index): if index > 0: # not showing camera image @@ -600,461 +630,66 @@ class Main(QMainWindow, Ui_MainWindow): except AttributeError: app._camera.run(self.new_frame_pv_cb) - - - def check_zescape(self): - msg = zescape.check() - if msg is None: - return - if "current" in msg: - _log.warning(f"current state: {self._escape_current_state}") - zescape.reply(self._escape_current_state) - elif "goto" in msg: - state = msg.split()[1].lower() - _log.warning(f"TELL requests to go to {state}") - try: - if "sampleexchange" in state: - _log.debug( - f"moving to mount with offset = {self._pin_mounting_offset}" - ) - self.move_gonio_to_mount_position(offset=self._pin_mounting_offset) - elif "samplealignment" in state: - self.escape_goToSampleAlignment() - except: - zescape.reply("Maintenance") - zescape.reply(self._escape_current_state) - else: # JSON - data = json.loads(msg) - if "sampleName" in data: - _log.debug(f"TELL SAMPLE DATA => {data}") - self.tell2storage(data) - zescape.reply("ack") - elif "pin_offset" in data: - _log.debug(f"TELL pin offset => {data}") - self._pin_mounting_offset = data["pin_offset"] - zescape.reply("ack") - elif "get_pin_offset" in data: - _log.debug(f"TELL get pin offset => {data}") - zescape.reply_json({"pin_offset": self._pin_mounting_offset}) - - def tell2storage(self, sample): - _log.debug(f"2 TELL SAMPLE DATA => {type(sample)}") - self._le_prefix.setText(sample["sampleName"]) - self._le_project.setText(sample["sampleFolder"]) - tstf = folders.get_prefixed_file("_newsample") - self.storage_cascade_prefix(None) - _log.warning(f"sample info: {tstf}") - - def switch_task(self, index=0): - stack = self._centerpiece_stack - task = self._left_tabs.currentWidget().accessibleName() - setup_task = self._setup_toolbox.currentWidget().accessibleName() - method = self._tabs_daq_methods.currentWidget().accessibleName() - - _log.debug("Task switching: top_tabs={} exp.method={} setup_task={}".format(task, method, setup_task)) - - if task == "task_experiment": - stack.setCurrentIndex(0) - active_task = method - elif task == "task_setup": - active_task = setup_task - - elif task == "task_sample_selection": - active_task = TASK_SAMPLE_SELECTION - stack.setCurrentIndex(1) - else: - _log.error("BUG: un-handled task") - QMessageBox.warning(self, "BUG unhandled task!", "unhandled task: top_tabs={} method={}".format(task, method),) - self.set_active_task(active_task) - self._status_task.setText(active_task) - - def set_active_task(self, task): - _log.info("TASK == {}".format(task)) - self._active_task = task - - def active_task(self): - return self._active_task - - def is_task(self, task): - return task == self._active_task - - def get_task_menu(self): - pass - - def toggle_shutter(self, **kwargs): - if self._pv_shutter: - if 0 == self._pv_shutter.get(): - self._pv_shutter.put(1) - self._button_shutter.setText("shutter opened\n\u2622") - else: - self._pv_shutter.put(0) - self._button_shutter.setText("shutter closed\n\u2622") - elif self._has_pulse_picker: - pulsePicker.toggle() - - def update_shutter_label(self, pvname, value, char_value, **kwargs): - if 0 == value: - self._button_shutter.setText("shutter closed") - else: - self._button_shutter.setText("shutter opened") - - def prepare_left_tabs(self): - tabs = self._left_tabs - tabs.currentChanged.connect(self.switch_task) - - setup_tab = self._tab_setup - exp_tab = self._tab_experiment - - # add layouts - exp_tab.setLayout(QVBoxLayout()) - setup_tab.setLayout(QVBoxLayout()) - setup_tab.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) - self._setup_toolbox = tbox = QToolBox() - tbox.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Ignored)) - # tbox.setMinimumWidth(itemWidget.sizeHint().width()) - - setup_tab.layout().addWidget(tbox) - - # Jungfrau parameters - block = QWidget() - block.setAccessibleName(TASK_JUNGFRAU_SETTINGS) - block.setContentsMargins(0, 0, 0, 0) - block.setLayout(QVBoxLayout()) - #self.jungfrau = jungfrau_widget.JungfrauWidget() #ZAC: orig. code - #block.layout().addWidget(self.jungfrau) #ZAC: orig. code - block.layout().addStretch() - tbox.addItem(block, "Jungfrau Parameters") - - # group beam box - block = QWidget() - block.setAccessibleName(TASK_SETUP_BEAM_CENTER) - block.setContentsMargins(0, 0, 0, 0) - block.setLayout(QVBoxLayout()) - grp = QWidget() - block.layout().addWidget(grp) - block.layout().addStretch() - grp.setLayout(QGridLayout()) - tbox.addItem(block, "Beam Box") - # setup_tab.layout().addWidget(grp) - - row = grp.layout().rowCount - - if self._pv_shutter is not None: - but = QPushButton("open/close shutter") - but.setCheckable(True) - but.setChecked(1 == self._pv_shutter.get()) - but.clicked.connect(self.toggle_shutter) - self._button_shutter = but - grp.layout().addWidget(but, 0, 0, 1, 2) - self._pv_shutter.add_callback(self.update_shutter_label) - #else: #ZAC: orig. code - # self._picker = bernina_pulse_picker.PickerWidget() - # grp.layout().addWidget(self._picker, 0, 0, 1, 2) - but = QPushButton("clear beam markers") - but.clicked.connect(self.remove_beam_markers) - grp.layout().addWidget(but, 1, 1) - help = QTextBrowser() - grp.layout().addWidget(help, 2, 0, 5, 2) - help.setHtml( - """ -

Updating Beam Mark

-
    -
  1. clear beam markers
  2. -
  3. for each zoom level, CTRL-Click (left mouse button) the center of the beam
  4. -
- - """ - ) - - # group regions - block = QWidget() - block.setAccessibleName(TASK_SETUP_ROI) - block.setContentsMargins(0, 0, 0, 0) - block.setLayout(QVBoxLayout()) - grp = QWidget() - block.layout().addWidget(grp) - block.layout().addStretch() - grp.setLayout(QGridLayout()) - tbox.addItem(block, "Regions of Interest") - but = QPushButton("add RECT roi") - but.clicked.connect(self.roi_add_rect) - grp.layout().addWidget(but, 0, 0) - but = QPushButton("add LINE roi") - but.clicked.connect(self.roi_add_line) - grp.layout().addWidget(but, 0, 1) - - # group regions - block = QWidget() - block.setAccessibleName(TASK_SETUP_CAMERA) - block.setContentsMargins(0, 0, 0, 0) - block.setLayout(QVBoxLayout()) - grp = QWidget() - block.layout().addWidget(grp) - block.layout().addStretch() - grp.setLayout(QGridLayout()) - tbox.addItem(block, "Camera Settings") - but = QPushButton("remove transformations") - but.clicked.connect(lambda bogus: self.modify_camera_transform("remove_all")) - grp.layout().addWidget(but, 0, 0) - but = QPushButton("remove last") - but.clicked.connect(lambda bogus: self.modify_camera_transform("undo_last")) - grp.layout().addWidget(but, 0, 1) - but = QPushButton("Turn 90 CCW") - #but.clicked.connect( - # lambda bogus, n=camera.Transforms.ROTATE_90: self.modify_camera_transform(n) - #) #ZAC: orig. code - grp.layout().addWidget(but, 1, 0) - but = QPushButton("Turn 90 CW") - #but.clicked.connect(lambda bogus, n=camera.Transforms.ROTATE_270: self.modify_camera_transform(n)) #ZAC: orig. code - grp.layout().addWidget(but) - but = QPushButton("Turn 180 CCW") - #but.clicked.connect(lambda bogus, n=camera.Transforms.ROTATE_180: self.modify_camera_transform(n)) #ZAC: orig. code - grp.layout().addWidget(but) - but = QPushButton("Transpose") - #but.clicked.connect(lambda bogus, n=camera.Transforms.TRANSPOSE: self.modify_camera_transform(n)) #ZAC: orig. code - grp.layout().addWidget(but) - but = QPushButton("Flip L/R") - #but.clicked.connect(lambda bogus, n=camera.Transforms.FLIP_LR: self.modify_camera_transform(n)) #ZAC: orig. code - grp.layout().addWidget(but) - but = QPushButton("Flip U/D") - #but.clicked.connect(lambda bogus, n=camera.Transforms.FLIP_UD: self.modify_camera_transform(n)) #ZAC: orig. code - grp.layout().addWidget(but) - row = grp.layout().rowCount() - self._label_transforms = QLabel() - self._label_transforms.setWordWrap(True) - self.modify_camera_transform(None) - - grp.layout().addWidget(self._label_transforms, row, 0, 1, 2) - - # group regions - block = QWidget() - block.setAccessibleName(TASK_SETUP_GEOMETRY_CALIB) - block.setContentsMargins(0, 0, 0, 0) - block.setLayout(QVBoxLayout()) - grp = QWidget() - block.layout().addWidget(grp) - block.layout().addStretch() - grp.setLayout(QGridLayout()) - tbox.addItem(block, "geometry calibration") - #grp.layout().addWidget(QLabel("feature size (µM)"), 0, 0) - #self._ppm_feature_size_spinbox = QDoubleSpinBox() - #self._ppm_feature_size_spinbox.setRange(5, 10000) - #self._ppm_feature_size_spinbox.setValue(50) - #self._ppm_feature_size_spinbox.setDecimals(0) - #self._ppm_feature_size_spinbox.setSuffix(" µM") - #grp.layout().addWidget(self._ppm_feature_size_spinbox, 0, 1) - self._btn_pix2pos = but = QPushButton("pix2pos") - but.setCheckable(True) - but.clicked.connect(self.update_pix2pos) - grp.layout().addWidget(but, 0, 0) - self._btn_opt_ctr = but = QPushButton("opt_ctr") - but.setCheckable(True) - but.clicked.connect(self.update_opt_ctr) - grp.layout().addWidget(but, 1, 0) - - help = QTextBrowser() - grp.layout().addWidget(help, 2, 0) - help.setHtml( - """ -

Pixel to position calibration

-
    -
  1. press: pix2pos
  2. -
  3. for each zoom level: -
  4. choose a good fiducial mark -
  5. move the stage x/y at min. 3 different locations -
  6. CTRL-Click (left mouse button) on the fiducial mark -
  7. un-click: pix2pos
  8. -
-

optical center calibration

-
    -
  1. press: opt_ctr
  2. -
  3. choose at least 3 fiducial mark visible at various zoom levels -
  4. for at least two zoom level: -
  5. CTRL-Click (left mouse button) on the fiducial marks -
  6. un-click: opt_ctr
  7. -
- - """ - ) - - # grp = PpmToolBox(viewbox=self.vb, camera=sample_camera, signals=self) - # grp.setAccessibleName(TASK_SETUP_PPM_CALIBRATION_TBOX) - # grp.pixelPerMillimeterCalibrationChanged.connect(self.update_ppm_fitters) - # tbox.addItem(grp, "PPM ToolBox") - # self._ppm_toolbox = grp - - tbox.currentChanged.connect(self.switch_task) - - # final stretch - # setup_tab.layout().addStretch() - exp_tab.layout().addStretch() - - # DAQ Methods Tabs - self.build_daq_methods_prelocated_tab() #ZAC: orig. code - self.build_daq_methods_grid_tab() - self.build_sample_selection_tab() - - def build_sample_selection_tab(self): - # self._sample_selection = sample_selection.SampleSelection(self) - # self._sample_selection.move_to_mount_position = ( - # self.move_gonio_to_mount_position - # ) - # self._tab_sample_selection.setLayout(QVBoxLayout()) - # self._tab_sample_selection.layout().addWidget(self._sample_selection) - # self._tab_sample_selection.layout().addStretch(2) - pass - - def build_embl_group(self): - grp = QGroupBox("EMBL Acquisition") - layout = QFormLayout() - grp.setLayout(layout) - layout.addWidget(QLabel("Prefix")) - self._embl_prefix = QLineEdit("img") - layout.addWidget(self._embl_prefix) - - def abort_measurement(self, ev=None): - if settings.value(ACTIVATE_PULSE_PICKER): - pulsePicker.close() - jungfrau_detector.abort() - delta_tau.abort() - _log.debug("aborting measurement") - - def trigger_detector(self, **kwargs): - if self._pv_shutter is not None: - self._pv_shutter.put(0) - # self._eiger_button_collect.show() - # self._eiger_button_abort.hide() - # self._eiger_now_collecting_label.setText( - # "Finished sequence id: {}\n" - # "Data in: Data10/{}".format( - # self._detector_sequence_id, self._eiger_now_collecting_file - # ) - # ) - - def modify_camera_transform(self, t): - if t == "remove_all": - sample_camera.set_transformations([]) - elif t == "undo_last": - sample_camera._transformations.pop() - #elif type(t) ==type(camera.Transforms): #ZAC: orig. code - # sample_camera.append_transform(t) - try: - label = ", ".join([t.name for t in sample_camera._transformations]) - except: - label = "" - self._label_transforms.setText(label) - #settings.setValue(CAMERA_TRANSFORMATIONS, sample_camera._transformations) #ZAC: orig. code - - def roi_add_line(self): - roi = pg.LineSegmentROI( - [200, 200], - [300, 300], - pen="r", - scaleSnap=True, - translateSnap=True, - rotateSnap=True, - removable=True, - ) - # roi.sigRegionChanged.connect(self.track_roi) - roi.sigRemoveRequested.connect(self.remove_roi) - self.vb.addItem(roi) - self._rois.append(roi) - - def roi_add_rect(self): - roi = pg.RectROI( - [200, 200], - [50, 50], - pen="r", - scaleSnap=True, - translateSnap=True, - rotateSnap=True, - removable=True, - ) - roi.sigRegionChanged.connect(self.track_roi) - roi.sigRemoveRequested.connect(self.remove_roi) - self.vb.addItem(roi) - self._rois.append(roi) - - def remove_roi(self, roi): - self.vb.removeItem(roi) - self._rois.remove(roi) - - def prepare_embl_gui(self): - app = QApplication.instance() - self._tab_daq_method_embl.setLayout(QVBoxLayout()) - layout = self._tab_daq_method_embl.layout() - #motors = self.get_gonio_motors() - self._embl_module = EmblWidget(self) #ZAC: orig. code - #self._embl_module.configure(motors, app._camera, app._zoom) - layout.addWidget(self._embl_module) - - def prepare_microscope_page(self): - layout = self.microscope_page.layout() - container = QWidget() - hlay = QHBoxLayout() - container.setLayout(hlay) - layout.addWidget(container) - - def update_beam_marker(self, zoom_lvl): - w, h = settings.value(BEAM_SIZE) - try: - bx = self.beamx_fitter(zoom_lvl) - by = self.beamy_fitter(zoom_lvl) - ok = True - except: - ok = False - _log.warning("beam marker not defined") - return - _log.debug("updating beam mark to {:.1f}x{:.1f}".format(bx, by)) - self.beamCameraCoordinatesChanged.emit(bx, by) - - def update_beam_marker_fitters(self): - if len(self._beam_markers) > 2: - _log.debug("defining beam marker") - bx = [(n, x[0]) for n, x in self._beam_markers.items()] - by = [(n, x[1]) for n, x in self._beam_markers.items()] - nbx = np.asarray(bx).T - nby = np.asarray(by).T - bx_coefs = np.polyfit(nbx[0], nbx[1], 3) - by_coefs = np.polyfit(nby[0], nby[1], 3) - _log.debug(".... beam marker X coeficients {}".format(bx_coefs)) - _log.debug(".... beam marker Y coeficients {}".format(by_coefs)) - self.beamx_fitter = np.poly1d(bx_coefs) - self.beamy_fitter = np.poly1d(by_coefs) - - def update_pix2pos(self, calib): + def new_frame_pv_cb(self, **kwargs): + #_log.debug('new_frame_pv_cb count {}'.format(kwargs['count'])) app=QApplication.instance() - if calib: - _log.info("received new pix2pos calibration") - app._raw_pix2pos=dict() + sz=app._camera._sz + if kwargs['count']==sz[0]*sz[1]: + pic=kwargs['value'].reshape(sz[::-1]) else: - s=str(app._raw_pix2pos).replace('),','),\n ').replace('],','],\n') - print(s) - res=QMessageBox.question(self, "calibration", f"use calibration\n{s} ? ") - if res==QMessageBox.Yes: - geo=app._geometry - geo.update_pix2pos(app._raw_pix2pos) - app._cfg.setValue(AppCfg.GEO_PIX2POS, geo._lut_pix2pos) - del app._raw_pix2pos + sz=app._camera.update_size() + pic=kwargs['value'].reshape(sz[::-1]) + if pic.dtype==np.int16: + pic.dtype=np.uint16 + camera.epics_cam.set_fiducial(pic, 255) + self._goImg.setImage(pic) - def update_opt_ctr(self, calib): - app=QApplication.instance() - if calib: - _log.info("received new pix2pos calibration") - app._raw_opt_ctr=dict() - else: - s=str(app._raw_opt_ctr).replace('),','),\n ').replace('],','],\n') - print(s) - res=QMessageBox.question(self, "calibration", f"use calibration\n{s} ? ") - if res==QMessageBox.Yes: - geo=app._geometry - geo.update_optical_center(app._raw_opt_ctr) - app._cfg.setValue(AppCfg.GEO_OPT_CTR, geo._opt_ctr) - go=self._goOptCtr - oc_sz=go.size() - go.setPos(-geo._opt_ctr-oc_sz/2) - del app._raw_opt_ctr - return + def load_stylesheet(self): + with open("swissmx.css", "r") as sheet: + self.setStyleSheet(sheet.read()) + + def setup_sliders(self): + cont = self._rightmost + self._tweak_container = QWidget() + self._tweak_container.setLayout(QVBoxLayout()) + cont.layout().addWidget(self._tweak_container) + layout = self._tweak_container.layout() + layout.setSpacing(0) + layout.setContentsMargins(0, 0, 0, 0) + if self._at_x06sa: + zoom_base = "ESBMX-SAMCAM" # fetura IOC by Jose Gabadinho + elif self._at_lab_eh060: + zoom_base = "/dev/ttyUSB0" # direct connection using fetura.py package + elif self._at_cristalina: + zoom_base = ("rest://pc12818.psi.ch:9999") # direct connection using fetura.py package + + self.zoombox = zoom.Zoom() + self.zoombox.init_settings() + self.zoombox.zoomChanged.connect(self.zoom_changed_cb) + self.zoombox.moveBacklight.connect(self.safe_backlight_move) + + layout.addWidget(self.zoombox) + + toolbox = QToolBox() + layout.addWidget(toolbox) + + self.build_faststage_group(toolbox) + # self.build_slits_group(toolbox) + self.build_collimator_group(toolbox) + self.build_posttube_group(toolbox) + self.build_xeye_group(toolbox) + #self.build_cryo_group(toolbox) + + # monitor all axis for an axis fault + for key, tweaker in self.tweakers.items(): + tweaker.event_axis_fault.connect(self.axis_fault) + + #self.tweakers["fast_x"].event_readback.connect(lambda alias, value, kw: self.fast_x_position.emit(value)) + #self.tweakers["fast_y"].event_readback.connect(lambda alias, value, kw: self.fast_y_position.emit(value)) + + self.tweakers["fast_x"].event_val.connect(lambda rec_name, kw: self.track_objects()) + self.tweakers["fast_y"].event_val.connect(lambda rec_name, kw: self.track_objects()) + # layout.addStretch() def zoom_changed_cb(self, value): #self.zoomChanged.emit(value) @@ -1078,108 +713,160 @@ class Main(QMainWindow, Ui_MainWindow): self.track_objects() #self.update_beam_marker(value) - def track_objects(self): - #self._goTracked= dictionary with infos about tracked objects - # objLst = list of objects to track - # state = (zoom, fx, fy) (created at first call of self.track_objects() ) - app=QApplication.instance() - geo=app._geometry - zoom = app._zoom.get_val() - fast_x=self.tweakers["fast_x"];fast_y=self.tweakers["fast_y"] - # TODO: get_position() is delayed as it is the RBV. do same as for the zoom - # TODO: and return the last set_point - fx=fast_x.get_val() - fy=fast_y.get_val() + def safe_backlight_move(self, pos): + # any move of backlight requires post sample tube out try: - tracked=self._goTracked - zoom_old,fx_old,fy_old=tracked['state'] - except AttributeError: # at initialization - self._goTracked={'objLst':list(), 'state':(zoom,fx,fy)} - return - _log.debug(f"zoom:{zoom_old}->{zoom} fx:{fx_old}->{fx} fy:{fy_old}->{fy}") - opt_ctr=geo._opt_ctr - if zoom_old!=zoom: - geo.interp_zoom(zoom_old) - pix2pos_old=geo._pix2pos - geo.interp_zoom(zoom) - pix2pos_new=geo._pix2pos - for o in tracked['objLst']: - # names consists of abrevations - # part 0: po=position sz=size dt=delta - # part 1: px=pixel eu=engineering units (e.g. mm) - po_px=o.pos() - sz_px=o.size() - tr=o.transform() - geo._pix2pos=pix2pos_old - dt_px=-opt_ctr-po_px - dt_eu=geo.pix2pos(dt_px) - sz_eu=geo.pix2pos(sz_px) + self.assert_post_tube_position(pos="out") + except: + self.move_post_tube("out") + backlight.move(pos) - geo._pix2pos=pix2pos_new - dt_px2=geo.pos2pix(dt_eu) - sz_px2=geo.pos2pix(sz_eu) - po_px2=-opt_ctr-dt_px2 - o.setPos(po_px2) - o.setSize(sz_px2) - - #np.asarray(self._pix2pos*np.mat(p).T).ravel() - geo.interp_zoom(zoom) - - if fx_old!=fx or fy_old!=fy: - p1=geo.pos2pix((fx_old,fy_old)) - p2=geo.pos2pix((fx,fy)) - d=p1-p2 - - for o in tracked['objLst']: - pos=o.pos() - sz=o.size() - tr=o.transform() - o.setPos(pos+d) - tracked['state']=(zoom, fx, fy) - #imgPos=self._goImg.mapFromScene(event.scenePos()) - #x=imgPos.x();y=imgPos.y() - - - - - - - def append_to_beam_markers(self, x, y, zoom): - self._beam_markers[zoom] = (x, y) - _log.info("beam markers {}".format(self._beam_markers)) - settings.setValue(BEAM_MARKER_POSITIONS, self._beam_markers) - self.update_beam_marker_fitters() - - def remove_beam_markers(self): - self._beam_markers = {} - self.beamx_fitter = None - self.beamy_fitter = None - - def track_roi(self, roi): - x, y = roi.pos() - w, h = roi.size() - # area = roi.getArrayRegion(self._im, self.img) - # sum = np.sum(area) - # _log.info('{} => sum {}'.format((x,y), sum)) - bx, by = x + w / 2., y + h / 2. - _log.info("beam pos {}".format((bx, by))) - _log.info("marker pos = {} ; size = {}".format((x, y), (w, h))) - - def toggle_mouse_tracking(self): - if self._mouse_tracking: - self.disengage_mouse_tracking() + def get_tweaker(self, rec, alias=None, label=None, mtype="epics_motor", layout=None, **kwargs): + app = QApplication.instance() + sim=app._args.sim + if mtype == "epics_motor": + if sim&0x10: + m=SimMotorTweak() + else: + m = MotorTweak() else: - self.engage_mouse_tracking() + if sim&0x20: + m=SimMotorTweak() + else: + m = SmaractMotorTweak() + m.connect_motor(rec, label, **kwargs) + self.tweakers[alias] = m + return m - def engage_mouse_tracking(self): - self.glw.scene().sigMouseMoved.connect(self.mouse_move_event) - self.glw.scene().sigMouseMoved.emit() - self._mouse_tracking = True + def build_post_tube_tandem_tweaker(self): + block = QWidget() + block.setAccessibleName("post tube tamden") + block.setContentsMargins(0, 0, 0, 0) + block.setLayout(QVBoxLayout()) + c = QWidget() + glay = QGridLayout() + c.setLayout(glay) - def disengage_mouse_tracking(self): - self.glw.scene().sigMouseMoved.disconnect(self.mouse_move_event) - self._mouse_tracking = False - self._lb_coords.setText("") + b = QWidget() + blay = QHBoxLayout() + b.setLayout(blay) + blay.addWidget(QLabel("Tweak (mm)")) + self._post_tandem_tweak_val = QLineEdit("1.0") + blay.addWidget(self._post_tandem_tweak_val) + glay.addWidget(b, 0, 0, 1, 2) + + icon = qtawesome.icon("material.arrow_back") + but = QPushButton(icon, "") + but.clicked.connect(lambda m, dir="x-pos": self.move_post_tube(dir)) + glay.addWidget(but, 1, 0) + + # c.setLayout(glay) + icon = qtawesome.icon("material.arrow_forward") + but = QPushButton(icon, "") + but.clicked.connect(lambda m, dir="x-neg": self.move_post_tube(dir)) + glay.addWidget(but, 1, 1) + + # c.setLayout(glay) + icon = qtawesome.icon("material.arrow_downward") + but = QPushButton(icon, "") + but.clicked.connect(lambda m, dir="down": self.move_post_tube(dir)) + glay.addWidget(but, 2, 0) + + # c.setLayout(glay) + icon = qtawesome.icon("material.arrow_upward") + but = QPushButton(icon, "") + but.clicked.connect(lambda m, dir="up": self.move_post_tube(dir)) + glay.addWidget(but, 2, 1) + + block.layout().addWidget(c) + return block + + def axis_fault(self, pvname, kw): + """ + swissmx - {'pvname': 'SAR-EXPMX:MOT_FY.STAT', 'value': 0, 'char_value': 'NO_ALARM', 'status': 0, 'ftype': 17, 'chid': 38980392, + 'host': 'SAR-CPPM-EXPMX1.psi.ch:5064', 'count': 1, 'access': 'read-only', 'write_access': False, 'read_access': True, + 'severity': 0, + 'timestamp': 1537867290.914189, 'precision': None, 'units': None, 'enum_strs': ('NO_ALARM', 'READ', 'WRITE', 'HIHI', 'HIGH', 'LOLO', 'LOW', 'STATE', 'COS', 'COMM', 'TIMEOUT', 'HWLIMIT', 'CALC', 'SCAN', 'LINK', 'SOFT'), 'upper_disp_limit': None, 'lower_disp_limit': None, 'upper_alarm_limit': None, 'lower_alarm_limit': None, 'lower_warning_limit': None, 'upper_warning_limit': None, 'upper_ctrl_limit': None, 'lower_ctrl_limit': None, 'nelm': 1, 'type': 'time_enum', 'typefull': 'time_enum', 'motor_field': 'STAT', 'source_field': 'STAT', 'cb_info': (1, ), 'alias': 'fast Y'} + + :param pvname: + :param kw: + :return: + """ + _log.debug(f"AXIS FAULT: {kw}") + if kw["severity"]: + msg = f"axis {pvname} has a fault" + _log.critical(msg) + _log.critical(f"{kw}") + else: + msg = "" + self._message_critical_fault.setText(msg) + + def build_faststage_group(self, toolbox): + qutilities.add_item_to_toolbox(toolbox,"Fast Stage", + widget_list=[ + # self.get_tweaker('SAR-EXPMX:MOT_BLGT', alias='backlight', label='backlight'), + self.get_tweaker("SAR-EXPMX:MOT_FY", alias="fast_y", label="fast Y"), + self.get_tweaker("SAR-EXPMX:MOT_FX", alias="fast_x", label="fast X"), + self.get_tweaker("SAR-EXPMX:MOT_ROT_Y",alias="omega",label="omega",tweak_min=0.001,tweak_max=180.0,), + self.get_tweaker("SAR-EXPMX:MOT_CX", alias="base_x", label="base X"), + self.get_tweaker("SAR-EXPMX:MOT_CZ", alias="base_z", label="base Z"), + ], + ) + + def build_collimator_group(self, toolbox): + qutilities.add_item_to_toolbox(toolbox,"Collimator", + widget_list=[ + self.get_tweaker("SARES30-ESBMX1", alias="colli_x", label="colli X", mtype="smaract_motor",), + self.get_tweaker("SARES30-ESBMX2", alias="colli_y", label="colli Y", mtype="smaract_motor",), + ], + ) + + def build_posttube_group(self, toolbox): + widgets = [ + self.get_tweaker("SARES30-ESBMX4", alias="tube_usx", label="upstream X", mtype="smaract_motor",), + self.get_tweaker("SARES30-ESBMX6", alias="tube_usy", label="upstream Y", mtype="smaract_motor",), + self.get_tweaker("SARES30-ESBMX5", alias="tube_dsx", label="downstream X", mtype="smaract_motor",), + self.get_tweaker("SARES30-ESBMX7", alias="tube_dsy", label="downstream Y", mtype="smaract_motor",), + self.get_tweaker("SARES30-ESBMX8", alias="tube_z", label="tube Z", mtype="smaract_motor"), + ] + c = QWidget() + c.setLayout(QGridLayout()) + but = QPushButton("post tube out") + but.clicked.connect(lambda m, dir="out": self.move_post_tube(dir)) + c.layout().addWidget(but, 0, 0) + but = QPushButton("post tube in") + but.clicked.connect(lambda m, dir="in": self.move_post_tube(dir)) + c.layout().addWidget(but, 0, 1) + widgets.append(c) + + label = "Post Sample Tube" + block = QWidget() + block.setAccessibleName(label) + block.setContentsMargins(0, 0, 0, 0) + block.setLayout(QVBoxLayout()) + for w in widgets: + block.layout().addWidget(w) + + block.layout().addWidget(self.build_post_tube_tandem_tweaker()) + block.layout().addStretch() + toolbox.addItem(block, label) + + def build_xeye_group(self, toolbox): + qutilities.add_item_to_toolbox( + toolbox, + "X-Ray Eye", + widget_list=[ + self.get_tweaker("SARES30-ESBMX14", alias="xeye_x", label="X", mtype="smaract_motor"), + self.get_tweaker("SARES30-ESBMX15", alias="xeye_y", label="Y", mtype="smaract_motor"), + ], + ) + + def set_active_task(self, task): + _log.info("TASK == {}".format(task)) + self._active_task = task + + def active_task(self): + return self._active_task def mouse_move_event(self, pos): app = QApplication.instance() @@ -1225,33 +912,6 @@ class Main(QMainWindow, Ui_MainWindow): ) ) - def mouse_click_event_geometry_calib(self, event): - app=QApplication.instance() - zoom = app._zoom.get_val() - fast_x=self.tweakers["fast_x"];fast_y=self.tweakers["fast_y"] - if self._btn_pix2pos.isChecked(): - try: - raw=app._raw_pix2pos[zoom] - except KeyError as e: - raw=app._raw_pix2pos[zoom]=list() - imgPos=self._goImg.mapFromScene(event.scenePos()) - fx=fast_x.get_rbv(); - fy=fast_y.get_rbv() - x=imgPos.x();y=imgPos.y() - _log.debug('append calib: zoom:{} stage_x_y:{}/{} cam_pix_x_y:{}/{}'.format(zoom, fx, fy, x, y)) - raw.append((fx, fy, x, y)) - elif self._btn_opt_ctr.isChecked(): - try: - raw=app._raw_opt_ctr[zoom] - except KeyError as e: - raw=app._raw_opt_ctr[zoom]=list() - imgPos=self._goImg.mapFromScene(event.scenePos()) - x=imgPos.x();y=imgPos.y() - _log.debug('append calib: zoom:{} cam_pix_x_y:{}/{}'.format(zoom, x, y)) - raw.append(( x, y)) - else: - QMessageBox.warning(self, "calibration", "no calibration started yet.\nPress 'pix2pos' or 'opt_ctr' button first") - def mouse_click_event(self, event): #_log.debug("{}".format(event)) #_log.debug("screen pos {}".format(event.screenPos())) #pixel position on the whole screen @@ -1448,31 +1108,162 @@ class Main(QMainWindow, Ui_MainWindow): else: pass - def get_beam_mark_on_camera_xy(self): + def track_objects(self): + #self._goTracked= dictionary with infos about tracked objects + # objLst = list of objects to track + # state = (zoom, fx, fy) (created at first call of self.track_objects() ) app=QApplication.instance() - z = app._zoom.get_val() + geo=app._geometry + zoom = app._zoom.get_val() + fast_x=self.tweakers["fast_x"];fast_y=self.tweakers["fast_y"] + # TODO: get_position() is delayed as it is the RBV. do same as for the zoom + # TODO: and return the last set_point + fx=fast_x.get_val() + fy=fast_y.get_val() try: - bx = self.beamx_fitter(z) - by = self.beamy_fitter(z) - except: - bx, by = 500, 500 - return (bx, by) + tracked=self._goTracked + zoom_old,fx_old,fy_old=tracked['state'] + except AttributeError: # at initialization + self._goTracked={'objLst':list(), 'state':(zoom,fx,fy)} + return + _log.debug(f"zoom:{zoom_old}->{zoom} fx:{fx_old}->{fx} fy:{fy_old}->{fy}") + opt_ctr=geo._opt_ctr + if zoom_old!=zoom: + geo.interp_zoom(zoom_old) + pix2pos_old=geo._pix2pos + geo.interp_zoom(zoom) + pix2pos_new=geo._pix2pos + for o in tracked['objLst']: + # names consists of abrevations + # part 0: po=position sz=size dt=delta + # part 1: px=pixel eu=engineering units (e.g. mm) + po_px=o.pos() + sz_px=o.size() + tr=o.transform() + geo._pix2pos=pix2pos_old + dt_px=-opt_ctr-po_px + dt_eu=geo.pix2pos(dt_px) + sz_eu=geo.pix2pos(sz_px) - def safe_backlight_move(self, pos): - # any move of backlight requires post sample tube out + geo._pix2pos=pix2pos_new + dt_px2=geo.pos2pix(dt_eu) + sz_px2=geo.pos2pix(sz_eu) + po_px2=-opt_ctr-dt_px2 + o.setPos(po_px2) + o.setSize(sz_px2) + + #np.asarray(self._pix2pos*np.mat(p).T).ravel() + geo.interp_zoom(zoom) + + if fx_old!=fx or fy_old!=fy: + p1=geo.pos2pix((fx_old,fy_old)) + p2=geo.pos2pix((fx,fy)) + d=p1-p2 + + for o in tracked['objLst']: + pos=o.pos() + sz=o.size() + tr=o.transform() + o.setPos(pos+d) + tracked['state']=(zoom, fx, fy) + #imgPos=self._goImg.mapFromScene(event.scenePos()) + #x=imgPos.x();y=imgPos.y() + + @pyqtSlot() + def saveSampleCameraScreenshot(self): + outf = self.get_screenshot_filename() + _log.info("saving original clean screenshot: {}".format(outf)) try: - self.assert_post_tube_position(pos="out") - except: - self.move_post_tube("out") - backlight.move(pos) + sample_camera.saveimage(outf) + except Exception as e: + _log.warning(e) + QMessageBox.warning(self, "Screenshot: failed to save image", "Failed to save screenshot!") - def escape_run_steps(self, steps, title): - with pg.ProgressDialog(title, 0, len(steps)) as dlg: - for step in steps: - step() - dlg += 1 - if dlg.wasCanceled(): - raise TransitionAborted("ABORTED" + title) + @pyqtSlot() + def saveSampleCameraScreenshotView(self): + outf = self.get_screenshot_filename() + _log.info("saving view screenshot: {}".format(outf)) + + exporter = pg.exporters.ImageExporter(self.vb) + + # set export parameters if needed + exporter.parameters()["width"] = 2000 # (note this also affects height parameter) + + # save to file + try: + exporter.export(outf) + except Exception as e: + _log.warning(e) + QMessageBox.warning(self, "Screenshot: failed to save viewer image", "Failed to save screenshot of viewer!",) + + def get_screenshot_filename(self): + global folders + _log.info("taking screenhot") + prefix = folders.prefix + folder = folders.res_folder + base = time.strftime("{}_%Y%m%d_%H%M%S.png".format(prefix)) + if not os._exists(folder): + try: + os.makedirs(folder, 0o750, exist_ok=True) + except: + msg = "Failed to create folder: {}".format(folder) + _log.warning(msg) + QMessageBox.warning(self, "Screenshot: failed to create folder", "Failed to create output folder for screenshot!\n\n\tScreenshot not taken!",) + raise + outf = os.path.join(folder, base) + return outf + + def execute_collection(self): + app=QApplication.instance() + geo=app._geometry + task = self.active_task() + self._is_aborted = False + method = self._tabs_daq_methods.currentWidget().accessibleName() + + if task == TASK_GRID: + self.re_connect_collect_button( + callback=self.collect_abort_grid, + accessibleName="grid_abort", + label="Abort Grid Scan", + ) + self._inspect = self._grid_inspect_area + self._inspect.setPlainText("") + + geo=app._geometry + zoom=app._zoom.get_val() + fast_x=self.tweakers["fast_x"]; + fast_y=self.tweakers["fast_y"] + fx=fast_x.get_val() + fy=fast_y.get_val() + opt_ctr=geo._opt_ctr + for go in self._goTracked['objLst']: + points=go.get_points() #points in coordinate system of ROI + # names consists of abrevations + # part 0: po=position sz=size dt=delta + # part 1: px=pixel eu=engineering units (e.g. mm) + po_px=go.pos() + sz_px=go.size() + tr=go.transform() # TODO: this is not yet used + UsrGO.obj_info(tr) + dt_px=-opt_ctr-po_px + dt_eu=geo.pix2pos(dt_px)+(fx,fy) + for i in range(points.shape[0]): + points[i,:]=dt_eu+geo.pix2pos(points[i,:])#*tr + + method="grid" + params=None #grid._grid_dimensions + # params = ([grid._grid_dimensions[0]], [grid._grid_dimensions[1]]) # FIXME something wrong here< + self.daq_collect_points(points, visualizer_method=method, visualizer_params=params) + + #self.daq_grid_collect_grid() + elif task == TASK_PRELOCATED: + self._inspect = self._preloc_inspect_area + self._inspect.setPlainText("") + self.daq_prelocated_collect_points() + elif task == TASK_HELICAL: + self.daq_helical_collect() + elif task == TASK_EMBL: + self.daq_embl_collect_points() def escape_goToSampleExchange(self): self._escape_current_state = "busy" @@ -1516,14 +1307,784 @@ class Main(QMainWindow, Ui_MainWindow): self.escape_run_steps(steps, "Transitioning to Data Collection") self._escape_current_state = "DataCollection" - def move_gonio_to_position(self, fx, fy, bx, bz, omega): + def really_quit(self): + """called when user Ctrl-Q the app""" + if QMessageBox.question(self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes: + self._do_quit = True + self.close() + + def home_deltatau_faststages(self): + _log.warning("homing fast stages") + epics.PV("SAR-EXPMX1:ASYN.AOUT").put(b"enable plc 1") + + def prepare_left_tabs(self): + tabs = self._left_tabs + tabs.currentChanged.connect(self.switch_task) + + setup_tab = self._tab_setup + exp_tab = self._tab_experiment + + # add layouts + exp_tab.setLayout(QVBoxLayout()) + setup_tab.setLayout(QVBoxLayout()) + setup_tab.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) + self._setup_toolbox = tbox = QToolBox() + tbox.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Ignored)) + # tbox.setMinimumWidth(itemWidget.sizeHint().width()) + + setup_tab.layout().addWidget(tbox) + + # Jungfrau parameters + block = QWidget() + block.setAccessibleName(TASK_JUNGFRAU_SETTINGS) + block.setContentsMargins(0, 0, 0, 0) + block.setLayout(QVBoxLayout()) + #self.jungfrau = jungfrau_widget.JungfrauWidget() #ZAC: orig. code + #block.layout().addWidget(self.jungfrau) #ZAC: orig. code + block.layout().addStretch() + tbox.addItem(block, "Jungfrau Parameters") + + # # group beam box + # block = QWidget() + # block.setAccessibleName(TASK_SETUP_BEAM_CENTER) + # block.setContentsMargins(0, 0, 0, 0) + # block.setLayout(QVBoxLayout()) + # grp = QWidget() + # block.layout().addWidget(grp) + # block.layout().addStretch() + # grp.setLayout(QGridLayout()) + # tbox.addItem(block, "Beam Box") + # # setup_tab.layout().addWidget(grp) + # + # row = grp.layout().rowCount + # + # if self._pv_shutter is not None: + # but = QPushButton("open/close shutter") + # but.setCheckable(True) + # but.setChecked(1 == self._pv_shutter.get()) + # but.clicked.connect(self.toggle_shutter) + # self._button_shutter = but + # grp.layout().addWidget(but, 0, 0, 1, 2) + # self._pv_shutter.add_callback(self.update_shutter_label) + # #else: #ZAC: orig. code + # # self._picker = bernina_pulse_picker.PickerWidget() + # # grp.layout().addWidget(self._picker, 0, 0, 1, 2) + # but = QPushButton("clear beam markers") + # but.clicked.connect(self.remove_beam_markers) + # grp.layout().addWidget(but, 1, 1) + # help = QTextBrowser() + # grp.layout().addWidget(help, 2, 0, 5, 2) + # help.setHtml( + # """ + #

Updating Beam Mark

+ #
    + #
  1. clear beam markers
  2. + #
  3. for each zoom level, CTRL-Click (left mouse button) the center of the beam
  4. + #
+ # + # """ + # ) + + # # group regions + # block = QWidget() + # block.setAccessibleName(TASK_SETUP_ROI) + # block.setContentsMargins(0, 0, 0, 0) + # block.setLayout(QVBoxLayout()) + # grp = QWidget() + # block.layout().addWidget(grp) + # block.layout().addStretch() + # grp.setLayout(QGridLayout()) + # tbox.addItem(block, "Regions of Interest") + # but = QPushButton("add RECT roi") + # but.clicked.connect(self.roi_add_rect) + # grp.layout().addWidget(but, 0, 0) + # but = QPushButton("add LINE roi") + # but.clicked.connect(self.roi_add_line) + # grp.layout().addWidget(but, 0, 1) + # + # # group camera settings + # block = QWidget() + # block.setAccessibleName(TASK_SETUP_CAMERA) + # block.setContentsMargins(0, 0, 0, 0) + # block.setLayout(QVBoxLayout()) + # grp = QWidget() + # block.layout().addWidget(grp) + # block.layout().addStretch() + # grp.setLayout(QGridLayout()) + # tbox.addItem(block, "Camera Settings") + # but = QPushButton("remove transformations") + # but.clicked.connect(lambda bogus: self.modify_camera_transform("remove_all")) + # grp.layout().addWidget(but, 0, 0) + # but = QPushButton("remove last") + # but.clicked.connect(lambda bogus: self.modify_camera_transform("undo_last")) + # grp.layout().addWidget(but, 0, 1) + # but = QPushButton("Turn 90 CCW") + # #but.clicked.connect( + # # lambda bogus, n=camera.Transforms.ROTATE_90: self.modify_camera_transform(n) + # #) #ZAC: orig. code + # grp.layout().addWidget(but, 1, 0) + # but = QPushButton("Turn 90 CW") + # #but.clicked.connect(lambda bogus, n=camera.Transforms.ROTATE_270: self.modify_camera_transform(n)) #ZAC: orig. code + # grp.layout().addWidget(but) + # but = QPushButton("Turn 180 CCW") + # #but.clicked.connect(lambda bogus, n=camera.Transforms.ROTATE_180: self.modify_camera_transform(n)) #ZAC: orig. code + # grp.layout().addWidget(but) + # but = QPushButton("Transpose") + # #but.clicked.connect(lambda bogus, n=camera.Transforms.TRANSPOSE: self.modify_camera_transform(n)) #ZAC: orig. code + # grp.layout().addWidget(but) + # but = QPushButton("Flip L/R") + # #but.clicked.connect(lambda bogus, n=camera.Transforms.FLIP_LR: self.modify_camera_transform(n)) #ZAC: orig. code + # grp.layout().addWidget(but) + # but = QPushButton("Flip U/D") + # #but.clicked.connect(lambda bogus, n=camera.Transforms.FLIP_UD: self.modify_camera_transform(n)) #ZAC: orig. code + # grp.layout().addWidget(but) + # row = grp.layout().rowCount() + # self._label_transforms = QLabel() + # self._label_transforms.setWordWrap(True) + # self.modify_camera_transform(None) + # + # grp.layout().addWidget(self._label_transforms, row, 0, 1, 2) + + # group geometry calibration + block = QWidget() + block.setAccessibleName(TASK_SETUP_GEOMETRY_CALIB) + block.setContentsMargins(0, 0, 0, 0) + block.setLayout(QVBoxLayout()) + grp = QWidget() + block.layout().addWidget(grp) + block.layout().addStretch() + grp.setLayout(QGridLayout()) + tbox.addItem(block, "geometry calibration") + #grp.layout().addWidget(QLabel("feature size (µM)"), 0, 0) + #self._ppm_feature_size_spinbox = QDoubleSpinBox() + #self._ppm_feature_size_spinbox.setRange(5, 10000) + #self._ppm_feature_size_spinbox.setValue(50) + #self._ppm_feature_size_spinbox.setDecimals(0) + #self._ppm_feature_size_spinbox.setSuffix(" µM") + #grp.layout().addWidget(self._ppm_feature_size_spinbox, 0, 1) + self._btn_pix2pos = but = QPushButton("pix2pos") + but.setCheckable(True) + but.clicked.connect(self.update_pix2pos) + grp.layout().addWidget(but, 0, 0) + self._btn_opt_ctr = but = QPushButton("opt_ctr") + but.setCheckable(True) + but.clicked.connect(self.update_opt_ctr) + grp.layout().addWidget(but, 1, 0) + + help = QTextBrowser() + grp.layout().addWidget(help, 2, 0) + help.setHtml( + """ +

Pixel to position calibration

+
    +
  1. press: pix2pos
  2. +
  3. for each zoom level: +
  4. choose a good fiducial mark +
  5. move the stage x/y at min. 3 different locations +
  6. CTRL-Click (left mouse button) on the fiducial mark +
  7. un-click: pix2pos
  8. +
+

optical center calibration

+
    +
  1. press: opt_ctr
  2. +
  3. choose at least 3 fiducial mark visible at various zoom levels +
  4. for at least two zoom level: +
  5. CTRL-Click (left mouse button) on the fiducial marks +
  6. un-click: opt_ctr
  7. +
+ + """ + ) + + # grp = PpmToolBox(viewbox=self.vb, camera=sample_camera, signals=self) + # grp.setAccessibleName(TASK_SETUP_PPM_CALIBRATION_TBOX) + # grp.pixelPerMillimeterCalibrationChanged.connect(self.update_ppm_fitters) + # tbox.addItem(grp, "PPM ToolBox") + # self._ppm_toolbox = grp + + tbox.currentChanged.connect(self.switch_task) + + # final stretch + # setup_tab.layout().addStretch() + exp_tab.layout().addStretch() + + # DAQ Methods Tabs + self._OLD_build_daq_methods_grid_tab() + self._OLD_build_daq_methods_prelocated_tab() #ZAC: orig. code + self._OLD_create_helical_widgets() #ZAC: orig. code + self._OLD_build_daq_methods_embl_tab() + #self._OLD_build_sample_selection_tab() + + + def switch_task(self, index=0): + stack = self._centerpiece_stack + task = self._left_tabs.currentWidget().accessibleName() + setup_task = self._setup_toolbox.currentWidget().accessibleName() + method = self._tabs_daq_methods.currentWidget().accessibleName() + + _log.debug("Task switching: top_tabs={} exp.method={} setup_task={}".format(task, method, setup_task)) + + if task == "task_experiment": + stack.setCurrentIndex(0) + active_task = method + elif task == "task_setup": + active_task = setup_task + + elif task == "task_sample_selection": + active_task = TASK_SAMPLE_SELECTION + stack.setCurrentIndex(1) + else: + _log.error("BUG: un-handled task") + QMessageBox.warning(self, "BUG unhandled task!", "unhandled task: top_tabs={} method={}".format(task, method),) + self.set_active_task(active_task) + self._status_task.setText(active_task) + + def update_pix2pos(self, calib): + app=QApplication.instance() + if calib: + _log.info("received new pix2pos calibration") + app._raw_pix2pos=dict() + else: + s=str(app._raw_pix2pos).replace('),','),\n ').replace('],','],\n') + print(s) + res=QMessageBox.question(self, "calibration", f"use calibration\n{s} ? ") + if res==QMessageBox.Yes: + geo=app._geometry + geo.update_pix2pos(app._raw_pix2pos) + app._cfg.setValue(AppCfg.GEO_PIX2POS, geo._lut_pix2pos) + del app._raw_pix2pos + + def update_opt_ctr(self, calib): + app=QApplication.instance() + if calib: + _log.info("received new pix2pos calibration") + app._raw_opt_ctr=dict() + else: + s=str(app._raw_opt_ctr).replace('),','),\n ').replace('],','],\n') + print(s) + res=QMessageBox.question(self, "calibration", f"use calibration\n{s} ? ") + if res==QMessageBox.Yes: + geo=app._geometry + geo.update_optical_center(app._raw_opt_ctr) + app._cfg.setValue(AppCfg.GEO_OPT_CTR, geo._opt_ctr) + go=self._goOptCtr + oc_sz=go.size() + go.setPos(-geo._opt_ctr-oc_sz/2) + del app._raw_opt_ctr + return + + +# **************** OBSOLETE AND/OR OLD STUFF **************** + + +# functions are prefixed with _OLD_ + def _OLD_build_daq_methods_grid_tab(self): + self._grids = [] + tab = self._tab_daq_method_grid + layout = tab.layout() # gridlayout + self._sb_grid_x_step.setValue(30) + self._sb_grid_y_step.setValue(30) + self._bt_add_grid.clicked.connect(self._OLD_daq_grid_add_grid) + self._bt_remove_all_grids.clicked.connect(self._OLD_daq_grid_remove_all) + self._find_targets_from_microscope_image.clicked.connect(self._OLD_daq_grid_findxtals) + self.addGridRequest.connect(self._OLD_daq_grid_add_grid) + self.gridUpdated.connect(self._OLD_daq_grid_update) + + def _OLD_build_daq_methods_prelocated_tab(self): + tab = self._tab_daq_method_prelocated + self.prelocationModule = PrelocatedCoordinatesModel.PrelocatedCoordinates(parent=self) + tab.layout().addWidget(self.prelocationModule) + self.prelocationModule.prefixSelected.connect(lambda prefix: self._le_prefix.setText(prefix)) + self.prelocationModule.dataFileLoaded.connect(self._OLD_daq_method_prelocated_update_markers) + self.prelocationModule.prelocatedDataUpdated.connect(self._OLD_daq_method_prelocated_update_markers) + self.prelocationModule.markersDeleted.connect(self._OLD_daq_method_prelocated_remove_markers) + self.fiducialPositionSelected.connect(self._OLD_daq_method_prelocated_set_fiducial) + self.appendPrelocatedPosition.connect(self._OLD_daq_method_prelocated_append_data) + self.prelocationModule.moveFastStageRequest.connect(self._OLD_move_fast_stage) + self._preloc_inspect_area = QPlainTextEdit() + tab.layout().addWidget(self._preloc_inspect_area) + + def _OLD_build_daq_methods_embl_tab(self): + app = QApplication.instance() + self._tab_daq_method_embl.setLayout(QVBoxLayout()) + layout = self._tab_daq_method_embl.layout() + #motors = self.get_gonio_motors() + self._embl_module = EmblWidget(self) #ZAC: orig. code + #self._embl_module.configure(motors, app._camera, app._zoom) + layout.addWidget(self._embl_module) + + def _OLD_create_helical_widgets(self): + tbox = self._helical_tablebox + htab = self._helical_scan_table = HelicalTableWidget() + htab.gonioMoveRequest.connect(self._OLD_move_gonio_to_position) + tbox.setLayout(QVBoxLayout()) + + grp = QWidget() + grp.setLayout(QFormLayout()) + le = QSpinBox() + le.setRange(1, 100) + le.setValue(htab.scanHorizontalCount()) + le.valueChanged.connect(lambda cnt: htab.setScanHorizontalCount(cnt)) + grp.layout().addRow("Horizontal Count", le) + + le = QSpinBox() + le.setRange(1, 100) + le.setValue(htab.scanVerticalCount()) + le.valueChanged.connect(lambda cnt: htab.setScanVerticalCount(cnt)) + grp.layout().addRow("Vertical Count", le) + + le = QDoubleSpinBox() + le.setRange(-180.0, 180.0) + le.setSingleStep(5.0) + le.setSuffix(" degrees") + le.valueChanged.connect(htab.setStartAngle) + grp.layout().addRow("Start angle", le) + + tbox.layout().addWidget(grp) + widgi = QWidget() + widgi.setLayout(QHBoxLayout()) + tbox.layout().addWidget(widgi) + + but = QPushButton("Add Crystal") + but.clicked.connect(htab.add_xtal) + widgi.layout().addWidget(but) + + but = QPushButton("Set START") + but.clicked.connect(lambda: htab.set_xtal_start(self.get_gonio_positions())) + widgi.layout().addWidget(but) + + but = QPushButton("Set END") + but.clicked.connect(lambda: htab.set_xtal_end(self.get_gonio_positions())) + widgi.layout().addWidget(but) + + tbox.layout().addWidget(htab) + + def _OLD_add_beam_marker(self): + app = QApplication.instance() + cfg = app._cfg + w, h = cfg.value(AppCfg.GEO_BEAM_SZ) + self._beammark = bm = CstROI.BeamMark([100, 100], (int(w), int(h)), parent=self) + tr=QtGui.QTransform() # prepare ImageItem transformation: + tr.rotate(30) + bm.setTransform(tr) # assign transform + self.vb.addItem(self._beammark) + bm=UsrGO.BeamMark([50, 120], [30, 20]) + self.vb.addItem(bm) + vi=UsrGO.Grid((120, -100), (200, 150), (30, 20), 2) + self.vb.addItem(vi) + + def _OLD_camera_pause_toggle(self): + app=QApplication.instance() + app._camera.pause() + + def _OLD_new_frame_sim_cb(self, **kwargs): + app=QApplication.instance() + sim=app._camera._sim + imgSeq=sim['imgSeq'] + idx=sim['imgIdx'] + sim['imgIdx']=(idx+1)%imgSeq.shape[0] + # _log.info('simulated idx:{}'.format(idx)) + pic=imgSeq[idx] + self._goImg.setImage(pic) + + delay=500 # ms -> 2fps + QtCore.QTimer.singleShot(delay, self.new_frame_sim_cb) + + def _OLD_init_settings_tracker(self): + app=QApplication.instance() + cfg=app._cfg + _log.info("configuring widget persistence") + fields = { + # 'folder': (self._label_folder, str), + "project": (self._le_project, str), + "prefix": (self._le_prefix, str), + "actual_prefix": (self._label_actual_prefix, str), + "exposureTime": (self._dsb_exposure_time, float), + "oscillationAngle": (self._dsb_oscillation_step, float), + "blastRadius": (self._dsb_blast_radius, float), + } + for key, f_config in fields.items(): + widget, conv = f_config + value = cfg.value(key) + try: + wset, wget = widget.setText, widget.text + _log.debug("tracking text field {}".format(key)) + except AttributeError: + _log.debug("tracking {} number field {}".format(conv, key)) + wset, wget = widget.setValue, lambda fget=widget.value: conv(fget()) + except Exception as e: + _log.error(e) + + try: + wset(conv(value)) + except Exception as e: + _log.debug(e) + _log.warning('failed for "{}" updating field of type {} with {}'.format( key, type(widget), value)) + finally: + # _log.debug('wget = {}; wset = {}'.format(wget, wset)) + widget.editingFinished.connect(lambda w=widget, k=key, func_get=wget: self.persist_setting(k, func_get() ) ) + #self.storage_cascade_prefix(None) #ZAC: orig. code + + def _OLD_init_validators(self): + identifier_regex = QRegExp("[a-z-A-Z_0-9%]+") + self._le_project.setValidator(QRegExpValidator(identifier_regex, self._le_project)) + self._le_prefix.setValidator(QRegExpValidator(identifier_regex, self._le_prefix)) + + def _OLD_wire_storage(self): + self._le_prefix.textChanged.connect(self._OLD_storage_cascade_prefix) + self._le_prefix.textChanged.connect(lambda newtext: self.prefixChanged.emit(newtext)) + self._le_project.textChanged.connect(self._OLD_storage_cascade_prefix) + self._le_project.textChanged.connect(lambda newtext: self.projectChanged.emit(newtext)) + self._le_prefix.editingFinished.connect(self._OLD_prepare_daq_folder) + self._le_project.editingFinished.connect(self._OLD_prepare_daq_folder) + self.increaseRunNumberRequest.connect(self._OLD_increase_run_number) + + def _OLD_storage_cascade_prefix(self, val): + prefix = self._le_prefix.text() + if 0 == len(prefix): + _log.warning("empty prefix is not accepted") + self._le_prefix.setAccessibleName("invalid_input") + self._le_prefix.blockSignals(True) + self._le_prefix.setText("INVALID=>" + prefix) + QMessageBox.warning(self, "prefix is not valid", "Prefix is not valid!") + self._le_prefix.blockSignals(False) + + return + else: + self._le_prefix.setAccessibleName("") + project = self._le_project.text() + folders.set_prefix(prefix) + folders.set_project(project) + folders.run = settings.value("run_number", type=int) + self._label_runnumber.setText(f"{folders.run:04d}") + self._data_folder = folders.raw_folder + self.folderChanged.emit(folders.raw_folder) + self._label_actual_prefix.setText(folders.prefix) + self._label_folder.setText(folders.raw_folder) + + def _OLD_increase_run_number(self): + run = settings.value("run_number", type=int) + run += 1 + settings.setValue("run_number", run) + folders.run = run + self._label_runnumber.setText(f"{run:04d}") + + def _OLD_prepare_daq_folder(self): + global home, folders + prefix = folders.prefix + folder = folders.res_folder + if 0 == len(prefix): + return + + try: + os.makedirs(folder, 0o750, exist_ok=True) + except: + msg = "Failed to create folder: {}".format(folder) + _log.warning(msg) + QMessageBox.warning(self, "Screenshot: failed to create folder", "Failed to create output folder for screenshot!\n\n\tScreenshot not taken!",) + raise + + fname = os.path.join(folders.pgroup_folder, ".latest_raw") + try: + with open(fname, "w") as f: + f.write(folders.raw_folder) + _log.info("wrote: {}".format(fname)) + except: + _log.warning("failed writing {}".format(fname)) + + fname = os.path.join(folders.pgroup_folder, ".latest_res") + try: + with open(fname, "w") as f: + f.write(folders.res_folder) + _log.info("wrote: {}".format(fname)) + except: + _log.warning("failed writing {}".format(fname)) + + def _OLD_persist_setting(self, s, v): + app=QApplication.instance() + cfg=app._cfg + _log.debug("persisting {} = {}".format(s, v)) + cfg.setValue(s, v) + + def _OLD_method_changed(self, index): + method = self._tabs_daq_methods.currentWidget().accessibleName() + _log.info("method now => {}".format(method)) + + + + def _OLD_check_zescape(self): + msg = zescape.check() + if msg is None: + return + if "current" in msg: + _log.warning(f"current state: {self._escape_current_state}") + zescape.reply(self._escape_current_state) + elif "goto" in msg: + state = msg.split()[1].lower() + _log.warning(f"TELL requests to go to {state}") + try: + if "sampleexchange" in state: + _log.debug( + f"moving to mount with offset = {self._pin_mounting_offset}" + ) + self.move_gonio_to_mount_position(offset=self._pin_mounting_offset) + elif "samplealignment" in state: + self.escape_goToSampleAlignment() + except: + zescape.reply("Maintenance") + zescape.reply(self._escape_current_state) + else: # JSON + data = json.loads(msg) + if "sampleName" in data: + _log.debug(f"TELL SAMPLE DATA => {data}") + self.tell2storage(data) + zescape.reply("ack") + elif "pin_offset" in data: + _log.debug(f"TELL pin offset => {data}") + self._pin_mounting_offset = data["pin_offset"] + zescape.reply("ack") + elif "get_pin_offset" in data: + _log.debug(f"TELL get pin offset => {data}") + zescape.reply_json({"pin_offset": self._pin_mounting_offset}) + + def _OLD_tell2storage(self, sample): + _log.debug(f"2 TELL SAMPLE DATA => {type(sample)}") + self._le_prefix.setText(sample["sampleName"]) + self._le_project.setText(sample["sampleFolder"]) + tstf = folders.get_prefixed_file("_newsample") + self.storage_cascade_prefix(None) + _log.warning(f"sample info: {tstf}") + + def _OLD_is_task(self, task): + return task == self._active_task + + def _OLD_get_task_menu(self): + pass + + def _OLD_toggle_shutter(self, **kwargs): + if self._pv_shutter: + if 0 == self._pv_shutter.get(): + self._pv_shutter.put(1) + self._button_shutter.setText("shutter opened\n\u2622") + else: + self._pv_shutter.put(0) + self._button_shutter.setText("shutter closed\n\u2622") + elif self._has_pulse_picker: + pulsePicker.toggle() + + def _OLD_update_shutter_label(self, pvname, value, char_value, **kwargs): + if 0 == value: + self._button_shutter.setText("shutter closed") + else: + self._button_shutter.setText("shutter opened") + + def _OLD_build_sample_selection_tab(self): + self._sample_selection = sample_selection.SampleSelection(self) + self._sample_selection.move_to_mount_position = (self.move_gonio_to_mount_position) + self._tab_sample_selection.setLayout(QVBoxLayout()) + self._tab_sample_selection.layout().addWidget(self._sample_selection) + self._tab_sample_selection.layout().addStretch(2) + + def _OLD_build_embl_group(self): + grp = QGroupBox("EMBL Acquisition") + layout = QFormLayout() + grp.setLayout(layout) + layout.addWidget(QLabel("Prefix")) + self._embl_prefix = QLineEdit("img") + layout.addWidget(self._embl_prefix) + + def _OLD_abort_measurement(self, ev=None): + if settings.value(ACTIVATE_PULSE_PICKER): + pulsePicker.close() + jungfrau_detector.abort() + delta_tau.abort() + _log.debug("aborting measurement") + + def _OLD_trigger_detector(self, **kwargs): + if self._pv_shutter is not None: + self._pv_shutter.put(0) + # self._eiger_button_collect.show() + # self._eiger_button_abort.hide() + # self._eiger_now_collecting_label.setText( + # "Finished sequence id: {}\n" + # "Data in: Data10/{}".format( + # self._detector_sequence_id, self._eiger_now_collecting_file + # ) + # ) + + def _OLD_modify_camera_transform(self, t): + if t == "remove_all": + sample_camera.set_transformations([]) + elif t == "undo_last": + sample_camera._transformations.pop() + #elif type(t) ==type(camera.Transforms): #ZAC: orig. code + # sample_camera.append_transform(t) + try: + label = ", ".join([t.name for t in sample_camera._transformations]) + except: + label = "" + self._label_transforms.setText(label) + #settings.setValue(CAMERA_TRANSFORMATIONS, sample_camera._transformations) #ZAC: orig. code + + def _OLD_roi_add_line(self): + roi = pg.LineSegmentROI( + [200, 200], + [300, 300], + pen="r", + scaleSnap=True, + translateSnap=True, + rotateSnap=True, + removable=True, + ) + # roi.sigRegionChanged.connect(self.track_roi) + roi.sigRemoveRequested.connect(self.remove_roi) + self.vb.addItem(roi) + self._rois.append(roi) + + def _OLD_roi_add_rect(self): + roi = pg.RectROI( + [200, 200], + [50, 50], + pen="r", + scaleSnap=True, + translateSnap=True, + rotateSnap=True, + removable=True, + ) + roi.sigRegionChanged.connect(self.track_roi) + roi.sigRemoveRequested.connect(self.remove_roi) + self.vb.addItem(roi) + self._rois.append(roi) + + def _OLD_remove_roi(self, roi): + self.vb.removeItem(roi) + self._rois.remove(roi) + + def _OLD_prepare_microscope_page(self): + layout = self.microscope_page.layout() + container = QWidget() + hlay = QHBoxLayout() + container.setLayout(hlay) + layout.addWidget(container) + + def _OLD_update_beam_marker(self, zoom_lvl): + w, h = settings.value(BEAM_SIZE) + try: + bx = self.beamx_fitter(zoom_lvl) + by = self.beamy_fitter(zoom_lvl) + ok = True + except: + ok = False + _log.warning("beam marker not defined") + return + _log.debug("updating beam mark to {:.1f}x{:.1f}".format(bx, by)) + self.beamCameraCoordinatesChanged.emit(bx, by) + + def _OLD_update_beam_marker_fitters(self): + if len(self._beam_markers) > 2: + _log.debug("defining beam marker") + bx = [(n, x[0]) for n, x in self._beam_markers.items()] + by = [(n, x[1]) for n, x in self._beam_markers.items()] + nbx = np.asarray(bx).T + nby = np.asarray(by).T + bx_coefs = np.polyfit(nbx[0], nbx[1], 3) + by_coefs = np.polyfit(nby[0], nby[1], 3) + _log.debug(".... beam marker X coeficients {}".format(bx_coefs)) + _log.debug(".... beam marker Y coeficients {}".format(by_coefs)) + self.beamx_fitter = np.poly1d(bx_coefs) + self.beamy_fitter = np.poly1d(by_coefs) + + + def _OLD_append_to_beam_markers(self, x, y, zoom): + self._beam_markers[zoom] = (x, y) + _log.info("beam markers {}".format(self._beam_markers)) + settings.setValue(BEAM_MARKER_POSITIONS, self._beam_markers) + self.update_beam_marker_fitters() + + def _OLD_remove_beam_markers(self): + self._beam_markers = {} + self.beamx_fitter = None + self.beamy_fitter = None + + def _OLD_track_roi(self, roi): + x, y = roi.pos() + w, h = roi.size() + # area = roi.getArrayRegion(self._im, self.img) + # sum = np.sum(area) + # _log.info('{} => sum {}'.format((x,y), sum)) + bx, by = x + w / 2., y + h / 2. + _log.info("beam pos {}".format((bx, by))) + _log.info("marker pos = {} ; size = {}".format((x, y), (w, h))) + + def _OLD_toggle_mouse_tracking(self): + if self._mouse_tracking: + self.disengage_mouse_tracking() + else: + self.engage_mouse_tracking() + + def _OLD_engage_mouse_tracking(self): + self.glw.scene().sigMouseMoved.connect(self.mouse_move_event) + self.glw.scene().sigMouseMoved.emit() + self._mouse_tracking = True + + def _OLD_disengage_mouse_tracking(self): + self.glw.scene().sigMouseMoved.disconnect(self.mouse_move_event) + self._mouse_tracking = False + self._lb_coords.setText("") + + def _OLD_mouse_click_event_geometry_calib(self, event): + app=QApplication.instance() + zoom = app._zoom.get_val() + fast_x=self.tweakers["fast_x"];fast_y=self.tweakers["fast_y"] + if self._btn_pix2pos.isChecked(): + try: + raw=app._raw_pix2pos[zoom] + except KeyError as e: + raw=app._raw_pix2pos[zoom]=list() + imgPos=self._goImg.mapFromScene(event.scenePos()) + fx=fast_x.get_rbv(); + fy=fast_y.get_rbv() + x=imgPos.x();y=imgPos.y() + _log.debug('append calib: zoom:{} stage_x_y:{}/{} cam_pix_x_y:{}/{}'.format(zoom, fx, fy, x, y)) + raw.append((fx, fy, x, y)) + elif self._btn_opt_ctr.isChecked(): + try: + raw=app._raw_opt_ctr[zoom] + except KeyError as e: + raw=app._raw_opt_ctr[zoom]=list() + imgPos=self._goImg.mapFromScene(event.scenePos()) + x=imgPos.x();y=imgPos.y() + _log.debug('append calib: zoom:{} cam_pix_x_y:{}/{}'.format(zoom, x, y)) + raw.append(( x, y)) + else: + QMessageBox.warning(self, "calibration", "no calibration started yet.\nPress 'pix2pos' or 'opt_ctr' button first") + + def _OLD_get_beam_mark_on_camera_xy(self): + app=QApplication.instance() + z = app._zoom.get_val() + try: + bx = self.beamx_fitter(z) + by = self.beamy_fitter(z) + except: + bx, by = 500, 500 + return (bx, by) + + def _OLD_escape_run_steps(self, steps, title): + with pg.ProgressDialog(title, 0, len(steps)) as dlg: + for step in steps: + step() + dlg += 1 + if dlg.wasCanceled(): + raise TransitionAborted("ABORTED" + title) + + def _OLD_move_gonio_to_position(self, fx, fy, bx, bz, omega): self.tweakers["fast_x"].motor.move(fx, wait=False, ignore_limits=True) self.tweakers["fast_y"].motor.move(fy, wait=False, ignore_limits=True) self.tweakers["base_x"].motor.move(bx, wait=False, ignore_limits=True) self.tweakers["base_z"].motor.move(bz, wait=False, ignore_limits=True) self.tweakers["omega"].motor.move(omega, wait=False, ignore_limits=True) - def get_gonio_motors(self, as_json=False): + def _OLD_get_gonio_motors(self, as_json=False): if as_json: return { "fast_x": self.tweakers["fast_x"].motor, @@ -1541,7 +2102,7 @@ class Main(QMainWindow, Ui_MainWindow): self.tweakers["omega"].motor, ) - def get_gonio_tweakers(self): + def _OLD_get_gonio_tweakers(self): return ( self.tweakers["fast_x"], self.tweakers["fast_y"], @@ -1550,7 +2111,7 @@ class Main(QMainWindow, Ui_MainWindow): self.tweakers["omega"], ) - def get_gonio_positions(self, as_json: bool = False): + def _OLD_get_gonio_positions(self, as_json: bool = False): fx, fy, cx, cz, omega = ( self.tweakers["fast_x"].motor, self.tweakers["fast_y"].motor, @@ -1571,11 +2132,11 @@ class Main(QMainWindow, Ui_MainWindow): else: return (a, b, c, d, e) - def escape_goToTellMountPosition(self): + def _OLD_escape_goToTellMountPosition(self): self.move_gonio_to_mount_position() self.lock_goniometer() - def move_gonio_to_mount_position(self, offset: float = 0.0): + def _OLD_move_gonio_to_mount_position(self, offset: float = 0.0): fx, fy, cx, cz, omega = self.get_gonio_motors() bmark = "bookmark_0" try: @@ -1602,7 +2163,7 @@ class Main(QMainWindow, Ui_MainWindow): ) self.escape_goToSampleExchange() - def lock_goniometer(self): + def _OLD_lock_goniometer(self): # tell.set_in_mount_position(True) res = QMessageBox.question(self, "", "Mount a sample from console and click ok once the sample is mounted.", QMessageBox.Ok, QMessageBox.Ok,) res = QMessageBox.question(self, "", "Is the sample is mounted?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) @@ -1611,7 +2172,7 @@ class Main(QMainWindow, Ui_MainWindow): pass @pyqtSlot(int) - def saveBookmark(self, key: int): + def _OLD_saveBookmark(self, key: int): """save a bookmark for the corresponding key is the Qt.Key_* code """ fx, fy, cx, cz, omega = ( self.tweakers["fast_x"].motor, @@ -1642,7 +2203,7 @@ class Main(QMainWindow, Ui_MainWindow): settings.setValue(bmark + "/mount_cz", cz.get_position()) settings.setValue(bmark + "/mount_omega", omega.get_position()) - def gotoBookmark(self, key: int): + def _OLD_gotoBookmark(self, key: int): """save a bookmark for the corresponding key""" fx, fy, cx, cz, omega = ( self.tweakers["fast_x"].motor, @@ -1667,7 +2228,7 @@ class Main(QMainWindow, Ui_MainWindow): cz.move(t_cz, wait=True, ignore_limits=True) omega.move(t_omega, wait=True, ignore_limits=True) - def move_collimator(self, pos): + def _OLD_move_collimator(self, pos): cx = self.tweakers["colli_x"] cy = self.tweakers["colli_y"] @@ -1696,7 +2257,7 @@ class Main(QMainWindow, Ui_MainWindow): else: raise UnknownLabeledPosition("Collimator position *{}* is not known!!") - def move_cryojet_nozzle(self, pos): + def _OLD_move_cryojet_nozzle(self, pos): cx = self.tweakers["cryo"] if "in" == pos.lower(): key = CRYOJET_NOZZLE_IN @@ -1708,70 +2269,7 @@ class Main(QMainWindow, Ui_MainWindow): raise IncompleteConfiguration(f"CRYOJET configuration is incomplete! Missing {key}") cx.move_motor_to_position(to_pos, assert_position=True) - def setup_sliders(self): - cont = self._rightmost - self._tweak_container = QWidget() - self._tweak_container.setLayout(QVBoxLayout()) - cont.layout().addWidget(self._tweak_container) - layout = self._tweak_container.layout() - layout.setSpacing(0) - layout.setContentsMargins(0, 0, 0, 0) - if self._at_x06sa: - zoom_base = "ESBMX-SAMCAM" # fetura IOC by Jose Gabadinho - elif self._at_lab_eh060: - zoom_base = "/dev/ttyUSB0" # direct connection using fetura.py package - elif self._at_cristalina: - zoom_base = ("rest://pc12818.psi.ch:9999") # direct connection using fetura.py package - - self.zoombox = zoom.Zoom() - self.zoombox.init_settings() - self.zoombox.zoomChanged.connect(self.zoom_changed_cb) - self.zoombox.moveBacklight.connect(self.safe_backlight_move) - - layout.addWidget(self.zoombox) - - toolbox = QToolBox() - layout.addWidget(toolbox) - - self.build_faststage_group(toolbox) - # self.build_slits_group(toolbox) - self.build_collimator_group(toolbox) - self.build_posttube_group(toolbox) - self.build_xeye_group(toolbox) - self.build_cryo_group(toolbox) - - # monitor all axis for an axis fault - for key, tweaker in self.tweakers.items(): - tweaker.event_axis_fault.connect(self.axis_fault) - - #self.tweakers["fast_x"].event_readback.connect(lambda alias, value, kw: self.fast_x_position.emit(value)) - #self.tweakers["fast_y"].event_readback.connect(lambda alias, value, kw: self.fast_y_position.emit(value)) - - self.tweakers["fast_x"].event_val.connect(lambda rec_name, kw: self.track_objects()) - self.tweakers["fast_y"].event_val.connect(lambda rec_name, kw: self.track_objects()) - # layout.addStretch() - - def axis_fault(self, pvname, kw): - """ - swissmx - {'pvname': 'SAR-EXPMX:MOT_FY.STAT', 'value': 0, 'char_value': 'NO_ALARM', 'status': 0, 'ftype': 17, 'chid': 38980392, - 'host': 'SAR-CPPM-EXPMX1.psi.ch:5064', 'count': 1, 'access': 'read-only', 'write_access': False, 'read_access': True, - 'severity': 0, - 'timestamp': 1537867290.914189, 'precision': None, 'units': None, 'enum_strs': ('NO_ALARM', 'READ', 'WRITE', 'HIHI', 'HIGH', 'LOLO', 'LOW', 'STATE', 'COS', 'COMM', 'TIMEOUT', 'HWLIMIT', 'CALC', 'SCAN', 'LINK', 'SOFT'), 'upper_disp_limit': None, 'lower_disp_limit': None, 'upper_alarm_limit': None, 'lower_alarm_limit': None, 'lower_warning_limit': None, 'upper_warning_limit': None, 'upper_ctrl_limit': None, 'lower_ctrl_limit': None, 'nelm': 1, 'type': 'time_enum', 'typefull': 'time_enum', 'motor_field': 'STAT', 'source_field': 'STAT', 'cb_info': (1, ), 'alias': 'fast Y'} - - :param pvname: - :param kw: - :return: - """ - _log.debug(f"AXIS FAULT: {kw}") - if kw["severity"]: - msg = f"axis {pvname} has a fault" - _log.critical(msg) - _log.critical(f"{kw}") - else: - msg = "" - self._message_critical_fault.setText(msg) - - def build_cryo_group(self, toolbox): + def _OLD_build_cryo_group(self, toolbox): qutilities.add_item_to_toolbox( toolbox, "Cryojet", @@ -1780,19 +2278,7 @@ class Main(QMainWindow, Ui_MainWindow): ], ) - def build_faststage_group(self, toolbox): - qutilities.add_item_to_toolbox(toolbox,"Fast Stage", - widget_list=[ - # self.get_tweaker('SAR-EXPMX:MOT_BLGT', alias='backlight', label='backlight'), - self.get_tweaker("SAR-EXPMX:MOT_FY", alias="fast_y", label="fast Y"), - self.get_tweaker("SAR-EXPMX:MOT_FX", alias="fast_x", label="fast X"), - self.get_tweaker("SAR-EXPMX:MOT_ROT_Y",alias="omega",label="omega",tweak_min=0.001,tweak_max=180.0,), - self.get_tweaker("SAR-EXPMX:MOT_CX", alias="base_x", label="base X"), - self.get_tweaker("SAR-EXPMX:MOT_CZ", alias="base_z", label="base Z"), - ], - ) - - def build_wegde_group(self, toolbox): + def _OLD_build_wegde_group(self, toolbox): qutilities.add_item_to_toolbox(toolbox,"Wedge Mover", widget_list=[ self.get_tweaker("SAR-EXPMX:MOT_WEDGE1", alias="wedge_1", label="wedge_1"), @@ -1806,15 +2292,7 @@ class Main(QMainWindow, Ui_MainWindow): ], ) - def build_collimator_group(self, toolbox): - qutilities.add_item_to_toolbox(toolbox,"Collimator", - widget_list=[ - self.get_tweaker("SARES30-ESBMX1", alias="colli_x", label="colli X", mtype="smaract_motor",), - self.get_tweaker("SARES30-ESBMX2", alias="colli_y", label="colli Y", mtype="smaract_motor",), - ], - ) - - def build_slits_group(self, toolbox): + def _OLD_build_slits_group(self, toolbox): qutilities.add_item_to_toolbox( toolbox, "Slits", @@ -1826,90 +2304,7 @@ class Main(QMainWindow, Ui_MainWindow): ], ) - def build_xeye_group(self, toolbox): - qutilities.add_item_to_toolbox( - toolbox, - "X-Ray Eye", - widget_list=[ - self.get_tweaker("SARES30-ESBMX14", alias="xeye_x", label="X", mtype="smaract_motor"), - self.get_tweaker("SARES30-ESBMX15", alias="xeye_y", label="Y", mtype="smaract_motor"), - ], - ) - - def build_posttube_group(self, toolbox): - widgets = [ - self.get_tweaker("SARES30-ESBMX4", alias="tube_usx", label="upstream X", mtype="smaract_motor",), - self.get_tweaker("SARES30-ESBMX6", alias="tube_usy", label="upstream Y", mtype="smaract_motor",), - self.get_tweaker("SARES30-ESBMX5", alias="tube_dsx", label="downstream X", mtype="smaract_motor",), - self.get_tweaker("SARES30-ESBMX7", alias="tube_dsy", label="downstream Y", mtype="smaract_motor",), - self.get_tweaker("SARES30-ESBMX8", alias="tube_z", label="tube Z", mtype="smaract_motor"), - ] - c = QWidget() - c.setLayout(QGridLayout()) - but = QPushButton("post tube out") - but.clicked.connect(lambda m, dir="out": self.move_post_tube(dir)) - c.layout().addWidget(but, 0, 0) - but = QPushButton("post tube in") - but.clicked.connect(lambda m, dir="in": self.move_post_tube(dir)) - c.layout().addWidget(but, 0, 1) - widgets.append(c) - - label = "Post Sample Tube" - block = QWidget() - block.setAccessibleName(label) - block.setContentsMargins(0, 0, 0, 0) - block.setLayout(QVBoxLayout()) - for w in widgets: - block.layout().addWidget(w) - - block.layout().addWidget(self.build_post_tube_tandem_tweaker()) - block.layout().addStretch() - toolbox.addItem(block, label) - - def build_post_tube_tandem_tweaker(self): - block = QWidget() - block.setAccessibleName("post tube tamden") - block.setContentsMargins(0, 0, 0, 0) - block.setLayout(QVBoxLayout()) - c = QWidget() - glay = QGridLayout() - c.setLayout(glay) - - b = QWidget() - blay = QHBoxLayout() - b.setLayout(blay) - blay.addWidget(QLabel("Tweak (mm)")) - self._post_tandem_tweak_val = QLineEdit("1.0") - blay.addWidget(self._post_tandem_tweak_val) - glay.addWidget(b, 0, 0, 1, 2) - - icon = qtawesome.icon("material.arrow_back") - but = QPushButton(icon, "") - but.clicked.connect(lambda m, dir="x-pos": self.move_post_tube(dir)) - glay.addWidget(but, 1, 0) - - # c.setLayout(glay) - icon = qtawesome.icon("material.arrow_forward") - but = QPushButton(icon, "") - but.clicked.connect(lambda m, dir="x-neg": self.move_post_tube(dir)) - glay.addWidget(but, 1, 1) - - # c.setLayout(glay) - icon = qtawesome.icon("material.arrow_downward") - but = QPushButton(icon, "") - but.clicked.connect(lambda m, dir="down": self.move_post_tube(dir)) - glay.addWidget(but, 2, 0) - - # c.setLayout(glay) - icon = qtawesome.icon("material.arrow_upward") - but = QPushButton(icon, "") - but.clicked.connect(lambda m, dir="up": self.move_post_tube(dir)) - glay.addWidget(but, 2, 1) - - block.layout().addWidget(c) - return block - - def assert_post_tube_position(self, pos): + def _OLD_assert_post_tube_position(self, pos): x_up = settings.value("post_sample_tube/x_up", 1e10, type=float) y_up = settings.value("post_sample_tube/y_up", 1e10, type=float) x_down = settings.value("post_sample_tube/x_down", 1e10, type=float) @@ -1949,7 +2344,7 @@ class Main(QMainWindow, Ui_MainWindow): (tbz, z, 0.1),],timeout=2.0, ) - def move_post_tube(self, dir): + def _OLD_move_post_tube(self, dir): app=QApplication.instance() cfg=app._cfg x_up = cfg.value(AppCfg.PST_X_UP , type=float) @@ -2045,24 +2440,7 @@ class Main(QMainWindow, Ui_MainWindow): usy.move_relative(-tandem_twv) dsy.move_relative(-tandem_twv) - def get_tweaker(self, rec, alias=None, label=None, mtype="epics_motor", layout=None, **kwargs): - app = QApplication.instance() - sim=app._args.sim - if mtype == "epics_motor": - if sim&0x10: - m=SimMotorTweak() - else: - m = MotorTweak() - else: - if sim&0x20: - m=SimMotorTweak() - else: - m = SmaractMotorTweak() - m.connect_motor(rec, label, **kwargs) - self.tweakers[alias] = m - return m - - def add_tweaker(self, pv, alias=None, label=None, mtype="epics_motor", layout=None): + def _OLD_add_tweaker(self, pv, alias=None, label=None, mtype="epics_motor", layout=None): if layout is None: layout = self._tweak_container.layout() if mtype == "epics_motor": @@ -2073,54 +2451,10 @@ class Main(QMainWindow, Ui_MainWindow): m.connect_motor(pv, label) self.tweakers[alias] = m - def done_sliding(self): + def _OLD_done_sliding(self): print("done sliding at {}".format(self.slider_fast_x.value())) - @pyqtSlot() - def saveSampleCameraScreenshot(self): - outf = self.get_screenshot_filename() - _log.info("saving original clean screenshot: {}".format(outf)) - try: - sample_camera.saveimage(outf) - except Exception as e: - _log.warning(e) - QMessageBox.warning(self, "Screenshot: failed to save image", "Failed to save screenshot!") - - @pyqtSlot() - def saveSampleCameraScreenshotView(self): - outf = self.get_screenshot_filename() - _log.info("saving view screenshot: {}".format(outf)) - - exporter = pg.exporters.ImageExporter(self.vb) - - # set export parameters if needed - exporter.parameters()["width"] = 2000 # (note this also affects height parameter) - - # save to file - try: - exporter.export(outf) - except Exception as e: - _log.warning(e) - QMessageBox.warning(self, "Screenshot: failed to save viewer image", "Failed to save screenshot of viewer!",) - - def get_screenshot_filename(self): - global folders - _log.info("taking screenhot") - prefix = folders.prefix - folder = folders.res_folder - base = time.strftime("{}_%Y%m%d_%H%M%S.png".format(prefix)) - if not os._exists(folder): - try: - os.makedirs(folder, 0o750, exist_ok=True) - except: - msg = "Failed to create folder: {}".format(folder) - _log.warning(msg) - QMessageBox.warning(self, "Screenshot: failed to create folder", "Failed to create output folder for screenshot!\n\n\tScreenshot not taken!",) - raise - outf = os.path.join(folder, base) - return outf - - def daq_grid_add_grid(self, gx=None, gy=None): + def _OLD_daq_grid_add_grid(self, gx=None, gy=None): grid_index = len(self._grids) if gx in (False, None): gx=self.tweakers["fast_x"].get_rbv() @@ -2155,26 +2489,26 @@ class Main(QMainWindow, Ui_MainWindow): #grid.calculate_gonio_xy() #grid.sigRemoveRequested.connect(lambda g=grid: self.remove_grid(g)) - def daq_grid_remove_all(self): + def _OLD_daq_grid_remove_all(self): vb=self.vb for go in self._goTracked['objLst']: vb.removeItem(go) self._goTracked['objLst']=[] - def grids_pause_stage_tracking(self): + def _OLD_grids_pause_stage_tracking(self): for grid in self._grids: grid.disable_stage_tracking() - def grids_start_stage_tracking(self): + def _OLD_grids_start_stage_tracking(self): for grid in self._grids: grid.enable_stage_tracking() - def remove_grid(self, grid): + def _OLD_remove_grid(self, grid): self.vb.removeItem(grid) self._grids.remove(grid) - def daq_grid_update(self, grid_index): + def _OLD_daq_grid_update(self, grid_index): try: grid = self._grids[grid_index] except: @@ -2192,7 +2526,7 @@ class Main(QMainWindow, Ui_MainWindow): m = "Number of points: {}\nEstimated Time: {:.1f} minutes".format(num_points, num_points * etime / 60.) self._label_grid_parameters.setText(m) - def daq_embl_collect_points(self): + def _OLD_daq_embl_collect_points(self): coords = self._embl_module.coords points = [[x, y] for x, y, bx, bz, o in coords] points = np.array(points) @@ -2201,7 +2535,7 @@ class Main(QMainWindow, Ui_MainWindow): params = (xp[:, 0].tolist(), xp[:, 1].tolist()) self.daq_collect_points(points, visualizer_method=method, visualizer_params=params) - def daq_prelocated_collect_points(self): + def _OLD_daq_prelocated_collect_points(self): points = [] data = self.prelocationModule.get_collection_targets() for n, cc in enumerate(data): @@ -2213,12 +2547,12 @@ class Main(QMainWindow, Ui_MainWindow): params = (xp[:, 0].tolist(), xp[:, 1].tolist()) self.daq_collect_points(points, visualizer_method=method, visualizer_params=params) - def daq_grid_findxtals(self): + def _OLD_daq_grid_findxtals(self): feature_size = self._sb_findxtals_feature_size.value() image = sample_camera.get_image() findObj(-image, objSize=feature_size, viz=1) - def check_jungfrau_save(self) -> bool: + def _OLD_check_jungfrau_save(self) -> bool: if jungfrau_detector.is_running_detector(): saveRaw = jungfrau_detector.is_saving_data() @@ -2242,7 +2576,7 @@ class Main(QMainWindow, Ui_MainWindow): return True return True - def daq_collect_points(self, points, visualizer_method, visualizer_params): + def _OLD_daq_collect_points(self, points, visualizer_method, visualizer_params): app = QApplication.instance() cfg = app._cfg verbose=0xff @@ -2405,7 +2739,7 @@ class Main(QMainWindow, Ui_MainWindow): sequencer_steps.append(lambda: shapepath.trigger(wait=0.5)) - def shapepath_progress(): + def _OLD_shapepath_progress(): while True: p = shapepath.progress() if p < 0: @@ -2434,7 +2768,7 @@ class Main(QMainWindow, Ui_MainWindow): self._thread.started.connect(self.sequencer.run_sequence) self._thread.start() - def run_steps(self, steps, title, at_end=None, cancelable=False): + def _OLD_run_steps(self, steps, title, at_end=None, cancelable=False): dlg = QProgressDialog(self) dlg.setWindowTitle(title) dlg.setWindowModality(Qt.WindowModal) @@ -2499,7 +2833,7 @@ class Main(QMainWindow, Ui_MainWindow): at_end() dlg.reset() - def daq_collect_points_wrapup(self): + def _OLD_daq_collect_points_wrapup(self): self.qprogress.reset() if self._thread.isRunning(): self._thread.quit() @@ -2530,13 +2864,13 @@ class Main(QMainWindow, Ui_MainWindow): jungfrau_detector.abort() self.increaseRunNumberRequest.emit() - def daq_collect_update_inspect(self, msg): + def _OLD_daq_collect_update_inspect(self, msg): te = self._inspect m = te.toPlainText() te.setPlainText(m + msg + "\n") te.verticalScrollBar().setValue(te.verticalScrollBar().maximum()) - def daq_helical_collect(self): + def _OLD_daq_helical_collect(self): """[ [{ 0: (0.0, 1.238401694734829, 3.527, 0.936, 0.001), @@ -2675,7 +3009,7 @@ class Main(QMainWindow, Ui_MainWindow): sequencer_steps.append(lambda: helical.trigger()) - def motion_progress(): + def _OLD_motion_progress(): while True: p = helical.progress() if p < 0: @@ -2699,7 +3033,7 @@ class Main(QMainWindow, Ui_MainWindow): self._thread.started.connect(self.sequencer.run_sequence) self._thread.start() - def daq_helical_collect_wrapup(self): + def _OLD_daq_helical_collect_wrapup(self): try: self.qprogress.reset() except: @@ -2718,7 +3052,7 @@ class Main(QMainWindow, Ui_MainWindow): hsgui = HelicalScanGui(helical) hsgui.interactive_anim() - def complete_daq(self): + def _OLD_complete_daq(self): _log.info("daq completed: cleaning up") try: self.qprogress.reset() @@ -2733,21 +3067,7 @@ class Main(QMainWindow, Ui_MainWindow): self.abort_measurement() self.re_connect_collect_button() - def build_daq_methods_grid_tab(self): - self._grids = [] - tab = self._tab_daq_method_grid - layout = tab.layout() # gridlayout - self._sb_grid_x_step.setValue(30) - self._sb_grid_y_step.setValue(30) - self._bt_add_grid.clicked.connect(self.daq_grid_add_grid) - self._bt_remove_all_grids.clicked.connect(self.daq_grid_remove_all) - self._find_targets_from_microscope_image.clicked.connect( - self.daq_grid_findxtals - ) - self.addGridRequest.connect(self.daq_grid_add_grid) - self.gridUpdated.connect(self.daq_grid_update) - - def re_connect_collect_button(self, callback=None, **kwargs): + def _OLD_re_connect_collect_button(self, callback=None, **kwargs): _log.debug("re_connect_collect_button() {} => {}".format(callback, kwargs)) return # button = self._button_collect @@ -2768,7 +3088,7 @@ class Main(QMainWindow, Ui_MainWindow): # button.setText(kwargs["label"]) # self.load_stylesheet() - def collect_abort_grid(self): + def _OLD_collect_abort_grid(self): self._is_aborted = True try: self._eigerwaitthread._is_aborted = True @@ -2780,59 +3100,7 @@ class Main(QMainWindow, Ui_MainWindow): jungfrau_detector.disarm() self.re_connect_collect_button() - def execute_collection(self): - app=QApplication.instance() - geo=app._geometry - task = self.active_task() - self._is_aborted = False - method = self._tabs_daq_methods.currentWidget().accessibleName() - - if task == TASK_GRID: - self.re_connect_collect_button( - callback=self.collect_abort_grid, - accessibleName="grid_abort", - label="Abort Grid Scan", - ) - self._inspect = self._grid_inspect_area - self._inspect.setPlainText("") - - geo=app._geometry - zoom=app._zoom.get_val() - fast_x=self.tweakers["fast_x"]; - fast_y=self.tweakers["fast_y"] - fx=fast_x.get_val() - fy=fast_y.get_val() - opt_ctr=geo._opt_ctr - for go in self._goTracked['objLst']: - points=go.get_points() #points in coordinate system of ROI - # names consists of abrevations - # part 0: po=position sz=size dt=delta - # part 1: px=pixel eu=engineering units (e.g. mm) - po_px=go.pos() - sz_px=go.size() - tr=go.transform() # TODO: this is not yet used - UsrGO.obj_info(tr) - dt_px=-opt_ctr-po_px - dt_eu=geo.pix2pos(dt_px)+(fx,fy) - for i in range(points.shape[0]): - points[i,:]=dt_eu+geo.pix2pos(points[i,:])#*tr - - method="grid" - params=None #grid._grid_dimensions - # params = ([grid._grid_dimensions[0]], [grid._grid_dimensions[1]]) # FIXME something wrong here< - self.daq_collect_points(points, visualizer_method=method, visualizer_params=params) - - #self.daq_grid_collect_grid() - elif task == TASK_PRELOCATED: - self._inspect = self._preloc_inspect_area - self._inspect.setPlainText("") - self.daq_prelocated_collect_points() - elif task == TASK_HELICAL: - self.daq_helical_collect() - elif task == TASK_EMBL: - self.daq_embl_collect_points() - - def create_escape_toolbar(self): + def _OLD_create_escape_toolbar(self): cont = self._rightmost w = QGroupBox("Escape") layout = QHBoxLayout() @@ -2852,170 +3120,7 @@ class Main(QMainWindow, Ui_MainWindow): layout.addWidget(but) cont.layout().addWidget(w) - def init_actions(self): - app = QApplication.instance() - cfg = app._cfg - self.toolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) - - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_S), self) - self.shortcut.activated.connect(self.saveSampleCameraScreenshot) - - self.shortcut = QShortcut(QKeySequence(Qt.Key_F2), self) - self.shortcut.activated.connect(self.saveSampleCameraScreenshot) - - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_S), self) - self.shortcut.activated.connect(self.saveSampleCameraScreenshotView) - - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_T), self) - self.shortcut.activated.connect(lambda: qutilities.toggle_warn(SKIP_ESCAPE_TRANSITIONS_IF_SAFE)) - - for k in range(10): - qkey = k + Qt.Key_0 - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + qkey), self) - self.shortcut.activated.connect(lambda key=k: self.saveBookmark(key)) - - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + qkey), self) - self.shortcut.activated.connect(lambda key=k: self.gotoBookmark(key)) - - self._button_collect.clicked.connect(self.execute_collection) - - # Toolbar buttons - icon_size = QSize(50, 50) - - icon = qtawesome.icon("material.photo_camera") - action = QAction(icon, "Save View", self) - action.setToolTip("(Ctrl+S) Take a screenshot of the currently visible sample image, including markers. Saves in current folder.") - action.triggered.connect(self.saveSampleCameraScreenshotView) - self.toolBar.addAction(action) - - action = QAction(icon, "Save Original", self) - action.setToolTip("(Ctrl+Shift+S) Take a screenshot of the sample image, without markers. Saves in current folder.") - action.triggered.connect(self.saveSampleCameraScreenshot) - self.toolBar.addAction(action) - - if os.getenv("DEVELOPMENT_VERSION"): - icon = qtawesome.icon("material.style") - action = QAction(icon, "Reload Stylesheet", self) - action.triggered.connect(self.load_stylesheet) - self.toolBar.addAction(action) - - # icon = qtawesome.icon("material.shutter_speed") - action = QAction("Use Pulse Picker", self) - action.setCheckable(True) - action.setChecked(cfg.option(AppCfg.ACTIVATE_PULSE_PICKER)) - action.triggered.connect(lambda: cfg.toggle_option(AppCfg.ACTIVATE_PULSE_PICKER)) - self.toolBar.addAction(action) - - icon = qtawesome.icon("material.timeline") - action = QAction(icon, "Add Line", self) - action.triggered.connect(self.roi_add_line) - self.toolBar.addAction(action) - - icon = qtawesome.icon("material.tab_unselected") - action = QAction(icon, "Add Rect", self) - action.triggered.connect(self.roi_add_rect) - self.toolBar.addAction(action) - - icon = qtawesome.icon("material.play_for_work") - action = QAction(icon, "TELL Mount", self) - action.setToolTip("BookMark(0) => Move stages CZ, CX, FX, FY, and Omega to Tell sample changer mount position") - action.triggered.connect(self.escape_goToTellMountPosition) - self.toolBar.addAction(action) - - self.toolBar.addWidget(qutilities.horiz_spacer()) - - icon = qtawesome.icon("material.sync") - action = QAction(icon, "Sample\nExchange", self) - action.setToolTip("Move devices so a sample can be exchanged.") - action.setObjectName("action_SampleExchange") - action.triggered.connect(self.escape_goToSampleExchange) - self.toolBar.addAction(action) - self.toolBar.widgetForAction(action).setAccessibleName("action_SampleExchange") - - icon = qtawesome.icon("material.my_location") - action = QAction(icon, "Sample\nAlignment", self) - action.setToolTip("Move devices so a sample can be aligned.") - action.triggered.connect(self.escape_goToSampleAlignment) - self.toolBar.addAction(action) - self.toolBar.widgetForAction(action).setAccessibleName("action_SampleAlignment") - - icon = qtawesome.icon("material.fingerprint") - action = QAction(icon, "Data\nCollection", self) - action.setToolTip("Move devices so a sample can be collected.") - action.triggered.connect(self.escape_goToDataCollection) - self.toolBar.addAction(action) - self.toolBar.widgetForAction(action).setAccessibleName("action_DataCollection") - - self.actionQuit.triggered.connect(self.really_quit) - self.actionPreferences.triggered.connect(self.openPreferencesDialog) - self.actionHome_Fast_Stages.triggered.connect(self.home_deltatau_faststages) - self.actionUser_Storage.triggered.connect(self.update_user_and_storage) - - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_L), self) - self.shortcut.activated.connect(self.roi_add_line) - - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_R), self) - self.shortcut.activated.connect(self.roi_add_rect) - - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_M), self) - self.shortcut.activated.connect(self.toggle_mouse_tracking) - - self.shortcut = QShortcut(QKeySequence(Qt.Key_F11), self) - self.shortcut.activated.connect(self.toggle_maximized) - - self.shortcut = QShortcut(QKeySequence(Qt.Key_F12), self) - self.shortcut.activated.connect(self.show_window_configuration) - - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_B), self) - self.shortcut.activated.connect(lambda: self._beammark.toggle_handle()) - - self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_P), self) - self.shortcut.activated.connect(self.camera_pause_toggle) - - # adding a menu entry to one of the menus - action = QAction("geometry", self) - action.setToolTip("Update optical center, beam marker size etc.") - action.setStatusTip("Update optical center, beam marker size etc.") - action.triggered.connect(lambda x: cfg.dlg_geometry(self)) - self.menuAdvanced.addAction(action) - - action = QAction("Backlight Reference Positions", self) - action.setToolTip("Update the reference positions for the backlight") - action.setStatusTip("Update the reference positions for the backlight") - action.triggered.connect(cfg.dlg_backlight_positions) - self.menuAdvanced.addAction(action) - - action = QAction("Collimator Reference Positions", self) - action.setToolTip("Update the reference positions for the collimator") - action.setStatusTip("Update the reference positions for the collimator") - action.triggered.connect(cfg.dlg_collimator_reference_positions) - self.menuAdvanced.addAction(action) - - action = QAction("Post sample tube Reference Positions", self) - action.setToolTip("Update the reference positions for the post tube") - action.setStatusTip("Update the reference positions for the post tube") - action.triggered.connect(cfg.dlg_posttube_references) - self.menuAdvanced.addAction(action) - - action = QAction("Delta Tau Parameters", self) - action.setToolTip("Parameters affecting the Delta Tau") - action.setStatusTip("Parameters affecting the Delta Tau") - action.triggered.connect(cfg.dlg_deltatau_parameters) - self.menuAdvanced.addAction(action) - - #action = QAction("Cryojet Reference Positions", self) - #action.setToolTip("Update the reference positions for the cryojet nozzle position") - #action.setStatusTip("Update the reference positions for the cryojet nozzle position") - #action.triggered.connect(self.set_cryojet_positions_dialog) - #self.menuAdvanced.addAction(action) - - #action = QAction("Tell Mount Positions", self) - #action.setToolTip("Mount positions for TELL sample changer") - #action.setStatusTip("Parameters affecting the Delta Tau") - #action.triggered.connect(cfg.dlg_tell_mount_positions) - #self.menuAdvanced.addAction(action) - - def daq_method_prelocated_remove_markers(self): + def _OLD_daq_method_prelocated_remove_markers(self): try: for m in self._marker_rois: m.disconnect_signals() @@ -3024,15 +3129,15 @@ class Main(QMainWindow, Ui_MainWindow): _log.warning("maybe failed removing markers: {}".format(e)) self._marker_rois = [] - def pause_all_markers(self): + def _OLD_pause_all_markers(self): for m in self._marker_rois: m.disconnect_signals() - def resume_all_markers(self): + def _OLD_resume_all_markers(self): for m in self._marker_rois: m.reconnect_signals() - def daq_method_prelocated_update_markers(self): + def _OLD_daq_method_prelocated_update_markers(self): self.daq_method_prelocated_remove_markers() data = self.prelocationModule.get_data() add_xtals = self.prelocationModule._xtals_transformed @@ -3060,58 +3165,40 @@ class Main(QMainWindow, Ui_MainWindow): c.reconnect_signals() c.follow_stage() - def daq_method_prelocated_set_fiducial(self, camx, camy, gx, gy): + def _OLD_daq_method_prelocated_set_fiducial(self, camx, camy, gx, gy): _log.debug(f"camx, camy: {camx}, {camy}, fx, fy: {gx, gy}") self.prelocationModule.set_fiducial_coords(camx, camy, gx, gy) - def daq_method_prelocated_append_data(self, x, y, gx, gy): + def _OLD_daq_method_prelocated_append_data(self, x, y, gx, gy): _log.debug("appending to model: {} {}".format((x, y), (gx, gy))) self.prelocationModule.append_data((x, y, gx, gy)) self.daq_method_prelocated_update_markers() - def daq_method_prelocated_update_model(self, roi): + def _OLD_daq_method_prelocated_update_model(self, roi): row = roi.get_model_row() pos = roi.pos() self.prelocationModule.set_data_camera(row, pos) _log.debug("updating row {} => {}".format(row, pos)) - def daq_method_prelocated_add_reference(self): + def _OLD_daq_method_prelocated_add_reference(self): self._references.append(pg.CircleROI()) - def build_daq_methods_prelocated_tab(self): - tab = self._tab_daqmethod_prelocated - self.prelocationModule = PrelocatedCoordinatesModel.PrelocatedCoordinates(parent=self) - tab.layout().addWidget(self.prelocationModule) - self.prelocationModule.prefixSelected.connect(lambda prefix: self._le_prefix.setText(prefix)) - self.prelocationModule.dataFileLoaded.connect(self.daq_method_prelocated_update_markers) - self.prelocationModule.prelocatedDataUpdated.connect(self.daq_method_prelocated_update_markers) - self.prelocationModule.markersDeleted.connect(self.daq_method_prelocated_remove_markers) - self.fiducialPositionSelected.connect(self.daq_method_prelocated_set_fiducial) - self.appendPrelocatedPosition.connect(self.daq_method_prelocated_append_data) - self.prelocationModule.moveFastStageRequest.connect(self.move_fast_stage) - self._preloc_inspect_area = QPlainTextEdit() - tab.layout().addWidget(self._preloc_inspect_area) - - def move_fast_stage(self, x, y): + def _OLD_move_fast_stage(self, x, y): _log.info(f"received request to move gonio to x, y = {x:.3f}, {y:.3f} mm") fx_motor, fy_motor, bx_motor, bz_motor, omega_motor = self.get_gonio_tweakers() fx_motor.move_motor_to_position(x) fy_motor.move_motor_to_position(y) - def toggle_maximized(self): + def _OLD_toggle_maximized(self): if self.isMaximized(): self.showNormal() else: self.showMaximized() - def show_window_configuration(self): + def _OLD_show_window_configuration(self): _log.debug("maximized? {}".format(self.isMaximized())) - def home_deltatau_faststages(self): - _log.warning("homing fast stages") - epics.PV("SAR-EXPMX1:ASYN.AOUT").put(b"enable plc 1") - - def update_user_and_storage(self): + def _OLD_update_user_and_storage(self): global folders pgroup = settings.value(EXPERIMENT_PGROUP, "not_set_yet") diag = GenericDialog( title="P-group for experiment", message="Enter the p-group to be used", @@ -3157,78 +3244,19 @@ class Main(QMainWindow, Ui_MainWindow): self._label_pgroup.setText(settings.value(EXPERIMENT_PGROUP)) - def init_settings(self): - app = QApplication.instance() - cfg = app._cfg - keys = cfg.allKeys() - - #if EXPERIMENT_PGROUP not in keys: - # self.update_user_and_storage() - - if cfg.WINDOW_GEOMETRY in keys: - self.restoreGeometry(cfg.value(cfg.WINDOW_GEOMETRY, "")) - self.restoreState(cfg.value(cfg.WINDOW_STATE, "")) - - if cfg.WINDOW_SPLITTER in keys: - sz = [int(s) for s in cfg.value(cfg.WINDOW_SPLITTER)] - else: - sz=(500, 1200) - self._main_splitter.setSizes(sz) - - #if AppCfg.BEAM_MARKER_POSITIONS in keys: - # self._beam_markers = s.value(AppCfg.BEAM_MARKER_POSITIONS) - # self.update_beam_marker_fitters() - # _log.info("read beam markers {}".format(self._beam_markers)) - - #if AppCfg.CAMERA_TRANSFORMATIONS in keys: - # app._camera.set_transformations(s.value(AppCfg.CAMERA_TRANSFORMATIONS)) - - #if AppCfg.CAMERA_ZOOM_TO_PPM in keys: - # self._zoom_to_ppm = s.value(AppCfg.CAMERA_ZOOM_TO_PPM) - # _log.info(f"{AppCfg.CAMERA_ZOOM_TO_PPM} updated: {self._zoom_to_ppm}") - # self.update_ppm_fitters() - - def really_quit(self): - """called when user Ctrl-Q the app""" - if QMessageBox.question(self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes: - self._do_quit = True - self.close() - - def closeEvent(self, event): - """this is called when the user clicks the window's cross icon""" - if (self._do_quit or QMessageBox.question( self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes): - app=QApplication.instance() - cfg=app._cfg - try: - pv=app._camera._pv['pic'] - pv.clear_auto_monitor() # disconnect PV monitor callback -> program exit faster. - except AttributeError: - _log.warning('disconnect PV callback failed.') - - _log.info('disconnect PV callback') - cfg.setValue(cfg.WINDOW_GEOMETRY, self.saveGeometry()) - cfg.setValue(cfg.WINDOW_STATE, self.saveState()) - cfg.setValue(cfg.WINDOW_SPLITTER, self._main_splitter.sizes()) - cfg.setValue('last_active', time.time()) - _log.info('save settings') - #QMainWindow.closeEvent(self, event) - _log.info('closeEvent done') - else: - event.ignore() - - def is_recently_active(self): + def _OLD_is_recently_active(self): last_active = settings.value("last_active", 0, type=float) minutes_since_last = int((time.time() - last_active) / 60.0) return minutes_since_last < 60 - def openPreferencesDialog(self): + def _OLD_openPreferencesDialog(self): PreferencesDialog(self).exec_() - def set_app_icon(self): + def _OLD_set_app_icon(self): scriptDir = os.path.dirname(os.path.realpath(__file__)) self.setWindowIcon(QtGui.QIcon(os.path.join(scriptDir + os.path.sep + "logo.png"))) - def set_widget_background_color(self, color): + def _OLD_set_widget_background_color(self, color): """change a widget's color :param color: :return: @@ -3241,127 +3269,94 @@ class Main(QMainWindow, Ui_MainWindow): p.setColor(self.backgroundRole(), color) self.setPalette(p) - def load_stylesheet(self): - with open("swissmx.css", "r") as sheet: - self.setStyleSheet(sheet.read()) - -def sigint_handler(*args): - """Handler for the SIGINT signal.""" - app=QApplication.instance() - app.quit() - - -class StartupSplash: - - def __init__(self): - splash_pix = QPixmap("artwork/logo/256x256.png") - self._wnd=splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) - splash.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) - splash.setEnabled(False) - - self._prgsBar=prgs=QProgressBar(splash) - prgs.setMaximum(100) - prgs.setGeometry(0, splash_pix.height() - 50, splash_pix.width(), 20) - - splash.show() - - def set(self,i,msg): - self._prgsBar.setValue(i) - self._wnd.showMessage(f"{msg}", int(Qt.AlignBottom|Qt.AlignCenter), Qt.black) - app=QApplication.instance() - app.processEvents() - time.sleep(.1) - -def main(): - from PyQt5.QtCore import QT_VERSION_STR - _log.info(f'Version: pyqtgraph:{pg.__version__} matplotlib:{mpl.__version__} numpy:{np.__version__} epics:{epics.__version__} qt:{QT_VERSION_STR}' ) - import argparse, socket - hostname=socket.gethostname() - if hostname=='ganymede': - #use EPICS locally - #os.environ['EPICS_CA_ADDR_LIST']='localhost' - #use EPICS if connected to ESC network - os.environ['EPICS_CA_ADDR_LIST'] ='129.129.244.255 sf-saresc-cagw.psi.ch:5062 sf-saresc-cagw.psi.ch:5066' +if __name__=="__main__": + def main(): + from PyQt5.QtCore import QT_VERSION_STR + _log.info(f'Version: pyqtgraph:{pg.__version__} matplotlib:{mpl.__version__} numpy:{np.__version__} epics:{epics.__version__} qt:{QT_VERSION_STR}' ) + import argparse, socket + hostname=socket.gethostname() + if hostname=='ganymede': + #use EPICS locally + #os.environ['EPICS_CA_ADDR_LIST']='localhost' + #use EPICS if connected to ESC network + os.environ['EPICS_CA_ADDR_LIST'] ='129.129.244.255 sf-saresc-cagw.psi.ch:5062 sf-saresc-cagw.psi.ch:5066' - #(h, t)=os.path.split(sys.argv[0]);cmd='\n '+(t if len(h)>20 else sys.argv[0])+' ' - #exampleCmd=('', '-m0xf -v0') - epilog=__doc__ #+'\nExamples:'+''.join(map(lambda s:cmd+s, exampleCmd))+'\n' - parser=argparse.ArgumentParser(epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument("--sim", "-s", type=lambda x: int(x,0), help="simulate devices (see bitmasks) default=0x%(default)x", default=0) - args = parser.parse_args() - _log.info('Arguments:{}'.format(args.__dict__)) + #(h, t)=os.path.split(sys.argv[0]);cmd='\n '+(t if len(h)>20 else sys.argv[0])+' ' + #exampleCmd=('', '-m0xf -v0') + epilog=__doc__ #+'\nExamples:'+''.join(map(lambda s:cmd+s, exampleCmd))+'\n' + parser=argparse.ArgumentParser(epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument("--sim", "-s", type=lambda x: int(x,0), help="simulate devices (see bitmasks) default=0x%(default)x", default=0) + args = parser.parse_args() + _log.info('Arguments:{}'.format(args.__dict__)) - from PyQt5.QtWidgets import QApplication + from PyQt5.QtWidgets import QApplication - # set app icon + # set app icon - app = QApplication(sys.argv) - app_icon = QtGui.QIcon() - app_icon.addFile("artwork/logo/16x16.png", QtCore.QSize(16, 16)) - app_icon.addFile("artwork/logo/24x24.png", QtCore.QSize(24, 24)) - app_icon.addFile("artwork/logo/32x32.png", QtCore.QSize(32, 32)) - app_icon.addFile("artwork/logo/48x48.png", QtCore.QSize(48, 48)) - app_icon.addFile("artwork/logo/256x256.png", QtCore.QSize(256, 256)) - app.setWindowIcon(app_icon) + app = QApplication(sys.argv) + app_icon = QtGui.QIcon() + app_icon.addFile("artwork/logo/16x16.png", QtCore.QSize(16, 16)) + app_icon.addFile("artwork/logo/24x24.png", QtCore.QSize(24, 24)) + app_icon.addFile("artwork/logo/32x32.png", QtCore.QSize(32, 32)) + app_icon.addFile("artwork/logo/48x48.png", QtCore.QSize(48, 48)) + app_icon.addFile("artwork/logo/256x256.png", QtCore.QSize(256, 256)) + app.setWindowIcon(app_icon) - startupWin=StartupSplash() + startupWin=StartupSplash() - #for i in range(1, 20): - # startupWin.set(i,f'sample startup text {i}') - # #app.processEvents() - # t = time.time() - # #while time.time() < t + 0.1: - # # app.processEvents() + #for i in range(1, 20): + # startupWin.set(i,f'sample startup text {i}') + # #app.processEvents() + # t = time.time() + # #while time.time() < t + 0.1: + # # app.processEvents() - #app._settings=QSettings("PSI", "SwissMX") + #app._settings=QSettings("PSI", "SwissMX") - app._args=args + app._args=args - startupWin.set(5, f'load settings') - app._cfg=cfg=AppCfg() + startupWin.set(5, f'load settings') + app._cfg=cfg=AppCfg() - app._geometry=geometry.geometry() - app._geometry._lut_pix2pos=cfg.value(cfg.GEO_PIX2POS) - app._geometry._opt_ctr=cfg.value(cfg.GEO_OPT_CTR) + app._geometry=geometry.geometry() + app._geometry._lut_pix2pos=cfg.value(cfg.GEO_PIX2POS) + app._geometry._opt_ctr=cfg.value(cfg.GEO_OPT_CTR) - startupWin.set(15, f'connect backlight') - if args.sim&0x01: - app._backlight = backlight.Backlight(None) - else: - app._backlight = backlight.Backlight() - startupWin.set(20, f'connect illumination') - if args.sim&0x02: - app._illumination = illumination.IlluminationControl(None) - else: - app._illumination = illumination.IlluminationControl() - startupWin.set(40, f'connect zoom') - if args.sim&0x04: - app._zoom = zoom.QopticZoom(None) - else: - app._zoom = zoom.QopticZoom() - startupWin.set(60, f'connect camera') - if args.sim&0x08: - app._camera = camera.epics_cam(None) - app._camera.sim_gen(mode=1) - else: - app._camera = camera.epics_cam() - #app._camera.run() is called in center_piece_update + startupWin.set(15, f'connect backlight') + if args.sim&0x01: + app._backlight = backlight.Backlight(None) + else: + app._backlight = backlight.Backlight() + startupWin.set(20, f'connect illumination') + if args.sim&0x02: + app._illumination = illumination.IlluminationControl(None) + else: + app._illumination = illumination.IlluminationControl() + startupWin.set(40, f'connect zoom') + if args.sim&0x04: + app._zoom = zoom.QopticZoom(None) + else: + app._zoom = zoom.QopticZoom() + startupWin.set(60, f'connect camera') + if args.sim&0x08: + app._camera = camera.epics_cam(None) + app._camera.sim_gen(mode=1) + else: + app._camera = camera.epics_cam() + #app._camera.run() is called in center_piece_update - startupWin.set(60, f'start main window') + startupWin.set(60, f'start main window') - main = Main() - main.show() - startupWin._wnd.finish(main) + main = SwissMxWnd() + main.show() + startupWin._wnd.finish(main) - # needed so pycharm can restart application - signal.signal(signal.SIGINT, sigint_handler) + # needed so pycharm can restart application + signal.signal(signal.SIGINT, sigint_handler) - #main.update_user_and_storage() #ZAC: orig. code - sys.exit(app.exec_()) - - -if __name__ == "__main__": + #main.update_user_and_storage() #ZAC: orig. code + sys.exit(app.exec_()) main() diff --git a/swissmx.ui b/swissmx.ui index 6d2841a..0bd26df 100644 --- a/swissmx.ui +++ b/swissmx.ui @@ -510,7 +510,7 @@ - + prelocated