diff --git a/RIXSconfig/RIXSconfig.py b/RIXSconfig/RIXSconfig.py index a038e08..62a126e 100755 --- a/RIXSconfig/RIXSconfig.py +++ b/RIXSconfig/RIXSconfig.py @@ -29,9 +29,10 @@ bitmask for simulation: from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QSlider, QLineEdit,\ - QCheckBox, QHBoxLayout, QVBoxLayout, QGroupBox, QGridLayout, QComboBox + QCheckBox, QHBoxLayout, QVBoxLayout, QGroupBox, QGridLayout, QComboBox, QMessageBox from PyQt5.QtGui import QPainter, QColor, QPen, QBrush, QPolygon, QTransform from PyQt5.QtCore import QPoint, QPointF, Qt +from numpy.matlib import empty from pyqtgraph.Qt import QtCore, QtGui import PyQt5.QtGui as QtGui @@ -118,7 +119,7 @@ class WndMainRIXS(QWidget): w.clicked.connect(lambda dummy,pb=pb: self.OnOpenChildWnd(pb)) lv.addWidget(w) - w=QGroupBox(dev._name, self) + w=QGroupBox(dev._name, self,objectName=dev._name) lv.addWidget(w) lg=QGridLayout(w) row=0 @@ -169,18 +170,27 @@ class WndMainRIXS(QWidget): def btnSyncMotors(self): #reads the epics motor and updates the vizualization _log.info('') + app=QApplication.instance() dev=app._dev - pv_rbv=dev._pvDict['rbv'] geo=dev._geo + pv_rbv=dev._pvDict['rbv'] + wGrp=self.findChild(QGroupBox,dev._name) + wLe=wGrp.findChild(QLineEdit, 'energy') + #wLe=self.findChild(QLineEdit, 'energy') + wLe.blockSignals(True) + wLe.setText('') + wLe.blockSignals(False) + m=dict() for k,v in pv_rbv.items(): if v.connected: - geo[k]=v.get() + m[k]=v.get() else: _log.warning(f'pv {k} not connected') - return - dev.motor2geometry() - dev.setGeometry(dev._geo) + break + dev.motor2geometry(m) + geo.update(m) + dev.setGeo2Paint(dev._geo) try: wndCld=app._wndVisualize except AttributeError as e: @@ -293,7 +303,7 @@ class WndMainRIXS(QWidget): _log.error(f'can not find probe: {repr(e)}') return geo=vlsg.energy2geometry(energy,probe) - dev.setGeometry(geo) + dev.setGeo2Paint(geo) try: dev.geometry2motor() except ValueError as e: @@ -313,8 +323,6 @@ class WndMainRIXS(QWidget): wndCld.updateDevice(dev) - - class RIXSdevice(): _lutDifrBeamPaint=( # (number of difr beam,draw mode,alpha,width) (4, 2, 190, 0), @@ -356,7 +364,7 @@ class RIXSdevice(): 'bb':87, # reflection angle 'cc':22, # detector angle } - self.setGeometry(g) + self.setGeo2Paint(g) self.connectEPICS() def connectEPICS(self): @@ -367,8 +375,14 @@ class RIXSdevice(): for m,v in self._motors: pvn=self._prefix+'MOT_'+m.upper()+'.RBV' pv=epics.get_pv(pvn,connection_callback=self.OnConnectionChange,callback=self.OnValueChange) + #pv=epics.get_pv(pvn) pv_rbv[m]=pv _log.info(f'{pv}') + print(len(pv_rbv)) + #for pv in pv_rbv.values(): #need to do it is 2 steps. + # pv.connection_callbacks.append(self.OnConnectionChange) + # idx=pv.add_callback(self.OnValueChange) + # pv.run_callback(idx) def OnConnectionChange(self, pvname=None, conn=None, **kws): pvc=self._pvConnected @@ -376,7 +390,8 @@ class RIXSdevice(): pvc+=1 else: if pvc>0: pvc-=1 - _log.info(f'PV connection {pvc}/{len(self._pvDict)}: {pvname} {conn}') + pv_rbv=self._pvDict['rbv'] + _log.info(f'PV connection {pvc}/{len(pv_rbv)}: {pvname} {conn}') self._pvConnected=pvc app=QApplication.instance() @@ -402,18 +417,29 @@ class RIXSdevice(): #} _log.info(f"PV val:{pvname}:{value}") app=QApplication.instance() + self.motor2geometry() + self.setGeo2Paint(self._geo) try: - wnd=app._wndVars + wndCld=app._wndVisualize except AttributeError as e: pass else: - wnd.update_label(pvname,value,**kw) + wndCld.updateDevice(self) + try: + wndCld=app._wndVars + except AttributeError as e: + pass + else: + #wnd.update_label(pvname, value, **kw) # would not update the geometry + wndCld.updateDevice(self) + + #pv.add_callback('RBV', self.update_label) #_log.warning(f"can't handle PV: {pvname}:{value}") # return #self.vis_update(key,value,'008000') - def setGeometry(self,geo): + def setGeo2Paint(self,geo): self._geo=geo p=self._paint sclA,sclD=p['sclTrf'] @@ -428,7 +454,6 @@ class RIXSdevice(): def geometry2motor(self): # returns raw motor positions # offset detector plane to deflected beam: 34deg - geo=self._geo r1,r2,aa,bb,cc=geo['r1'],geo['r2'],geo['aa'],geo['bb'],geo['cc'] mt=gtz=gty1=gty2=grx=gtx=dtz=dty1=dty2=drx=None @@ -436,7 +461,7 @@ class RIXSdevice(): radArm=np.deg2rad(degArm) gtz=r1 grx=90-aa - dtz=np.cos(radArm)*r2 + dtz=r1+np.cos(radArm)*r2 dty1=dty2=np.sin(radArm)*r2 drx=90-aa+90-bb+cc-34 dd=cc-34 # angle of bellow to detector @@ -460,24 +485,54 @@ class RIXSdevice(): elif abs(dd)>15: raise(ValueError('angle bellow to detector > 15°')) - def motor2geometry(self): - _log.info('TODO...') - geo=self._geo - mt,gtz,gty1,gty2,grx,gtx,dtz,dty1,dty2,drx= geo['mt'],geo['gtz'],geo['gty1'],geo['gty2'],geo['grx'],geo['gtx'],geo['dtz'],geo['dty1'],geo['dty2'],geo['drx'] + def motor2geometry(self,m=None): + # reads the motor position from the pv and updates the geometry + # IT DOES NOT touch the motor fields in _geometry ! + if m is None: #dictionary is empty + pv_rbv=self._pvDict['rbv'] + if len(pv_rbv)<10: + _log.info('not yet populated') + return + m=dict() + for k, v in pv_rbv.items(): + if v.connected and v._args['value'] is not None: + # v._args['value'] is not None is needed as connected sometimes is not save enough + m[k]=v.get() + else: + _log.warning(f'pv {k} not connected or no value') + return + def mot2geo(mt,gtz,gty1,gty2,grx,gtx,dtz,dty1,dty2,drx): + geo=self._geo + #degArm=90-aa+90-bb + #radArm=np.deg2rad(degArm) + #gtz=r1 + #grx=90-aa + #dtz=np.cos(radArm)*r2 + #dty1=dty2=np.sin(radArm)*r2 + #drx=90-aa+90-bb+cc-34 + #dd=cc-34 # angle of bellow to detector - r1=gtz - #r2= - aa=90-grx - #bb= - #cc= + r1=gtz + x=(dtz-gtz) + y=(dty1+dty2)/2 + r2=(x**2+y**2)**.5 + radArm=np.arctan2(y,x) + degArm=np.rad2deg(radArm) + aa=90-grx + #degArm=90-aa+90-bb + bb=90-aa+90-degArm + #drx=90-aa+90-bb+cc-34 + #cc=drx-90+aa-90+bb+34 + cc=drx-degArm+34 - geo.update({ - 'r1':r1, - #'r2':r2, - 'aa':aa, - #'bb':bb, - #'cc':cc, - }) + geo.update({ + 'r1':r1, + 'r2':r2, + 'aa':aa, + 'bb':bb, + 'cc':cc, + }) + mot2geo(**m) @@ -758,7 +813,7 @@ class WndVisualize(QWidget): p['sclTrf']=(2**(val/2),p['sclTrf'][1]) else: p['sclTrf']=(p['sclTrf'][0],2**(val/2)) - dev.setGeometry(dev._geo) + dev.setGeo2Paint(dev._geo) else: p[key]=val g=dev._geo @@ -844,6 +899,7 @@ class WndVisualize(QWidget): qp.end() def updateDevice(self, dev): + #_log.info(f'WndVis') self._devSel=dev devP=dev._paint wGrp=self._wdGrpDraw @@ -998,14 +1054,14 @@ class WndVars(QWidget): self.update() def update_label(self, k,v,**kwargs): - _log.info(f'{k}:{v}:{kwargs}') + #_log.info(f'{k}:{v}:{kwargs}') app=QApplication.instance() dev=app._dev if kwargs: rbv=v key=re.search('_(.*)\.',k).group(1).lower() val=dev._geo.get(key,None) - _log.debug(f'monitoring: {key}:{val}:{rbv}') + #_log.debug(f'monitoring: {key}:{val}:{rbv}') else: key=k val=v @@ -1015,7 +1071,7 @@ class WndVars(QWidget): rbv=pv.get() else: rbv=None - _log.debug(f'change: {key}:{val}:{rbv}') + #_log.debug(f'change: {key}:{val}:{rbv}') grpMot=self._wdGrpMotor wLe=grpMot.findChild(QLineEdit, key) if wLe is not None: @@ -1042,17 +1098,30 @@ class WndVars(QWidget): def btnMoveMotors(self): app=QApplication.instance() dev=app._dev - pv_rbv=dev._pvDict['rbv'] + grpMot=self._wdGrpMotor + lg=grpMot.layout() + row=lg.rowCount() + cnt=0 + for r in range(row-1): # -1 because last one is a button + wCb=lg.itemAtPosition(r, 0) + if wCb is None: continue + if wCb.widget().isChecked(): cnt+=1 + if cnt==0: return + btn=QMessageBox.question( + self, + "Motion", + f"Really want to move {cnt} motors ?", + buttons=QMessageBox.Yes|QMessageBox.No, + defaultButton=QMessageBox.No, + ) + if btn!=QMessageBox.Yes: return + + geo=dev._geo try: pv_val=dev._pvDict['val'] except KeyError as e: pv_val=dev._pvDict['val']=dict() - geo=dev._geo - grpMot=self._wdGrpMotor - lg=grpMot.layout() - col=lg.columnCount() - row=lg.rowCount() for r in range(row-1): # -1 because last one is a button wCb=lg.itemAtPosition(r, 0) if wCb is None: