This commit is contained in:
2022-09-09 15:54:18 +02:00
parent f70421d2f3
commit 189c98951a
7 changed files with 206 additions and 1548 deletions

View File

@@ -45,20 +45,10 @@ ts=timestamp()
ts.log('Import part 1/8:')
import sys, os, time
import json, re
import random, signal,threading
import random, signal, subprocess
import matplotlib as mpl
mpl.use('Qt5Agg') # needed to avoid blocking of ui !
#import Wigis #ZAC: orig. code
#import jungfrau_widget #ZAC: orig. code
#import bernina_pulse_picker #ZAC: orig. code
#import storage #ZAC: orig. code
#from zmq_escape import zescape #ZAC: orig. code
#from helicalscan import HelicalScanGui #ZAC: orig. code
# publisher = pubber.Publisher()
TASK_JUNGFRAU_SETTINGS = "jungfrau_settings"
TASK_SETUP_GEOMETRY_CALIB = "geometry_calib"
TASK_SETUP_PPM_CALIBRATION_TBOX = "ppm_calibration_tbox"
@@ -78,17 +68,12 @@ import ModuleFixTarget
import PrelocatedCoordinatesModel # ZAC: orig. code
from EmblModule import EmblWidget #ZAC: orig. code
from HelicalTable import HelicalTableWidget #ZAC: orig. code
#from Wigis import Spinner, Checkbox #ZAC: orig. code
#from exceptions import * #ZAC: orig. code
#import qoptic #ZAC: orig. code
#import mx_swissfel #ZAC: orig. code
#swissfel = mx_swissfel.SwissFELMachine() #ZAC: orig. code
#from bernina_pulse_picker import pulsePicker #ZAC: orig. code
ts.log('Import part 3/8:')
import qtawesome
import qutilities
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import Qt, pyqtSlot, QSize, QRegExp, pyqtSignal, QObject, QThread, QRectF
from PyQt5.QtCore import Qt, pyqtSlot, QSize, QRegExp, pyqtSignal, QObject, QThread, QRectF,QT_VERSION_STR
from PyQt5.QtGui import QKeySequence, QPixmap, QRegExpValidator, QFont
from PyQt5.QtWidgets import (
QAction, QApplication, QDoubleSpinBox, QFileDialog, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit,
@@ -96,20 +81,11 @@ from PyQt5.QtWidgets import (
QSplashScreen, QTextBrowser, QToolBox, QVBoxLayout, QWidget,)
from PyQt5.uic import loadUiType
ts.log('Import part 4/8:')
import CustomROI as CstROI
import pyqtUsrObj as UsrGO
#from CustomROI import BeamMark, Grid, CrystalCircle #ZAC: orig. code
#from GenericDialog import GenericDialog #ZAC: orig. code
#from dialogs.PreferencesDialog import PreferencesDialog #ZAC: orig. code
#from epics_widgets import zoom #ZAC: orig. code
from epics_widgets.MotorTweak import MotorTweak
from epics_widgets.SmaractMotorTweak import SmaractMotorTweak
from epics_widgets.SimMotorTweak import SimMotorTweak
ts.log('Import part 5/8:')
#import matplotlib as mpl
#import matplotlib.pyplot as plt
import numpy as np
np.set_printoptions(suppress=True,linewidth=196)
import pyqtgraph as pg
@@ -128,47 +104,24 @@ import deltatau
import detector
ts.log('Import part 8/8:')
#_URL = "http://PC12288:8080"
# import TellClient
# tell = TellClient.TellClient(_URL)
#import eventer #ZAC: orig. code
#from detector_control import jungfrau_detector #ZAC: orig. code
#from findxtal import findObj #ZAC: orig. code
#if simulated: #ZAC: orig. code #ZAC: orig. code
# _log.warning("simulation mode enabled")
# qoptic_zoom = qoptic.FeturaClientBogus()
#else:
# qoptic_zoom = qoptic.FeturaClient()
#from epics_widgets import MotorTweak
#user = getpass.getuser() #ZAC: orig. code
#home = os.path.expanduser("~")
#just_quit = user in ["e10003", "gac-esbmx"]
#folders = storage.Folders() #ZAC: orig. code
#from deltatau import DeltaTau, shapepath, helical, DebugPlot #ZAC: orig. code
#delta_tau = DeltaTau() #ZAC: orig. code
#BROKER_SERVER = "127.0.0.1" #ZAC: orig. code
#BROKER_PORT = 61613 #ZAC: orig. code
# sample_camera = camera.camera_server(basename="SARES20-PROF142-M1")
#_log.info(f"connecting to microscope to camera server: {appsconf['microscope']['sample_camera']['pv_prefix']} ")
#sample_camera = camera.camera_server(basename=appsconf["microscope"]["sample_camera"]["pv_prefix"]) #ZAC: orig. code
def tdstamp():
return time.strftime("%Y%m%dH%H%M%S")
def datestamp():
return time.strftime("%Y%m%d")
def get_version(path='.'):
#sys.stdout.write('getVersion() -> using git command -> ')
p = subprocess.Popen(f'git -C {path} describe --match ''*.*.*'' --long --tags --dirty', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
retval = p.wait()
res=p.stdout.readline()
p.stdout.close()
#res=res.decode()[1:-1].split('-',2)
res=res.decode()[:-1].split('-',2)
ver='.'.join(res[:2])
gitcmt=res[2][1:]
return (ver,gitcmt)
def sigint_handler(*args):
"""Handler for the SIGINT signal."""
app=QApplication.instance()
@@ -177,7 +130,6 @@ def sigint_handler(*args):
class AcquisitionAbortedException(Exception):
pass
class Sequencer(QObject):
finished = pyqtSignal()
timeoutExpired = pyqtSignal()
@@ -260,13 +212,6 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
QtGui.QFontDatabase.addApplicationFont("fonts/Inconsolata-Bold.ttf")
QtGui.QFontDatabase.addApplicationFont("fonts/Baloo-Regular.ttf")
# TODO: Cleanup many member functions that are unused or obsolete
self._pv_shutter = None # epics.PV('X06SA-ES-MD2:SHUTTER')
self._has_pulse_picker = False
self._at_x06sa = False
self._at_cristalina = True
self._at_lab_eh060 = False
self.init_settings()
# self.create_escape_toolbar()
@@ -333,13 +278,13 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
self.init_actions()
#self.prepare_microscope_page()
self.prepare_left_tabs()
self.prepare_wd_tabs_left()
#self.update_beam_marker(qoptic_zoom.get_sp()) #ZAC: orig. code
self._centerpiece_stack.setCurrentIndex(0)
self._centerpiece_stack.currentChanged.connect(self.cb_update_center_widget)
self._OLD_init_validators()
self._wd_stack.setCurrentIndex(0)
self._wd_stack.currentChanged.connect(self.cb_update_center_widget)
#self._OLD_init_validators()
#self.init_settings_tracker() ? not needed, was for TELL ?
self._OLD_wire_storage()
#self._OLD_wire_storage()
self.cb_update_center_widget(0) # start camera updater
curzoom = app._zoom.get_val()
@@ -364,7 +309,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
sz = [int(s) for s in cfg.value(cfg.WINDOW_SPLITTER)]
else:
sz=(500, 1200)
self._main_splitter.setSizes(sz)
self._wd_splitter.setSizes(sz)
#if AppCfg.BEAM_MARKER_POSITIONS in keys:
# self._beam_markers = s.value(AppCfg.BEAM_MARKER_POSITIONS)
@@ -523,11 +468,11 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
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)
#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)
@@ -575,9 +520,9 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
self.toolBar.widgetForAction(action).setAccessibleName("action_DataCollection")
self.actionQuit.triggered.connect(self.cb_really_quit)
self.actionPreferences.triggered.connect(self._OLD_openPreferencesDialog)
self.actionPreferences.triggered.connect(self.cb_modify_app_param)
self.actionHome_Fast_Stages.triggered.connect(self.cb_deltatau_home_faststages)
self.actionUser_Storage.triggered.connect(self._OLD_update_user_and_storage)
self.actionAbout.triggered.connect(self.cb_about)
self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_L), self)
self.shortcut.activated.connect(self._OLD_roi_add_line)
@@ -601,6 +546,12 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
self.shortcut.activated.connect(self._OLD_camera_pause_toggle)
# adding a menu entry to one of the menus
#action = QAction("parameters", self)
#action.setToolTip("modify application parameters")
#action.setStatusTip("modify application parameters")
#action.triggered.connect(self.cb_modify_app_param)
#self.menuAdvanced.addAction(action)
#action = QAction("geometry", self)
#action.setToolTip("Update optical center, beam marker size etc.")
#action.setStatusTip("Update optical center, beam marker size etc.")
@@ -631,14 +582,6 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
#action.triggered.connect(cfg.dlg_deltatau_parameters)
#self.menuAdvanced.addAction(action)
action = QAction("parameters", self)
action.setToolTip("modify application parameters")
action.setStatusTip("modify application parameters")
action.triggered.connect(self.cb_modify_app_param)
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")
@@ -665,7 +608,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
_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(cfg.WINDOW_SPLITTER, self._wd_splitter.sizes())
cfg.setValue('last_active', time.time())
_log.info('save settings')
#QMainWindow.closeEvent(self, event)
@@ -755,19 +698,13 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
self.setStyleSheet(sheet.read())
def setup_sliders(self):
cont = self._rightmost
cont = self._wd_right
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()
@@ -1506,46 +1443,44 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
def cb_esc_sample_exchange(self):
app=QApplication.instance()
self._esc_state ="busy"
steps = []
#if option(CRYOJET_MOTION_ENABLED):
# steps.append(lambda: self.move_cryojet_nozzle("out"))
steps.extend(
[
steps=[
lambda:self.move_detector("out"),
lambda: self.move_post_tube("out"),
lambda: app._backlight.move("out", wait=True),
lambda: app._backlight.move("out"),
lambda: self.move_collimator("out"),
]
)
self.esc_run_steps(steps, "Transitioning to Sample Exchange")
self._esc_state ="ManualSampleExchange"
self.esc_run_steps(steps, "Transitioning to Sample Exchange","ManualSampleExchange")
def cb_esc_sample_alignment(self):
app=QApplication.instance()
self._esc_state ="busy"
steps = [
# lambda: sample_selection.tell.set_current(30.0),
lambda: self.move_collimator("ready")
lambda: self.move_collimator("ready"),
lambda:self.move_detector("out"),
lambda:self.move_post_tube("out"),
lambda:app._backlight.move("in"),
lambda:self.move_collimator("out"),
]
#if option(CRYOJET_MOTION_ENABLED):
# steps.extend([lambda: self.move_cryojet_nozzle("in")])
steps.extend([lambda: self.move_post_tube("out"), lambda: app._backlight.move("in")])
self.esc_run_steps(steps, "Transitioning to Sample Alignment")
self._esc_state ="SampleAlignment"
#steps.extend([lambda: self.move_post_tube("out"), lambda: app._backlight.move("in")])
self.esc_run_steps(steps, "Transitioning to Sample Alignment","SampleAlignment")
def cb_esc_data_collection(self):
app=QApplication.instance()
self._esc_state ="busy"
steps = [
# lambda: sample_selection.tell.set_current(30.0),
lambda: app._backlight.move("out"),
lambda: self.move_post_tube("in"),
lambda: self.move_collimator("in"),
lambda:self.move_detector("in"),
]
#if option(CRYOJET_MOTION_ENABLED):
# steps.extend([lambda: self.move_cryojet_nozzle("in")])
self.esc_run_steps(steps, "Transitioning to Data Collection")
self._esc_state ="DataCollection"
self.esc_run_steps(steps, "Transitioning to Data Collection","DataCollection")
def cb_really_quit(self):
"""called when user Ctrl-Q the app"""
@@ -1555,9 +1490,43 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
def cb_deltatau_home_faststages(self):
pfx=QApplication.instance()._cfg.value(AppCfg.GBL_DEV_PREFIX)[0]
_log.warning("homing fast stages")
_log.info("homing fast stages")
epics.PV(f"{pfx}1:ASYN.AOUT").put(b"enable plc 1")
def cb_about(self):
try:
ver,gitcmt=get_version()
v_SMX=f'{ver} git:{gitcmt}'
except:
v_SMX='git version failed'
try:
ver,gitcmt=get_version('..')
v_SMXT=f'{ver} git:{gitcmt}'
except:
v_SMXT='git version failed'
txt=f'''About Swissmx:
SwissMX: {v_SMX}
SwissMXTools: {v_SMXT}
qt:{QT_VERSION_STR}
pyqtgraph:{pg.__version__}
numpy:{np.__version__}
matplotlib:{mpl.__version__}
epics:{epics.__version__}
Copyright (c) 2022 by Paul Scherrer Institute
(http://www.psi.ch)
Based on Zac great first implementation
Author Thierry Zamofing (thierry.zamofing@psi.ch)
'''
QMessageBox.about(self, "SwissMX", txt)
pass
def cb_testcode(self):
try:
tc=self._testCode
@@ -1602,8 +1571,8 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
#print(vb.childGroup.childItems())
pass
def prepare_left_tabs(self):
tabs = self._left_tabs
def prepare_wd_tabs_left(self):
tabs = self._wd_tabs_left
tabs.currentChanged.connect(self.cb_switch_task)
setup_tab = self._tab_setup
@@ -1832,8 +1801,8 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
def cb_switch_task(self, index=0):
stack = self._centerpiece_stack
task = self._left_tabs.currentWidget().accessibleName()
stack = self._wd_stack
task = self._wd_tabs_left.currentWidget().accessibleName()
setup_task = self._setup_toolbox.currentWidget().accessibleName()
method = self._tabs_daq_methods.currentWidget().accessibleName()
@@ -1992,7 +1961,6 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
dt_misc = cfg.value(AppCfg.DT_MISC)
geo = app._geometry
verbose=0xff
fn='/tmp/shapepath'
try:
dt=app._deltatau
@@ -2006,12 +1974,9 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
sp=dt._shapepath
sp.verbose=dt_misc['verbose']
sp.points=kwargs['points']
#sp.gen_grid_points(w=15, h=15, pitch=3, rnd=0, ofs=(0, +2000))
#sp.gen_grid_points(w=5, h=10, pitch=1, rnd=0, ofs=(0, 0));sp.sort_points(False, 10);sp.points
#sp.sort_points(False, 15);
sp.meta['pt2pt_time']=dt_misc['pt2pt_time']
sp.setup_gather()
sp.setup_sync(verbose=verbose&32, timeOfs=0.05)
sp.setup_sync(verbose=sp.verbose&0x20, timeOfs=0.05)
try:
p=geo._fitPlane
sp.setup_coord_trf(cz=f'{p[0]:+.18g}X{p[1]:+.18g}Y{p[2]:+.18g}') # reset to shape path system
@@ -2037,7 +2002,8 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
plt.show(block=False)
#plt.show(block=True)
def esc_run_steps(self, steps, title):
def esc_run_steps(self, steps, title, esc_state):
self._esc_state ="busy"
with pg.ProgressDialog(title, 0, len(steps)) as dlg:
for step in steps:
step()
@@ -2045,8 +2011,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
if dlg.wasCanceled():
QMessageBox.warning(self, "escape steps", "ABORTED" + title)
break
#backlight="{'pos_in': -10.0, 'pos_out': 0.0}"
self._esc_state = esc_state
def move_post_tube(self, pos):
# post_sample_tube="{'x_up': -0.2, 'y_up': 0.0, 'x_down': 0.0, 'y_down': 0.0, 'x_out_delta': 0.0, 'y_out_delta': 0.0, 'z_in': 0.0, 'z_out': 0.0}"
@@ -3554,7 +3519,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
self.re_connect_collect_button()
def _OLD_create_escape_toolbar(self):
cont = self._rightmost
cont = self._wd_right
w = QGroupBox("Escape")
layout = QHBoxLayout()
w.setLayout(layout)
@@ -3725,7 +3690,6 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
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}' )
_log.info(f'Version: pyqtgraph:{pg.__version__} epics:{epics.__version__} qt:{QT_VERSION_STR}' )
import argparse, socket