diff --git a/ModuleFixTarget.py b/ModuleFixTarget.py index 1867dd5..45869e7 100644 --- a/ModuleFixTarget.py +++ b/ModuleFixTarget.py @@ -812,7 +812,7 @@ if __name__ == "__main__": } elif t==3: data=[ - UsrGO.Grid(pos=(120.0, -100.0), size=(1000.0, 500.0), cnt=(10, 5), ficucialScale=2), + UsrGO.Grid(pos=(120.0, -100.0), size=(1000.0, 500.0), cnt=(10, 5), fiducialSize=2), Monster(name='Cave lizard', hp=[3,6], ac=16, attacks=['BITE','HURT']) ] mainWin.wndFixTrg._data=data diff --git a/app_config.py b/app_config.py index 9b3a7b2..e57abe7 100644 --- a/app_config.py +++ b/app_config.py @@ -9,7 +9,7 @@ import logging _log = logging.getLogger(__name__) from PyQt5.QtCore import QSettings -from PyQt5.QtWidgets import QApplication, QLineEdit, QWidget, QGridLayout, QLabel +from PyQt5.QtWidgets import QApplication, QMainWindow #QLineEdit, QWidget, QGridLayout, QLabel import json import pyqtgraph as pg import numpy as np @@ -52,23 +52,6 @@ class AppCfg(QSettings): DFT_POS_COL ="default_position/collimator" #json DFT_POS_BKLGT ="default_position/backlight" #json - PST_X_UP ="post_sample_tube/x_up" - PST_Y_UP ="post_sample_tube/y_up" - PST_X_DOWN="post_sample_tube/x_down" - PST_Y_DOWN="post_sample_tube/y_down" - PST_DX ="post_sample_tube/dx" - PST_DY ="post_sample_tube/dy" - PST_TZ_IN ="post_sample_tube/z_in" - PST_TZ_OUT="post_sample_tube/z_out" - - COL_DX ="collimator/dx" - COL_DY ="collimator/dy" - COL_X_IN ="collimator/x_in" - COL_Y_IN ="collimator/y_in" - - BKLGT_IN ="backlight/in" - BKLGT_OUT ="backlight/out" - DT_HOST="deltatau/host" DT_SHOW_PLOTS="deltatau/show_plots" DT_VEL_SCL="deltatau/velocity_scale" @@ -174,7 +157,7 @@ class AppCfg(QSettings): t=type(val) if key in (AppCfg.GEO_PIX2POS,): val=json.dumps(val, cls=MyJsonEncoder) - elif key in (AppCfg.GEO_CAM_PARAM,): + elif key in (AppCfg.GEO_CAM_PARAM,AppCfg.DFT_POS_DET,AppCfg.DFT_POS_PST,AppCfg.DFT_POS_COL,AppCfg.DFT_POS_BKLGT,): val=json.dumps(val, cls=MyJsonEncoder) val=val.replace('"',"'") elif key in (AppCfg.GEO_OPT_CTR,AppCfg.GEO_BEAM_SZ,AppCfg.GEO_BEAM_POS,): @@ -189,9 +172,10 @@ class AppCfg(QSettings): if key in (AppCfg.GEO_PIX2POS,): val=json.loads(val)#, object_hook=MyJsonDecoder) val=(np.array(val[0]),np.array(val[1])) - if key in (AppCfg.GEO_CAM_PARAM,): - val=val.replace("'",'"') - val=json.loads(val) # , object_hook=MyJsonDecoder) + elif key in (AppCfg.GEO_CAM_PARAM,AppCfg.DFT_POS_DET,AppCfg.DFT_POS_PST,AppCfg.DFT_POS_COL,AppCfg.DFT_POS_BKLGT,): + if val is not None: + val=val.replace("'",'"') + val=json.loads(val) # , object_hook=MyJsonDecoder) elif key in (AppCfg.GEO_BEAM_SZ,AppCfg.GEO_BEAM_POS,): val=np.array(tuple(map(float, val)))/1000 elif key in (AppCfg.GEO_OPT_CTR): @@ -213,6 +197,181 @@ class AppCfg(QSettings): self.setValue(key, not v) self.sync() +from pyqtgraph.parametertree import Parameter, ParameterTree +class WndParameter(QMainWindow): + def __init__(self, parent=None): + super(WndParameter, self).__init__(parent) + app=QApplication.instance() + cfg=app._cfg + #GBL_FLD_SCR_SHOT="global/folder_screenshot" + #GBL_DEV_PREFIX="global/device_prefix" # SAR-EXPMX + #GEO_OPT_CTR + #GEO_PIX2POS + #GEO_BEAM_POS + #GEO_CAM_PARAM + geo_beam_sz = cfg.value(AppCfg.GEO_BEAM_SZ)*1000 + dft_pos_pst = cfg.value(AppCfg.DFT_POS_PST) + dft_pos_col = cfg.value(AppCfg.DFT_POS_COL) + dft_pos_bklgt = cfg.value(AppCfg.DFT_POS_BKLGT) + dft_pos_det = cfg.value(AppCfg.DFT_POS_DET) + geo_cam_param = cfg.value(AppCfg.GEO_CAM_PARAM) + gbl_dev_prefix = cfg.value(AppCfg.GBL_DEV_PREFIX) + dt_host = cfg.value(AppCfg.DT_HOST) + dt_show_plots = cfg.value(AppCfg.DT_SHOW_PLOTS) + dt_vel_scl = cfg.value(AppCfg.DT_VEL_SCL) + + + + if dft_pos_pst is None:dft_pos_pst={} + if dft_pos_col is None:dft_pos_col={} + if dft_pos_bklgt is None:dft_pos_bklgt={} + if dft_pos_det is None:dft_pos_det={} + + params=[ + {'name':'geometry','type':'group', 'children':[ + {'name': AppCfg.GEO_BEAM_SZ, 'title':'size of the beam', 'type':'group', 'children':[ + {'name':'width', 'type':'float', 'value':geo_beam_sz[0], 'step':0.1,'suffix':' um'}, + {'name':'height', 'type':'float', 'value':geo_beam_sz[1], 'step':0.1,'suffix':' um'}, + #{'name':'TEST', 'type':'float', 'value':10.5, 'step':0.001, 'decimals':5}, + ]}, + ]}, + {'name': AppCfg.DFT_POS_PST, 'title':'post sample tube reference positions', 'type':'group', 'children':[ + {'name':'Up X' ,'value':dft_pos_pst.get('x_up' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'Up Y' ,'value':dft_pos_pst.get('y_up' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'Down X' ,'value':dft_pos_pst.get('x_down' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'Down Y' ,'value':dft_pos_pst.get('y_down' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'out delta X' ,'value':dft_pos_pst.get('x_out_delta',0),'type':'float','limits':(-32,32),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'out delta Y' ,'value':dft_pos_pst.get('y_out_delta',0),'type':'float','limits':(-32,32),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'tube Z in position' ,'value':dft_pos_pst.get('z_in' ,0),'type':'float','limits':(-8 ,1 ),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'tube Z OUT position','value':dft_pos_pst.get('z_out' ,0),'type':'float','limits':(-8 ,1 ),'step':0.1,'decimals':5,'suffix':' mm'}, + ]}, + {'name': AppCfg.DFT_POS_COL, 'title':'collimator reference positions', 'type':'group', 'children':[ + {'name':'in X', 'value':dft_pos_col.get('x_in',0), 'type':'float', 'limits':(-15.9, 15.9 ),'step':0.1, 'decimals':5, 'suffix':' mm'}, + {'name':'in Y', 'value':dft_pos_col.get('y_in',0), 'type':'float', 'limits':(-15.9, 15.9 ),'step':0.1, 'decimals':5, 'suffix':' mm'}, + {'name':'out deltaX', 'value':dft_pos_col.get('x_out_delta',0),'type':'float', 'limits':(-15.9, 15.9 ),'step':0.1, 'decimals':5, 'suffix':' mm'}, + {'name':'out deltaY', 'value':dft_pos_col.get('y_out_delta',0),'type':'float', 'limits':(-15.9, 15.9 ),'step':0.1, 'decimals':5, 'suffix':' mm'}, + ]}, + {'name': AppCfg.DFT_POS_BKLGT, 'title':'Back Light reference positions', 'type':'group', 'children':[ + {'name':'In position', 'value':dft_pos_bklgt.get('pos_in',0), 'type':'float', 'limits':(-30000, 10 ),'step':10, 'decimals':5, 'suffix':'ustep'}, + {'name':'Out position', 'value':dft_pos_bklgt.get('pos_out',0), 'type':'float', 'limits':(-1000, 10 ),'step':10, 'decimals':5, 'suffix':'ustep'}, + ]}, + {'name': AppCfg.DFT_POS_DET, 'title':'detector reference positions', 'type':'group', 'children':[ + {'name':'In position', 'value':dft_pos_det.get('pos_in',0), 'type':'float', 'limits':(-20, 20 ),'step':0.1, 'decimals':5, 'suffix':' mm'}, + {'name':'Out position', 'value':dft_pos_det.get('pos_out',0), 'type':'float', 'limits':(-20, 20 ),'step':0.1, 'decimals':5, 'suffix':' mm'}, + ]}, + {'name': AppCfg.GBL_DEV_PREFIX, 'title':'device prefix', 'type':'group', 'children':[ + {'name':'deltatau motors', 'value':gbl_dev_prefix[0],'type':'str' }, + {'name':'smaract motors', 'value':gbl_dev_prefix[1],'type':'str' }, + ]}, + {'name':AppCfg.GEO_CAM_PARAM, 'title':'camera parameters', 'type':'group', 'children':[ + {'name':'gain', 'value':geo_cam_param.get('gain',0), 'type':'float', 'step':1, }, + {'name':'exposure', 'value':geo_cam_param.get('exposure',0), 'type':'float', 'step':1, }, + {'name':'binning', 'value':geo_cam_param.get('binning','[1,1]'),'type':'str'}, + {'name':'roi', 'value':geo_cam_param.get('roi','[1,2,3,4]'),'type':'str'}, + {'name':'mono8', 'value':geo_cam_param.get('mono8','0'), 'type':'str'}, + ]}, + {'name':'Delta Tau Parameters', 'type':'group', 'children':[ + {'name':AppCfg.DT_HOST ,'title':'host name (host[:port:port_gather])','value':dt_host ,'type':'str'} , + {'name':AppCfg.DT_SHOW_PLOTS,'title':'show plots after collection' ,'value':dt_show_plots,'type':'bool' ,'tip':"This is a checkbox"}, + {'name':AppCfg.DT_VEL_SCL ,'title':'velocity_scale' ,'value':dt_vel_scl ,'type':'float','limits':(0,1),'step':0.1,'tip':"This is a checkbox"}, + ]}, + {'name':'Save/Restore functionality', 'type':'group', 'children':[ + {'name':'Save State', 'type':'action'}, + {'name':'Restore State', 'type':'action', 'children':[ + {'name':'Add missing items', 'type':'bool', 'value':True}, + {'name':'Remove extra items', 'type':'bool', 'value':True}, + ]}, + ]}, + ] + + self._p=p=Parameter.create(name='params', type='group', children=params) + p.sigTreeStateChanged.connect(lambda a,b: self.cb_change(a,b)) + # Too lazy for recursion: + for child in p.children(): + child.sigValueChanging.connect(lambda a,b: self.cb_valueChanging(a,b)) + for ch2 in child.children(): + ch2.sigValueChanging.connect(lambda a,b: self.cb_valueChanging(a,b)) + p.param('Save/Restore functionality', 'Save State').sigActivated.connect(self.cb_save) + p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(self.cb_restore) + + self._paramTree=pt=ParameterTree(parent=self) + pt.setParameters(p, showTop=False) + pt.setWindowTitle('SwissMX parameters') + #t.resize(600, 800) + self.setCentralWidget(pt) + self.move(100, 100) + self.resize(600, 800) + + def cb_change(self,paramAll, changes): + app=QApplication.instance() + cfg=app._cfg + assert(self._p==paramAll) + #param.parent() + for param, change, data in changes: + path=paramAll.childPath(param) + if path is not None: + childName='.'.join(path) + else: + childName=param.name() + _log.debug(f'parameter:{childName} change:{change} data:{str(data)}') + parent=param.parent() + par_nm=parent.name() + nm=param.name() + if par_nm in(AppCfg.DT_HOST,AppCfg.DT_SHOW_PLOTS,AppCfg.DT_VEL_SCL): + cfg.setValue(nm,param.value()) + elif par_nm==AppCfg.GEO_BEAM_SZ: + v = np.array(tuple(map(lambda x: x.value(),parent.children()))) + cfg.setValue(par_nm,v) + try: + bm=self.parent()._goBeamMarker + except AttributeError as e: + _log.warning('can not set beam size to application window') + else: + bm.setSize(v) + + elif par_nm == AppCfg.DFT_POS_PST: + k=tuple(map(lambda x: x.name(),parent.children())) + k=('x_up','y_up','x_down','y_down','x_out_delta','y_out_delta','z_in','z_out',) + v = tuple(map(lambda x: x.value(),parent.children())) + d=dict(zip(k,v)) + cfg.setValue(par_nm,d) + elif par_nm == AppCfg.DFT_POS_COL: + k=tuple(map(lambda x: x.name(),parent.children())) + k=('x_in','y_in','x_out_delta','y_out_delta') + v = tuple(map(lambda x: x.value(),parent.children())) + d=dict(zip(k,v)) + cfg.setValue(par_nm,d) + elif par_nm == AppCfg.DFT_POS_BKLGT: + k=tuple(map(lambda x: x.name(),parent.children())) + k=('pos_in','pos_out') + v = tuple(map(lambda x: x.value(),parent.children())) + d=dict(zip(k,v)) + cfg.setValue(par_nm,d) + elif par_nm == AppCfg.DFT_POS_DET: + k=tuple(map(lambda x: x.name(),parent.children())) + k=('pos_in','pos_out') + v = tuple(map(lambda x: x.value(),parent.children())) + d=dict(zip(k,v)) + cfg.setValue(par_nm,d) + elif par_nm == AppCfg.GBL_DEV_PREFIX: + v = tuple(map(lambda x: x.value(),parent.children())) + cfg.setValue(par_nm,v) + cfg.sync() + + def cb_valueChanging(self,param, value): + _log.debug(f'Value changing (not finalized): {param}, {value}') + + def cb_save(self): + self._state=p.saveState() + + def cb_restore(self): + p=self._p + add=p['Save/Restore functionality', 'Restore State', 'Add missing items'] + rem=p['Save/Restore functionality', 'Restore State', 'Remove extra items'] + p.restoreState(self._state, addChildren=add, removeChildren=rem) + +# ----------------------------- OBSOLETE ----------------------------- + #inst_folder = Path(__file__).absolute().parent #config_file = inst_folder / "swissmx.yaml" #configs = yaml.load(config_file.read_text(),Loader=yaml.FullLoader) @@ -239,296 +398,168 @@ class AppCfg(QSettings): # return str(p) - def dlg_geometry(self,obj): - SPN=GenericDialog.Spinner - app=QApplication.instance() - cfg=app._cfg - w, h = map(float,cfg.value(AppCfg.GEO_BEAM_SZ)) - d = GenericDialog.GenericDialog( - title="geometry", - message="Enter the size of the beam in microns", - inputs={ - "bw": ("beam width um" ,w,SPN(w, min=1, max=200, suffix=" \u00B5m"),), - "bh": ("beam height um",h,SPN(h, min=1, max=200, suffix=" \u00B5m"),), - }, - ) - if d.exec(): - results = d.results - _log.info("Updating beamsize to {}".format(results)) - bm_sz= (results["bw"], results["bh"]) - _log.debug("types {}".format(type(w))) - cfg.setValue(AppCfg.GEO_BEAM_SZ, bm_sz) - cfg.sync() - bm=obj._goBeamMarker - bm.setSize(bm_sz) - #self._beammark.set_beam_size((w, h)) - - def dlg_posttube_references(self): - SPN=GenericDialog.Spinner - app=QApplication.instance() - cfg=app._cfg - x_up = cfg.value(AppCfg.PST_X_UP , 0.0,type=float) - y_up = cfg.value(AppCfg.PST_Y_UP , 0.0,type=float) - x_down = cfg.value(AppCfg.PST_X_DOWN, 0.0,type=float) - y_down = cfg.value(AppCfg.PST_Y_DOWN, 0.0,type=float) - dx = cfg.value(AppCfg.PST_DX , 0.0,type=float) - dy = cfg.value(AppCfg.PST_DY , 0.0,type=float) - tz_in = cfg.value(AppCfg.PST_TZ_IN , 0.0,type=float) - tz_out = cfg.value(AppCfg.PST_TZ_OUT, 0.0,type=float) - - d = GenericDialog.GenericDialog( - title="Post Sample Tube Configuration", - message="Enter the relative displacements for X and Y to move the post sample tube either in or out.", - inputs={ - AppCfg.PST_X_UP : ("Up X" , x_up , SPN(x_up , decimals=3, min=-45.0, max=15.0, suffix=" mm"), ), - AppCfg.PST_Y_UP : ("Up Y" , y_up , SPN(y_up , decimals=3, min=-45.0, max=15.0, suffix=" mm"), ), - AppCfg.PST_X_DOWN: ("Down X" , x_down, SPN(x_down, decimals=3, min=-45.0, max=15.0, suffix=" mm"), ), - AppCfg.PST_Y_DOWN: ("Down Y" , y_down, SPN(y_down, decimals=3, min=-45.0, max=15.0, suffix=" mm"), ), - AppCfg.PST_DX : ("out delta X" , dx , SPN(dx , decimals=3, min=-32.0, max=32.0, suffix=" mm"), ), - AppCfg.PST_DY : ("out delta Y" , dy , SPN(dy , decimals=3, min=-32.0, max=32.0, suffix=" mm"), ), - AppCfg.PST_TZ_IN : ("tube Z in position" , tz_in , SPN(tz_in , decimals=3, min=-8.0 , max=1.0 , suffix=" mm"), ), - AppCfg.PST_TZ_OUT: ("tube Z OUT position", tz_out, SPN(tz_out, decimals=3, min=-8.0 , max=1.0 , suffix=" mm"), ), - }, - ) - if d.exec(): - results = d.results - _log.info("setting post-sample-tube displacements {}".format(results)) - for k, v in results.items(): - cfg.setValue(k, v) - cfg.sync() - - def dlg_collimator_reference_positions(self): - SPN=GenericDialog.Spinner - app=QApplication.instance() - cfg=app._cfg - x_out = cfg.value(AppCfg.COL_DX , 0.0,type=float) - y_out = cfg.value(AppCfg.COL_DY , 0.0,type=float) - x_in = cfg.value(AppCfg.COL_X_IN, 0.0,type=float) - y_in = cfg.value(AppCfg.COL_Y_IN, 0.0,type=float) - d = GenericDialog.GenericDialog( - title="Collimator configuration", - message="Enter reference positions for the collimator", - inputs={ - AppCfg.COL_DX: ("Collimator out deltaX", x_out, SPN(x_out, decimals=3, min=-15.9, max=15.9, suffix=" mm"),), - AppCfg.COL_DY: ("Collimator out deltaY", y_out, SPN(y_out, decimals=3, min=-15.9, max=15.9, suffix=" mm"),), - AppCfg.COL_X_IN: ("Collimator in X", x_in, SPN(x_in, decimals=3, min=-15.9, max=15.9, suffix=" mm"),), - AppCfg.COL_Y_IN: ("Collimator in Y", y_in, SPN(y_in, decimals=3, min=-15.9, max=15.9, suffix=" mm"),), - }, - ) - if d.exec(): - results = d.results - _log.info("setting collimator reference positions {}".format(results)) - for k, v in results.items(): - cfg.setValue(k, v) - cfg.sync() - - def dlg_backlight_positions(self): - SPN=GenericDialog.Spinner - app=QApplication.instance() - cfg=app._cfg - p_in = cfg.value(AppCfg.BKLGT_IN,0,type=int) - p_out = cfg.value(AppCfg.BKLGT_OUT,0,type=int) - d = GenericDialog.GenericDialog( - title="Back Light configuration", - message="Enter reference positions for the backlight", - inputs={ - AppCfg.BKLGT_IN: ("In position" , p_in , SPN(p_in, min=-30000, max=10), ), - AppCfg.BKLGT_OUT: ("Out position", p_out, SPN(p_out, min=-1000, max=10), ), - }, - ) - if d.exec(): - results = d.results - _log.info("setting back light reference positions {}".format(results)) - for k, v in results.items(): - cfg.setValue(k, v) - cfg.sync() - - def dlg_cryojet_positions(self): - p_in = settings.value(CRYOJET_NOZZLE_IN, type=float) - p_out = settings.value(CRYOJET_NOZZLE_OUT, type=float) - motion_enabled = option(CRYOJET_MOTION_ENABLED) - d = GenericDialog( - title="Cryojet Nozzle Configuration", - message="Enter reference positions for the cryojet nozzle position", - inputs={ - CRYOJET_NOZZLE_IN: ("In position", p_in, Spinner(p_in, min=3, max=15)), - CRYOJET_NOZZLE_OUT: ("Out position",p_out,Spinner(p_out, min=-1000, max=10),), - CRYOJET_MOTION_ENABLED: ("Move Cryojet in Transitions",motion_enabled,Checkbox(motion_enabled, "move cryojet"),), - }, - ) - if d.exec(): - results = d.results - _log.info("setting cryojet reference positions {}".format(results)) - for k, v in results.items(): - settings.setValue(k, v) - settings.sync() - - def dlg_deltatau_parameters(self): - SPN=GenericDialog.Spinner - CB=GenericDialog.Checkbox - app=QApplication.instance() - cfg=app._cfg - #dt1 = cfg.value(AppCfg.DT_HOST,'SAR-CPPM-EXPMX1') - dt1 = cfg.value(AppCfg.DT_HOST) - dt2 = cfg.value(AppCfg.DT_VEL_SCL, 1, type=float) - dt3 = cfg.option(AppCfg.DT_SHOW_PLOTS) - - d = GenericDialog.GenericDialog( - title="Delta Tau Parameters", - message="These parameters affect the data collection.", - inputs={ - AppCfg.DT_HOST:("host name (host[:port:port_gather])", dt1, QLineEdit(),), - AppCfg.DT_VEL_SCL: ("Velocity Scale (1=optimal, 0=zero vel at target)", dt2,SPN(dt2, min=0, max=1, suffix=""),), - AppCfg.DT_SHOW_PLOTS: ("show plots after collection", dt3,CB(dt3, "active"),), - #DELTATAU_SORT_POINTS: ("Sort pointshoot/prelocated coords", b,CB(b, "sort points"),), - }, - ) - if d.exec(): - results = d.results - _log.info("setting delta tau parameters {}".format(results)) - for k, v in results.items(): - cfg.setValue(k, v) - cfg.sync() - - def dlg_tell_mount_positions(self): - AUTODRY_ENABLED = "tell/autodry_enabled" - AUTODRY_MAXMOUNTS = "tell/autodry_max_number_of_mounts" - AUTODRY_MAXTIME = "tell/autodry_max_time" - - SECS_HOURS = 60 * 60 - - enabled = option(AUTODRY_ENABLED) - maxtime = settings.value(AUTODRY_MAXTIME, type=float) / SECS_HOURS - maxmounts = settings.value(AUTODRY_MAXMOUNTS, type=int) - - d = GenericDialog.GenericDialog( - title="TELL Settings", - message="These control some features of the TELL sample changer", - inputs={ - AUTODRY_ENABLED: ("Auto dry", enabled, - Checkbox(enabled, "enabled")), - AUTODRY_MAXMOUNTS: ("Max. num. mounts between dry",maxmounts, - Spinner(maxmounts, decimals=0, min=1, max=100, suffix=" mounts"),), - AUTODRY_MAXTIME: ("Max. time between dry",maxtime, - Spinner(maxtime, decimals=1, min=0.5, max=5, suffix=" hours"),), - }, - ) - if d.exec(): - results = d.results - _log.info("setting tell parameters {}".format(results)) - for k, v in results.items(): - if k == AUTODRY_MAXTIME: - v = v * SECS_HOURS - settings.setValue(k, v) - settings.sync() +# def dlg_geometry(self,obj): +# SPN=GenericDialog.Spinner +# app=QApplication.instance() +# cfg=app._cfg +# w, h = map(float,cfg.value(AppCfg.GEO_BEAM_SZ)) +# d = GenericDialog.GenericDialog( +# title="geometry", +# message="Enter the size of the beam in microns", +# inputs={ +# "bw": ("beam width um" ,w,SPN(w, min=1, max=200, suffix=" \u00B5m"),), +# "bh": ("beam height um",h,SPN(h, min=1, max=200, suffix=" \u00B5m"),), +# }, +# ) +# if d.exec(): +# results = d.results +# _log.info("Updating beamsize to {}".format(results)) +# bm_sz= (results["bw"], results["bh"]) +# _log.debug("types {}".format(type(w))) +# cfg.setValue(AppCfg.GEO_BEAM_SZ, bm_sz) +# cfg.sync() +# bm=obj._goBeamMarker +# bm.setSize(bm_sz) +# #self._beammark.set_beam_size((w, h)) +# +# def dlg_collimator_reference_positions(self): +# SPN=GenericDialog.Spinner +# app=QApplication.instance() +# cfg=app._cfg +# x_out = cfg.value(AppCfg.COL_DX , 0.0,type=float) +# y_out = cfg.value(AppCfg.COL_DY , 0.0,type=float) +# x_in = cfg.value(AppCfg.COL_X_IN, 0.0,type=float) +# y_in = cfg.value(AppCfg.COL_Y_IN, 0.0,type=float) +# d = GenericDialog.GenericDialog( +# title="Collimator configuration", +# message="Enter reference positions for the collimator", +# inputs={ +# AppCfg.COL_DX: ("Collimator out deltaX", x_out, SPN(x_out, decimals=3, min=-15.9, max=15.9, suffix=" mm"),), +# AppCfg.COL_DY: ("Collimator out deltaY", y_out, SPN(y_out, decimals=3, min=-15.9, max=15.9, suffix=" mm"),), +# AppCfg.COL_X_IN: ("Collimator in X", x_in, SPN(x_in, decimals=3, min=-15.9, max=15.9, suffix=" mm"),), +# AppCfg.COL_Y_IN: ("Collimator in Y", y_in, SPN(y_in, decimals=3, min=-15.9, max=15.9, suffix=" mm"),), +# }, +# ) +# if d.exec(): +# results = d.results +# _log.info("setting collimator reference positions {}".format(results)) +# for k, v in results.items(): +# cfg.setValue(k, v) +# cfg.sync() +# +# def dlg_backlight_positions(self): +# SPN=GenericDialog.Spinner +# app=QApplication.instance() +# cfg=app._cfg +# p_in = cfg.value(AppCfg.BKLGT_IN,0,type=int) +# p_out = cfg.value(AppCfg.BKLGT_OUT,0,type=int) +# d = GenericDialog.GenericDialog( +# title="Back Light configuration", +# message="Enter reference positions for the backlight", +# inputs={ +# AppCfg.BKLGT_IN: ("In position" , p_in , SPN(p_in, min=-30000, max=10), ), +# AppCfg.BKLGT_OUT: ("Out position", p_out, SPN(p_out, min=-1000, max=10), ), +# }, +# ) +# if d.exec(): +# results = d.results +# _log.info("setting back light reference positions {}".format(results)) +# for k, v in results.items(): +# cfg.setValue(k, v) +# cfg.sync() +# +# def dlg_cryojet_positions(self): +# p_in = settings.value(CRYOJET_NOZZLE_IN, type=float) +# p_out = settings.value(CRYOJET_NOZZLE_OUT, type=float) +# motion_enabled = option(CRYOJET_MOTION_ENABLED) +# d = GenericDialog( +# title="Cryojet Nozzle Configuration", +# message="Enter reference positions for the cryojet nozzle position", +# inputs={ +# CRYOJET_NOZZLE_IN: ("In position", p_in, Spinner(p_in, min=3, max=15)), +# CRYOJET_NOZZLE_OUT: ("Out position",p_out,Spinner(p_out, min=-1000, max=10),), +# CRYOJET_MOTION_ENABLED: ("Move Cryojet in Transitions",motion_enabled,Checkbox(motion_enabled, "move cryojet"),), +# }, +# ) +# if d.exec(): +# results = d.results +# _log.info("setting cryojet reference positions {}".format(results)) +# for k, v in results.items(): +# settings.setValue(k, v) +# settings.sync() +# +# def dlg_deltatau_parameters(self): +# SPN=GenericDialog.Spinner +# CB=GenericDialog.Checkbox +# app=QApplication.instance() +# cfg=app._cfg +# #dt1 = cfg.value(AppCfg.DT_HOST,'SAR-CPPM-EXPMX1') +# dt1 = cfg.value(AppCfg.DT_HOST) +# dt2 = cfg.value(AppCfg.DT_VEL_SCL, 1, type=float) +# dt3 = cfg.option(AppCfg.DT_SHOW_PLOTS) +# +# d = GenericDialog.GenericDialog( +# title="Delta Tau Parameters", +# message="These parameters affect the data collection.", +# inputs={ +# AppCfg.DT_HOST:("host name (host[:port:port_gather])", dt1, QLineEdit(),), +# AppCfg.DT_VEL_SCL: ("Velocity Scale (1=optimal, 0=zero vel at target)", dt2,SPN(dt2, min=0, max=1, suffix=""),), +# AppCfg.DT_SHOW_PLOTS: ("show plots after collection", dt3,CB(dt3, "active"),), +# #DELTATAU_SORT_POINTS: ("Sort pointshoot/prelocated coords", b,CB(b, "sort points"),), +# }, +# ) +# if d.exec(): +# results = d.results +# _log.info("setting delta tau parameters {}".format(results)) +# for k, v in results.items(): +# cfg.setValue(k, v) +# cfg.sync() +# +# def dlg_tell_mount_positions(self): +# AUTODRY_ENABLED = "tell/autodry_enabled" +# AUTODRY_MAXMOUNTS = "tell/autodry_max_number_of_mounts" +# AUTODRY_MAXTIME = "tell/autodry_max_time" +# +# SECS_HOURS = 60 * 60 +# +# enabled = option(AUTODRY_ENABLED) +# maxtime = settings.value(AUTODRY_MAXTIME, type=float) / SECS_HOURS +# maxmounts = settings.value(AUTODRY_MAXMOUNTS, type=int) +# +# d = GenericDialog.GenericDialog( +# title="TELL Settings", +# message="These control some features of the TELL sample changer", +# inputs={ +# AUTODRY_ENABLED: ("Auto dry", enabled, +# Checkbox(enabled, "enabled")), +# AUTODRY_MAXMOUNTS: ("Max. num. mounts between dry",maxmounts, +# Spinner(maxmounts, decimals=0, min=1, max=100, suffix=" mounts"),), +# AUTODRY_MAXTIME: ("Max. time between dry",maxtime, +# Spinner(maxtime, decimals=1, min=0.5, max=5, suffix=" hours"),), +# }, +# ) +# if d.exec(): +# results = d.results +# _log.info("setting tell parameters {}".format(results)) +# for k, v in results.items(): +# if k == AUTODRY_MAXTIME: +# v = v * SECS_HOURS +# settings.setValue(k, v) +# settings.sync() # ---------------------------------------------- -class WndParameter(): - def __init__(self,mainWnd): - from pyqtgraph.parametertree import Parameter, ParameterTree, ParameterItem, registerParameterType - params=[ - {'name':'Basic parameter data types', 'type':'group', 'children':[ - {'name':'Integer', 'type':'int', 'value':10}, - {'name':'Float', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'Subgroup', 'type':'group', 'children':[ - {'name':'Sub-param 1', 'type':'int', 'value':10}, - {'name':'Sub-param 2', 'type':'float', 'value':1.2e6}, - ]}, - ]}, - {'name':'geometry', 'type':'group', 'children':[ - {'name':'size of the beam', 'type':'group', 'children':[ - {'name':'width', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'height', 'type':'float', 'value':10.5, 'step':0.1}, - ]}, - ]}, - {'name':'post sample tube reference positions', 'type':'group', 'children':[ - {'name':'Up X', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'Up Y', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'Down X', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'Down Y', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'out delta X', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'out delta Y', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'tube Z in position', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'tube Z OUT position', 'type':'float', 'value':10.5, 'step':0.1}, - ]}, - {'name':'collimator reference positions', 'type':'group', 'children':[ - {'name':'in X', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'in Y', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'out deltaX', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'out deltaY', 'type':'float', 'value':10.5, 'step':0.1}, - ]}, - {'name':'Back Light reference positions', 'type':'group', 'children':[ - {'name':'In position', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'Out position', 'type':'float', 'value':0.0, 'step':0.1}, - ]}, - {'name':'Delta Tau Parameters', 'type':'group', 'children':[ - {'name':'host name (host[:port:port_gather])', 'type':'float', 'value':10.5, 'step':0.1}, - {'name':'show plots after collection', 'type':'bool', 'value':True, 'tip':"This is a checkbox"}, - ]}, - {'name':'Save/Restore functionality', 'type':'group', 'children':[ - {'name':'Save State', 'type':'action'}, - {'name':'Restore State', 'type':'action', 'children':[ - {'name':'Add missing items', 'type':'bool', 'value':True}, - {'name':'Remove extra items', 'type':'bool', 'value':True}, - ]}, - ]}, - ] - - self._p=p=Parameter.create(name='params', type='group', children=params) - p.sigTreeStateChanged.connect(lambda a,b: self.cb_change(a,b)) - # Too lazy for recursion: - for child in p.children(): - child.sigValueChanging.connect(lambda a,b: self.cb_valueChanging(a,b)) - for ch2 in child.children(): - ch2.sigValueChanging.connect(lambda a,b: self.cb_valueChanging(a,b)) - p.param('Save/Restore functionality', 'Save State').sigActivated.connect(self.cb_save) - p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(self.cb_restore) - - t=ParameterTree() - t.setParameters(p, showTop=False) - t.setWindowTitle('pyqtgraph example: Parameter Tree') - t.resize(400, 800) - self._wnd=t - - def cb_change(self,param, changes): - p=self._p - print("tree changes:") - for param, change, data in changes: - path=p.childPath(param) - if path is not None: - childName='.'.join(path) - else: - childName=param.name() - print(' parameter: %s'%childName) - print(' change: %s'%change) - print(' data: %s'%str(data)) - print(' ----------') - - def cb_valueChanging(self,param, value): - print("Value changing (not finalized): %s %s"%(param, value)) - - def cb_save(self): - self._state=p.saveState() - - def cb_restore(self): - add=p['Save/Restore functionality', 'Restore State', 'Add missing items'] - rem=p['Save/Restore functionality', 'Restore State', 'Remove extra items'] - p.restoreState(self._state, addChildren=add, removeChildren=rem) - - ## Start Qt event loop unless running in interactive mode or using pyside. if __name__ == '__main__': + logging.basicConfig(level=logging.DEBUG,format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ') import sys app=QApplication([]) - ## Create tree of Parameter objects - - cfg=AppCfg() + app._cfg=AppCfg() w=WndParameter(None) - w._wnd.show() + w.show() if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): diff --git a/swissmx.py b/swissmx.py index 7ac199d..ccc9ca6 100755 --- a/swissmx.py +++ b/swissmx.py @@ -114,7 +114,7 @@ import pyqtgraph.exporters pg.setConfigOptions(antialias=True,imageAxisOrder='row-major') ts.log('Import part 6/8:') import app_utils -from app_config import AppCfg #settings, option, toggle_option +from app_config import AppCfg,WndParameter #settings, option, toggle_option import epics from epics.ca import pend_event @@ -568,40 +568,41 @@ 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("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("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("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("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("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("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("parameters", self) action.setToolTip("modify application parameters") action.setStatusTip("modify application parameters") - action.triggered.connect(lambda x: cfg.dlg_parameters(self)) + + action.triggered.connect(self.cb_modify_app_param) self.menuAdvanced.addAction(action) @@ -1321,6 +1322,10 @@ class WndSwissMx(QMainWindow, Ui_MainWindow): #imgPos=self._goImg.mapFromScene(event.scenePos()) #x=imgPos.x();y=imgPos.y() + def cb_modify_app_param(self): + wnd=WndParameter(self) + wnd.show() + @pyqtSlot() def cb_save_cam_image(self,overlays=False): app=QApplication.instance()