refactoring and log of coorinate work

This commit is contained in:
2022-09-02 12:46:51 +02:00
parent a54e580664
commit 45e8ab680f
8 changed files with 215 additions and 154 deletions

View File

@@ -106,19 +106,26 @@ class AppCfg(QSettings):
if AppCfg.GEO_PIX2POS not in keys: if AppCfg.GEO_PIX2POS not in keys:
_log.warning(f'{AppCfg.GEO_PIX2POS} not defined. use default') _log.warning(f'{AppCfg.GEO_PIX2POS} not defined. use default')
lut_pix2pos=(np.array([1., 200., 400., 600., 800., 1000.]), #lut_pix2pos=(np.array([1., 200., 400., 600., 800., 1000.]),
np.array([[[ 2.42827273e-03, -9.22117396e-05], # np.array([[[ 2.42827273e-03, -9.22117396e-05],
[-1.10489804e-04, -2.42592492e-03]], # [-1.10489804e-04, -2.42592492e-03]],
[[ 1.64346103e-03, -7.52341417e-05], # [[ 1.64346103e-03, -7.52341417e-05],
[-6.60711165e-05, -1.64190224e-03]], # [-6.60711165e-05, -1.64190224e-03]],
[[ 9.91307639e-04, -4.02008751e-05], # [[ 9.91307639e-04, -4.02008751e-05],
[-4.23878232e-05, -9.91563507e-04]], # [-4.23878232e-05, -9.91563507e-04]],
[[ 5.98443038e-04, -2.54046255e-05], # [[ 5.98443038e-04, -2.54046255e-05],
[-2.76831563e-05, -6.02738142e-04]], # [-2.76831563e-05, -6.02738142e-04]],
[[ 3.64418977e-04, -1.41389267e-05], # [[ 3.64418977e-04, -1.41389267e-05],
[-1.55708176e-05, -3.66233567e-04]], # [-1.55708176e-05, -3.66233567e-04]],
[[ 2.16526433e-04, -8.23070130e-06], # [[ 2.16526433e-04, -8.23070130e-06],
[-9.29894004e-06, -2.16842976e-04]]])) # [-9.29894004e-06, -2.16842976e-04]]]))
# rough data for binning=1,1
z=np.array((1.0, 200.0, 400.0, 600.0, 800.0, 1000.0))
t1=np.array(([1, 0.0000], [0.0000, -1])).reshape(1, -1)
t2=np.array((0.001214,0.000821,0.000495,0.000299,0.000182,0.000108)).reshape(-1, 1)
trf=(t1*t2).reshape((-1, 2, 2))
lut_pix2pos=(z, trf)
self.setValue(AppCfg.GEO_PIX2POS, lut_pix2pos) self.setValue(AppCfg.GEO_PIX2POS, lut_pix2pos)
if AppCfg.GEO_OPT_CTR not in keys: if AppCfg.GEO_OPT_CTR not in keys:

View File

@@ -190,7 +190,7 @@ class epics_cam(object):
def set_param(self,**kwargs): def set_param(self,**kwargs):
param=[] param=[]
for k,v in kwargs: for k,v in kwargs.items():
if k=='gain': if k=='gain':
pv_gain=self.getPv('AMPGAIN') pv_gain=self.getPv('AMPGAIN')
param.append((pv_gain,v)) param.append((pv_gain,v))
@@ -214,8 +214,8 @@ class epics_cam(object):
param.append((pv_rye,v[1]+v[3])) param.append((pv_rye,v[1]+v[3]))
elif k=='mono8': elif k=='mono8':
pv_mono8=self.getPv('FORCEMONO8') pv_mono8=self.getPv('FORCEMONO8')
param.append((pv_mono8,vv)) param.append((pv_mono8,v))
self.update_params(param) self.update_params(*param)
def set_exposure(self,exp): def set_exposure(self,exp):
try: try:
@@ -246,16 +246,16 @@ class epics_cam(object):
#def update_params(self, **kargs): #def update_params(self, **kargs):
def update_params(self, *args): def update_params(self, *args):
"""update parameters on camera""" """update parameters on camera"""
pv_cam=self.getPv('CAMERA')
pv_cam.put(CameraStatus.IDLE, wait=True)
for pv, val in args: for pv, val in args:
if not pv.connected: if not pv.connected:
_log.info('force connect {}'.format(pv)) _log.info('force connect {}'.format(pv))
pv.force_connect() #force to connect pv pv.force_connect() #force to connect pv
_log.debug("updating {} = {}".format(pv.pvname, val)) _log.debug("updating {} = {}".format(pv.pvname, val))
pv.put(val, wait=True) pv.put(val, wait=True)
pv_cam=self.getPv('CAMERA')
pv_cs = self.getPv('CAMERASTATUS') pv_cs = self.getPv('CAMERASTATUS')
#pv_set_param=self.getPv("SET_PARAM") #pv_set_param=self.getPv("SET_PARAM")
pv_cam.put(CameraStatus.IDLE, wait=True)
#pv_set_param.put(1, wait=True) #pv_set_param.put(1, wait=True)
pv_cam.put(CameraStatus.RUNNING, wait=True) pv_cam.put(CameraStatus.RUNNING, wait=True)
self.update_size() self.update_size()
@@ -308,11 +308,13 @@ class epics_cam(object):
img=PIL.Image.open(fn) img=PIL.Image.open(fn)
#assert(img.mode=='L') # 8 bit grayscale #assert(img.mode=='L') # 8 bit grayscale
assert(sz==img.size) assert(sz==img.size)
if img.mode in ('L'): if img.mode=='L':
#imgSeq[i, :, :]=np.asarray(img) #imgSeq[i, :, :]=np.asarray(img)
imgSeq[i,:,:]=np.array(img.getdata()).reshape(sz[::-1]) imgSeq[i,:,:]=np.array(img.getdata()).reshape(sz[::-1])
elif img.mode=='LA': elif img.mode=='LA':
imgSeq[i, :, :]=np.asarray(img)[:,:,0] imgSeq[i, :, :]=np.asarray(img)[:, :, 0]
elif img.mode=='I':
imgSeq[i, :, :]=np.asarray(img)
else: else:
raise TypeError(f'unsupported image mode format {img.mode}') raise TypeError(f'unsupported image mode format {img.mode}')
pic=imgSeq[i] pic=imgSeq[i]

View File

@@ -60,7 +60,7 @@ class MotorTweak(QWidget, Ui_MotorTweak):
self.set_motor_validator() self.set_motor_validator()
self._drive_val.setText(m.get('VAL', as_string=True)) self._drive_val.setText(m.get('VAL', as_string=True))
self._drive_val.returnPressed.connect(self.move_motor_to_position) self._drive_val.returnPressed.connect(self.move_abs)
tweak_min = kwargs.get("tweak_min", 0.0001) tweak_min = kwargs.get("tweak_min", 0.0001)
tweak_max = kwargs.get("tweak_max", 10.0) tweak_max = kwargs.get("tweak_max", 10.0)
@@ -112,7 +112,7 @@ class MotorTweak(QWidget, Ui_MotorTweak):
lineedit.setValidator(QDoubleValidator(min, max, m.PV('PREC').get(), lineedit)) lineedit.setValidator(QDoubleValidator(min, max, m.PV('PREC').get(), lineedit))
def move_relative(self, dist): def move_rel(self, dist):
try: try:
self._val+=dist self._val+=dist
except AttributeError: except AttributeError:
@@ -144,7 +144,7 @@ class MotorTweak(QWidget, Ui_MotorTweak):
status = DeltatauMotorStatus(m.motor_status) status = DeltatauMotorStatus(m.motor_status)
return bool(DeltatauMotorStatus.MOTOR_HAS_BEEN_HOMED & status) return bool(DeltatauMotorStatus.MOTOR_HAS_BEEN_HOMED & status)
def move_motor_to_position(self, drive=None, wait=False, assert_position=False): def move_abs(self, drive=None, wait=False, assert_position=False):
if drive is None: if drive is None:
drive = float(self._drive_val.text()) drive = float(self._drive_val.text())
if assert_position: if assert_position:

View File

@@ -61,7 +61,7 @@ class SimMotorTweak(QWidget, Ui_MotorTweak):
self._motor=m=SimMotor(rec_name, short_name) self._motor=m=SimMotor(rec_name, short_name)
self.set_motor_validator() self.set_motor_validator()
self._drive_val.setText(str(m._pos)) self._drive_val.setText(str(m._pos))
self._drive_val.returnPressed.connect(self.move_motor_to_position) self._drive_val.returnPressed.connect(self.move_abs)
self.jog_forward.hide() self.jog_forward.hide()
self.jog_reverse.hide() self.jog_reverse.hide()
@@ -71,8 +71,8 @@ class SimMotorTweak(QWidget, Ui_MotorTweak):
self._tweak_val.setText(str(m._twv)) self._tweak_val.setText(str(m._twv))
self._tweak_val.setValidator(QDoubleValidator(tweak_min, tweak_max, 4, self._tweak_val)) self._tweak_val.setValidator(QDoubleValidator(tweak_min, tweak_max, 4, self._tweak_val))
#self._tweak_val.editingFinished.connect(lambda m=self._pv_tweak_val: m.put(self._tweak_val.text())) #self._tweak_val.editingFinished.connect(lambda m=self._pv_tweak_val: m.put(self._tweak_val.text()))
self.tweak_forward.clicked.connect(lambda m: self.move_relative(float(self._tweak_val.text()))) self.tweak_forward.clicked.connect(lambda m: self.move_rel(float(self._tweak_val.text())))
self.tweak_reverse.clicked.connect(lambda m: self.move_relative(-float(self._tweak_val.text()))) self.tweak_reverse.clicked.connect(lambda m: self.move_rel(-float(self._tweak_val.text())))
#self.tweak_forward.clicked.connect(lambda m: self._pv_tweak_f.put(1)) #self.tweak_forward.clicked.connect(lambda m: self._pv_tweak_f.put(1))
#self.tweak_reverse.clicked.connect(lambda m: self._pv_tweak_r.put(1)) #self.tweak_reverse.clicked.connect(lambda m: self._pv_tweak_r.put(1))
@@ -102,7 +102,7 @@ class SimMotorTweak(QWidget, Ui_MotorTweak):
lineedit.setValidator(QDoubleValidator(min, max, 5, lineedit)) lineedit.setValidator(QDoubleValidator(min, max, 5, lineedit))
def move_relative(self, dist, delay=None): def move_rel(self, dist, delay=None):
m=self._motor m=self._motor
m._pos += dist m._pos += dist
if delay: if delay:
@@ -144,7 +144,7 @@ class SimMotorTweak(QWidget, Ui_MotorTweak):
def is_done(self): def is_done(self):
return True # in (0, 3) return True # in (0, 3)
def move_motor_to_position(self, drive=None, wait=False, assert_position=False): def move_abs(self, drive=None, wait=False, assert_position=False):
m=self._motor m=self._motor
if assert_position: if assert_position:
wait=True wait=True

View File

@@ -80,7 +80,7 @@ class SmaractMotorTweak(QWidget, Ui_MotorTweak):
self.set_motor_validator() self.set_motor_validator()
self._drive_val.setText(self._pv_drive.get(as_string=True)) self._drive_val.setText(self._pv_drive.get(as_string=True))
self._drive_val.returnPressed.connect(self.move_motor_to_position) self._drive_val.returnPressed.connect(self.move_abs)
self.jog_forward.hide() self.jog_forward.hide()
self.jog_reverse.hide() self.jog_reverse.hide()
@@ -120,7 +120,7 @@ class SmaractMotorTweak(QWidget, Ui_MotorTweak):
lineedit.setValidator(QDoubleValidator(min, max, 5, lineedit)) lineedit.setValidator(QDoubleValidator(min, max, 5, lineedit))
def move_relative(self, dist, delay=None): def move_rel(self, dist, delay=None):
cur = self._pv_readback.get() cur = self._pv_readback.get()
target = cur + dist target = cur + dist
if delay: if delay:
@@ -158,7 +158,7 @@ class SmaractMotorTweak(QWidget, Ui_MotorTweak):
def is_done(self): def is_done(self):
return self._pv_status.get() in (0, 3) return self._pv_status.get() in (0, 3)
def move_motor_to_position(self, drive=None, wait=False, assert_position=False): def move_abs(self, drive=None, wait=False, assert_position=False):
if assert_position: if assert_position:
wait=True wait=True
if drive is None: if drive is None:

View File

@@ -531,3 +531,21 @@ if __name__=="__main__":
[2.80894834, 2.71536886, 3.1415], [2.80894834, 2.71536886, 3.1415],
[2.84446241, 3.54734879, 3.1415]]) [2.84446241, 3.54734879, 3.1415]])
plane=geometry.least_square_plane(pts) plane=geometry.least_square_plane(pts)
# pix2pos="[[1.0, 200.0, 400.0, 600.0, 800.0], [[[0.001182928623952055, -2.6941995127711305e-05], [-4.043716694634124e-05, -0.0011894314084263825]], [[0.0007955995220142541, -3.175003727901119e-05], [-2.0896601103372113e-05, -0.0008100805094631365]], [[0.00048302539335378367, -1.1661121407652543e-05], [-2.0673746995751222e-05, -0.0004950857899461772]], [[0.00028775903460576395, -1.3762555219494508e-05], [-9.319936861519268e-06, -0.0002889214488565999]], [[0.0001788819256630411, -6.470841493681516e-06], [-2.0336605088889967e-06, -0.0001831131753499113]]]]"
#lut_pix2pos=(np.array([1., 200., 400., 600., 800., 1000.]),
# np.array([[[ 2.42827273e-03, -9.22117396e-05],[-1.10489804e-04, -2.42592492e-03]],
# [[ 1.64346103e-03, -7.52341417e-05],[-6.60711165e-05, -1.64190224e-03]],
# [[ 9.91307639e-04, -4.02008751e-05],[-4.23878232e-05, -9.91563507e-04]],
# [[ 5.98443038e-04, -2.54046255e-05],[-2.76831563e-05, -6.02738142e-04]],
# [[ 3.64418977e-04, -1.41389267e-05],[-1.55708176e-05, -3.66233567e-04]],
# [[ 2.16526433e-04, -8.23070130e-06],[-9.29894004e-06, -2.16842976e-04]]]))
#np.array([[[ 0.0010, 0.0001],[-0.0001, -0.0010]],
# [[ 0.00163, 0.00000],[-0.00000, -0.00163]],
# [[ 0.00099, 0.00000],[-0.00000, -0.00099]],
# [[ 0.00060, 0.00000],[-0.00000, -0.00060]],
# [[ 0.00036, 0.00000],[-0.00000, -0.00036]],
# [[ 0.00022, 0.00000],[-0.00000, -0.00022]]]))

View File

@@ -145,9 +145,9 @@ class Marker(pg.ROI):
# # p.drawText(-w, -h, '{:.0f}x{:.0f}'.format(*self._size)) # # p.drawText(-w, -h, '{:.0f}x{:.0f}'.format(*self._size))
class Fiducial(pg.ROI): class Fiducial(pg.ROI):
def __init__(self, pos, size, xyz, **kargs): def __init__(self, pos, size, z:float, **kargs):
pg.ROI.__init__(self, pos, size, **kargs) pg.ROI.__init__(self, pos, size, **kargs)
self._xyz=xyz self._z=z
def paint(self, p, *args): def paint(self, p, *args):
#pg.ROI.paint(self, p, *args) #pg.ROI.paint(self, p, *args)
@@ -157,16 +157,30 @@ class Fiducial(pg.ROI):
p.translate(r.left(), r.top()) p.translate(r.left(), r.top())
p.scale(.01*r.width(), .01*r.height()) # -> values x,y 0 to 100 p.scale(.01*r.width(), .01*r.height()) # -> values x,y 0 to 100
p.drawRect(0, 0, 100, 100) p.drawRect(0, 0, 100, 100)
p.drawEllipse(45, 45, 10, 10)
p.setPen(pg.mkPen(width=1, color=[255, 0, 0])) p.setPen(pg.mkPen(width=1, color=[255, 0, 0]))
p.drawLine(pg.Point(50,10), pg.Point(50, 90)) p.drawLine(pg.Point(50,10), pg.Point(50, 90))
p.drawLine(pg.Point(10,50), pg.Point(90, 50)) p.drawLine(pg.Point(10,50), pg.Point(90, 50))
tr=p.transform() #tr=p.transform()
tr.setMatrix(tr.m11(), tr.m12(), tr.m13(), tr.m21(), -tr.m22(), tr.m23(), tr.m31(), tr.m32(), tr.m33()) #tr.setMatrix(tr.m11(), tr.m12(), tr.m13(), tr.m21(), -tr.m22(), tr.m23(), tr.m31(), tr.m32(), tr.m33())
p.setTransform(tr) #p.setTransform(tr)
f=p.font()
f.setPixelSize(10)
p.setFont(f)
#p.drawText(24, 20, 'beam marker')
ctr=tuple(self.pos()+self.size()/2)
sz=tuple(self.size())
print((*ctr,self._z))
#p.drawText(5, 25, 'x{:.4g}\ny{:.4g}\nz{:.4g}'.format(*ctr,self._z))
p.drawText(52, 10,40,40,Qt.TextWordWrap, 'x{:.5g}\ny{:.5g}\nz{:.5g}'.format(*ctr,self._z))
def ctr(self):
ctr=tuple(self.pos()+self.size()/2)+(self._z,)
return ctr
def __repr__(self): def __repr__(self):
pos='('+', '.join(tuple(map(lambda x: f'{x:.6g}',self.pos())))+')' ctr=self.ctr()
s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, xyz:{itr2str(self._xyz)}}}' s=f'{self.__class__.__name__}:(ctr:{itr2str(ctr)}, size:{itr2str(self.size())}}}'
return s return s
def obj2json(self,encoder): def obj2json(self,encoder):
@@ -174,7 +188,7 @@ class Fiducial(pg.ROI):
'__class__':self.__class__.__name__, '__class__':self.__class__.__name__,
'pos':tuple(self.pos()), 'pos':tuple(self.pos()),
'size':tuple(self.size()), 'size':tuple(self.size()),
'xyz':tuple(self._xyz), 'z':self._z,
} }
return jsn return jsn
@@ -469,6 +483,7 @@ class FixTargetFrame(pg.ROI):
def get_scan_param(self,mode=0x2): def get_scan_param(self,mode=0x2):
'returns scan parameters for scanning with deltatau. the format is as used for shapepath' 'returns scan parameters for scanning with deltatau. the format is as used for shapepath'
grid=self._dscr['grid'] grid=self._dscr['grid']
self._dscr['size']
#pos=np.array(self.pos()) #pos=np.array(self.pos())
cnt =np.array(grid['count'],np.int32) cnt =np.array(grid['count'],np.int32)
#pos =np.array(grid['pos'],np.float) #pos =np.array(grid['pos'],np.float)
@@ -486,10 +501,13 @@ class FixTargetFrame(pg.ROI):
pts=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float).transpose() #*pitch pts=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float).transpose() #*pitch
param={'grid':grid, 'points':pts} param={'grid':grid, 'points':pts}
trf=self.transform() t=self.transform()
if not trf.isIdentity(): p=np.array(self.pos())
#obj_info(trf) s=self.size()/self._dscr['size']
trf=np.array(((trf.m11(),trf.m12()),(trf.m21(),trf.m22()))) trf=np.array(((t.m11(),t.m12(),0),(t.m21(),t.m22(),0)))
trf[:,2]=p
trf[:,:2]*=s
# trf*'gridpos in um' -> motor pos in mm
param['trf']=trf param['trf']=trf
return param return param
@@ -661,7 +679,7 @@ if __name__=='__main__':
vi=FixTargetFrame((400,-200),(400,400),tpl='12.5x12.5') vi=FixTargetFrame((400,-200),(400,400),tpl='12.5x12.5')
vb.addItem(vi) vb.addItem(vi)
vi=Fiducial((0,200),(40,40),(1,2,3)) vi=Fiducial((0,200),(40,40),3)
vb.addItem(vi) vb.addItem(vi)
viRoi=pg.ROI([-200, -200], [100, 80],movable=True, rotatable=True, resizable=True) viRoi=pg.ROI([-200, -200], [100, 80],movable=True, rotatable=True, resizable=True)

View File

@@ -659,7 +659,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
if type(v)==tuple: if type(v)==tuple:
if v==tuple(paramSv[k]): if v==tuple(paramSv[k]):
continue continue
#cam.set_param(paramSv) cam.set_param(**paramSv)
#cfg.setValue(AppCfg.GEO_CAM_PARAM, param) #cfg.setValue(AppCfg.GEO_CAM_PARAM, param)
#break #break
_log.debug(f'diff:{k},{v} != {paramSv[k]}') _log.debug(f'diff:{k},{v} != {paramSv[k]}')
@@ -773,6 +773,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
obj._pos_eu=bm_pos=-geo.pix2pos(bm_pos+opt_ctr+bm_sz/2) obj._pos_eu=bm_pos=-geo.pix2pos(bm_pos+opt_ctr+bm_sz/2)
_log.debug(f'{obj}->{bm_pos} !!! NOT SAVED IN CONFIG !!!') _log.debug(f'{obj}->{bm_pos} !!! NOT SAVED IN CONFIG !!!')
#cfg.setValue(AppCfg.GEO_BEAM_POS,bm_pos) #cfg.setValue(AppCfg.GEO_BEAM_POS,bm_pos)
self.track_objects()
def cb_zoom_changed(self, value): def cb_zoom_changed(self, value):
#self.zoomChanged.emit(value) #self.zoomChanged.emit(value)
@@ -962,15 +963,22 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
pTrk=pg.Point(self._goTracked.mapFromScene(pos)) pTrk=pg.Point(self._goTracked.mapFromScene(pos))
fx=self.tweakers["fast_x"].get_val() fx=self.tweakers["fast_x"].get_val()
fy=self.tweakers["fast_y"].get_val() fy=self.tweakers["fast_y"].get_val()
pTrk=pTrk-(fx,fy) pRel=pTrk-(fx,fy)
#s=f'pImg{pImg} pTrk{pTrk} bm._pos_eu{bm._pos_eu}' #s=f'pImg{pImg} pTrk{pTrk} bm._pos_eu{bm._pos_eu}'
try:
pln=geo._fitPlane
except AttributeError:
cz=np.nan
else:
cz=pln[0]*pTrk[0]+pln[1]*pTrk[1]+pln[2] # z=ax+by+c
s=\ s=\
f'img pix ({pImg[0]:>0.1f} {pImg[1]:>0.1f})px \u23A2 ' \ f'img pix ({pImg[0]:0.1f} {pImg[1]:0.1f})px \u23A2 ' \
f'dist to beam ({pTrk[0]:>0.6g} {pTrk[1]:>0.6g}mm) ' f'stage ({pTrk[0]:0.4f} {pTrk[1]:>0.4f} {cz:>0.4f})mm \u23A2 ' \
f'dist to beam ({pRel[0]:>0.4f} {pRel[1]:>0.4f})mm '
#f'dist to beam ({pRel[0]:>0.6g} {pRel[1]:>0.6g}mm) '
_log.debug(s) #_log.debug(s)
self._lb_coords.setText(s) self._lb_coords.setText(s)
#self._lb_coords.setText( #self._lb_coords.setText(
# "\u23FA{:>}:{:>6.0f} {:<.0f}" # "\u23FA{:>}:{:>6.0f} {:<.0f}"
@@ -986,6 +994,33 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
# ) # )
#) #)
def cb_mouse_click_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 cb_mouse_click(self, event): def cb_mouse_click(self, event):
#_log.debug("{}".format(event)) #_log.debug("{}".format(event))
#_log.debug("screen pos {}".format(event.screenPos())) #pixel position on the whole screen #_log.debug("screen pos {}".format(event.screenPos())) #pixel position on the whole screen
@@ -997,9 +1032,13 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
# _log.debug(f"{type(o)} pos {o.mapFromScene(p)}") #pixel position on the scene (including black frame) # _log.debug(f"{type(o)} pos {o.mapFromScene(p)}") #pixel position on the scene (including black frame)
#_log.debug(f"currentItem:{event.currentItem}") #_log.debug(f"currentItem:{event.currentItem}")
app=QApplication.instance()
mod=event.modifiers()
btn=event.button()
task = self.active_task() task = self.active_task()
if task==TASK_SETUP_GEOMETRY_CALIB: if task==TASK_SETUP_GEOMETRY_CALIB:
self.mouse_click_event_geometry_calib(event) if btn==Qt.LeftButton and not mod&Qt.ControlModifier:
self.cb_mouse_click_geometry_calib(event)
return return
################################ ################################
# Ctrl-left : move to position # Ctrl-left : move to position
@@ -1007,9 +1046,6 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
################################ ################################
#dblclick = event.double() #dblclick = event.double()
app=QApplication.instance()
mod=event.modifiers()
btn=event.button()
if btn==Qt.LeftButton: if btn==Qt.LeftButton:
if mod&Qt.ShiftModifier: if mod&Qt.ShiftModifier:
pass pass
@@ -1017,28 +1053,28 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
pos=event.scenePos() pos=event.scenePos()
_log.debug(f'move to position :scene pos {pos}') _log.debug(f'move to position :scene pos {pos}')
geo=app._geometry geo=app._geometry
#geo.interp_zoom(1)
bm=self._goBeamMarker
p1=self._goImg.mapFromScene(pos)
p2=bm.pos()+bm.size()/2
px=p2+p1
mm=geo.pix2pos(px)
_log.debug(f'{px} -> {mm}')
pImg=pg.Point(self._goImg.mapFromScene(pos))
pTrk=pg.Point(self._goTracked.mapFromScene(pos))
fx=self.tweakers["fast_x"].get_val()
fy=self.tweakers["fast_y"].get_val()
pRel=pTrk-(fx, fy)
_log.debug(f'dist to beam ({pTrk[0]:>0.6g} {pTrk[1]:>0.6g}mm)')
fx_motor=self.tweakers["fast_x"] fx_motor=self.tweakers["fast_x"]
fy_motor=self.tweakers["fast_y"] fy_motor=self.tweakers["fast_y"]
#bz=self.tweakers["base_z"].get_rbv()
#fx_motor, fy_motor, bx_motor, bz_motor, omega_motor=self.get_gonio_tweakers() #fx_motor.move_rel(pRel[0])
#fx=fx_motor.get_position() #fy_motor.move_rel(pRel[1])
#fy=fy_motor.get_position() fx_motor.move_abs(pTrk[0])
#dx=(x-bx)/ppm fy_motor.move_abs(pTrk[1])
#dy=-(y-by)/ppm try:
#fx+=dx pln=geo._fitPlane
#fy+=dy except AttributeError: pass
fx_motor.move_relative(-mm[0]) else:
fy_motor.move_relative(-mm[1]) cz_motor=self.tweakers["base_z"]
#self.fast_dx_position.emit(dx) cz=pln[0]*pTrk[0]+pln[1]*pTrk[1]+pln[2] #z=ax+by+c
#self.fast_dy_position.emit(dy) cz_motor.move_abs(cz)
_log.debug(f'cz={pln[0]:.4g}*{pTrk[0]:.4g}+{pln[1]:.4g}*{pTrk[1]:.4g}+{pln[2]:.4g}={cz}')
pass pass
elif mod&Qt.AltModifier: elif mod&Qt.AltModifier:
pass pass
@@ -1118,14 +1154,14 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
dx = (x - bx) / ppm dx = (x - bx) / ppm
dy = -(y - by) / ppm dy = -(y - by) / ppm
_log.info("moving base_X, fast_Y {:.3f}, {:.3f}".format(dx, dy)) _log.info("moving base_X, fast_Y {:.3f}, {:.3f}".format(dx, dy))
bx_motor.move_relative(dx) bx_motor.move_rel(dx)
fy_motor.move_relative(dy) fy_motor.move_rel(dy)
else: else:
dx = np.cos(omega * np.pi / 180) * (x - bx) / ppm dx = np.cos(omega * np.pi / 180) * (x - bx) / ppm
dy = -(y - by) / ppm dy = -(y - by) / ppm
_log.info("moving fast x/y to {:.3f}, {:.3f}".format(dx, dy)) _log.info("moving fast x/y to {:.3f}, {:.3f}".format(dx, dy))
fx_motor.move_relative(dx) fx_motor.move_rel(dx)
fy_motor.move_relative(dy) fy_motor.move_rel(dy)
self.fast_dx_position.emit(dx) self.fast_dx_position.emit(dx)
self.fast_dy_position.emit(dy) self.fast_dy_position.emit(dy)
return return
@@ -1134,7 +1170,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
if ctrl and not (shft or alt): if ctrl and not (shft or alt):
mm = np.sign(y - by) * pixel_dist / 10000. mm = np.sign(y - by) * pixel_dist / 10000.
_log.debug("moving Z stage by {:.3f} mm".format(mm)) _log.debug("moving Z stage by {:.3f} mm".format(mm))
bz_motor.move_relative(mm) bz_motor.move_rel(mm)
return return
if task in (TASK_SETUP_PPM_CALIBRATION, TASK_SETUP_BEAM_CENTER): if task in (TASK_SETUP_PPM_CALIBRATION, TASK_SETUP_BEAM_CENTER):
@@ -1335,30 +1371,36 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
except AttributeError as e: except AttributeError as e:
_log.warning(f'no scan parameters for object->skipped:{go}') _log.warning(f'no scan parameters for object->skipped:{go}')
continue continue
# names consists of abrevations
# part 0: po=position dt=delta
# part 1: px=pixel eu=engineering units (e.g. mm)
po_px=go.pos()
dt_px=-opt_ctr-po_px
po_eu=geo.pix2pos(dt_px)+(fx,fy) # position of the 0/0 poit of the ROI in engineering units
p=param['points'] p=param['points']
trf=np.asmatrix(param['trf']*1000) #fix shear/rotation um->um
pos=np.array(param['grid']['pos']) #in um pos=np.array(param['grid']['pos']) #in um
pitch=np.array(param['grid']['pitch']) #in um pitch=np.array(param['grid']['pitch']) #in um
trf=param['trf'] #fix shear/rotation um->um
trf=np.asmatrix(np.diag(pitch))*np.asmatrix(trf)*geo._pix2pos
po_eu*=1000 #mm to um
trf*=1000 #mm to um
#pix2pos: return np.asarray(self._pix2pos*np.mat(p).T).ravel()
for i in range(p.shape[0]):
p[i,:]=po_eu+(trf*np.asmatrix(p[i,:]).T).A.ravel() #t=np.matrix((0,0,1)).T
#for i in range(p.shape[0]):
# t.A[:2,0]=pos+p[i,:]*pitch
# p[i,:]=(trf*t).A.ravel()
# Same but much faster !
m=np.hstack((p*pitch+pos,np.ones((p.shape[0],1))))
p=(trf*np.asmatrix(m).T).T.A
# add up to 100 test fiducial
grp=self._goTracked
mft=self._moduleFixTarget
n=int(p.shape[0]/100)+1
for i in range(0,p.shape[0],n):
fx,fy=p[i, :]/1000
l=.06
go=UsrGO.Fiducial((fx-l/2, fy-l/2), (l, l), i)
grp.addItem(go)
mft._tree.setData(grp.childItems())
print('DEBUG: first point:') print('DEBUG: first point:')
print(p[0,:]) print(p[0,:])
print('DEBUG: difference from point to point:') print('DEBUG: difference from point to point:')
print(np.diff(p, axis=0)) print(np.diff(p, axis=0))
self.daq_collect(**param) #self.daq_collect(**param)
elif task == TASK_GRID: elif task == TASK_GRID:
self.re_connect_collect_button( self.re_connect_collect_button(
@@ -1623,7 +1665,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
<li>for each zoom level: <li>for each zoom level:
<li>choose a good fiducial mark <li>choose a good fiducial mark
<li>move the stage x/y at min. 3 different locations <li>move the stage x/y at min. 3 different locations
<li>CTRL-Click (left mouse button) on the fiducial mark <li>Click (left mouse button) on the fiducial mark
<li>un-click: <b>pix2pos</b></li> <li>un-click: <b>pix2pos</b></li>
</ol> </ol>
<h2>optical center calibration</h2> <h2>optical center calibration</h2>
@@ -1631,7 +1673,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
<li>press: <b>opt_ctr</b></li> <li>press: <b>opt_ctr</b></li>
<li>choose at least 3 fiducial mark visible at various zoom levels <li>choose at least 3 fiducial mark visible at various zoom levels
<li>for at least two zoom level: <li>for at least two zoom level:
<li>CTRL-Click (left mouse button) on the fiducial marks <li>Click (left mouse button) on the fiducial marks
<li>un-click: <b>opt_ctr</b></li> <li>un-click: <b>opt_ctr</b></li>
</ol> </ol>
</body> </body>
@@ -1722,7 +1764,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
res=QMessageBox.question(self, "calibration", f"use calibration\n{s} ? ") res=QMessageBox.question(self, "calibration", f"use calibration\n{s} ? ")
if res==QMessageBox.Yes: if res==QMessageBox.Yes:
geo=app._geometry geo=app._geometry
geo.cb_update_pix2pos(app._raw_pix2pos) geo.update_pix2pos(app._raw_pix2pos)
app._cfg.setValue(AppCfg.GEO_PIX2POS, geo._lut_pix2pos) app._cfg.setValue(AppCfg.GEO_PIX2POS, geo._lut_pix2pos)
del app._raw_pix2pos del app._raw_pix2pos
@@ -1766,7 +1808,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
if idx==0: if idx==0:
#go=UsrGO.Fiducial(bm_pos+bm_sz/2-(20, 20), (40, 40),(fx,fy,bz)) #go=UsrGO.Fiducial(bm_pos+bm_sz/2-(20, 20), (40, 40),(fx,fy,bz))
l=.120 l=.120
go=UsrGO.Fiducial((fx-l/2,fy-l/2), (l, l),(fx,fy,bz)) go=UsrGO.Fiducial((fx-l/2,fy-l/2), (l, l),bz)
elif idx==1: elif idx==1:
v=geo.pos2pix((12.5, 0)) v=geo.pos2pix((12.5, 0))
l=np.linalg.norm(v) l=np.linalg.norm(v)
@@ -1834,7 +1876,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
j=0 j=0
elif type(go)==UsrGO.Fiducial: elif type(go)==UsrGO.Fiducial:
ptFitTrf[j]=go.pos()+go.size()/2 ptFitTrf[j]=go.pos()+go.size()/2
ptFitPlane[i]=go._xyz ptFitPlane[i]=go.ctr()
i+=1;j+=1 i+=1;j+=1
app=QApplication.instance() app=QApplication.instance()
geo=app._geometry geo=app._geometry
@@ -2366,33 +2408,6 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
self._mouse_tracking = False self._mouse_tracking = False
self._lb_coords.setText("") 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): def _OLD_get_beam_mark_on_camera_xy(self):
app=QApplication.instance() app=QApplication.instance()
z = app._zoom.get_val() z = app._zoom.get_val()
@@ -2580,14 +2595,14 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
_log.info("moving collimator {} to X,Y = {:.3f}, {:.3f}".format(pos, x_pos, y_pos)) _log.info("moving collimator {} to X,Y = {:.3f}, {:.3f}".format(pos, x_pos, y_pos))
if pos == "out": if pos == "out":
cy.move_motor_to_position(y_pos + dy, assert_position=True) cy.move_abs(y_pos+dy, assert_position=True)
cx.move_motor_to_position(x_pos + dx, assert_position=True) cx.move_abs(x_pos+dx, assert_position=True)
elif pos == "in": elif pos == "in":
cx.move_motor_to_position(x_pos, assert_position=True) cx.move_abs(x_pos, assert_position=True)
cy.move_motor_to_position(y_pos, assert_position=True) cy.move_abs(y_pos, assert_position=True)
elif pos == "ready": elif pos == "ready":
cx.move_motor_to_position(x_pos, assert_position=True) cx.move_abs(x_pos, assert_position=True)
cy.move_motor_to_position(y_pos + dy, assert_position=True) cy.move_abs(y_pos+dy, assert_position=True)
else: else:
raise UnknownLabeledPosition("Collimator position *{}* is not known!!") raise UnknownLabeledPosition("Collimator position *{}* is not known!!")
@@ -2601,7 +2616,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
to_pos = settings.value(key, 1e10, type=float) to_pos = settings.value(key, 1e10, type=float)
if to_pos > 1e9: if to_pos > 1e9:
raise IncompleteConfiguration(f"CRYOJET configuration is incomplete! Missing {key}") raise IncompleteConfiguration(f"CRYOJET configuration is incomplete! Missing {key}")
cx.move_motor_to_position(to_pos, assert_position=True) cx.move_abs(to_pos, assert_position=True)
def _OLD_build_cryo_group(self, toolbox): def _OLD_build_cryo_group(self, toolbox):
qutilities.add_item_to_toolbox( qutilities.add_item_to_toolbox(
@@ -2706,10 +2721,10 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
if dir == "in": if dir == "in":
_log.info("move post sample tube in") _log.info("move post sample tube in")
usy.move_motor_to_position(y_up) usy.move_abs(y_up)
dsy.move_motor_to_position(y_down) dsy.move_abs(y_down)
usx.move_motor_to_position(x_up) usx.move_abs(x_up)
dsx.move_motor_to_position(x_down) dsx.move_abs(x_down)
try: try:
app_utils.assert_tweaker_positions([ app_utils.assert_tweaker_positions([
(usy, y_up, 0.1), (usy, y_up, 0.1),
@@ -2722,7 +2737,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
_log.warning(e) _log.warning(e)
QMessageBox.warning(self, "failed to move post sample tube XY {in}", "failed to move post sample tube XY {in}",) QMessageBox.warning(self, "failed to move post sample tube XY {in}", "failed to move post sample tube XY {in}",)
raise raise
tube_z.move_motor_to_position(tz_in, wait=True) tube_z.move_abs(tz_in, wait=True)
try: try:
app_utils.assert_tweaker_positions([(tube_z, tz_in, 0.1)]) app_utils.assert_tweaker_positions([(tube_z, tz_in, 0.1)])
except app_utils.PositionsNotReached as e: except app_utils.PositionsNotReached as e:
@@ -2733,7 +2748,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
elif dir == "out": elif dir == "out":
_log.info("move post sample tube out") _log.info("move post sample tube out")
tube_z.move_motor_to_position(tz_out, wait=True) tube_z.move_abs(tz_out, wait=True)
try: try:
app_utils.assert_tweaker_positions([(tube_z, tz_out, 0.1)]) app_utils.assert_tweaker_positions([(tube_z, tz_out, 0.1)])
except app_utils.PositionsNotReached as e: except app_utils.PositionsNotReached as e:
@@ -2741,10 +2756,10 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
_log.warning(e) _log.warning(e)
QMessageBox.warning(self,"failed to move post sample tube Z {out}","failed to move post sample tube Z {out}",) QMessageBox.warning(self,"failed to move post sample tube Z {out}","failed to move post sample tube Z {out}",)
raise raise
usy.move_motor_to_position(y_up + dy) usy.move_abs(y_up+dy)
dsy.move_motor_to_position(y_down + dy) dsy.move_abs(y_down+dy)
usx.move_motor_to_position(x_up + dx) usx.move_abs(x_up+dx)
dsx.move_motor_to_position(x_down + dx) dsx.move_abs(x_down+dx)
try: try:
app_utils.assert_tweaker_positions([ app_utils.assert_tweaker_positions([
(usy, y_up + dy, 0.1), (usy, y_up + dy, 0.1),
@@ -2759,20 +2774,20 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
raise raise
elif dir == "x-pos": elif dir == "x-pos":
_log.info("tamdem move post sample tube X-pos by {} mm".format(tandem_twv)) _log.info("tamdem move post sample tube X-pos by {} mm".format(tandem_twv))
usx.move_relative(tandem_twv) usx.move_rel(tandem_twv)
dsx.move_relative(tandem_twv) dsx.move_rel(tandem_twv)
elif dir == "x-neg": elif dir == "x-neg":
_log.info("tamdem move post sample tube X-neg {} mm".format(tandem_twv)) _log.info("tamdem move post sample tube X-neg {} mm".format(tandem_twv))
usx.move_relative(-tandem_twv) usx.move_rel(-tandem_twv)
dsx.move_relative(-tandem_twv) dsx.move_rel(-tandem_twv)
elif dir == "up": elif dir == "up":
_log.info("tamdem move post sample tube UP {} mm".format(tandem_twv)) _log.info("tamdem move post sample tube UP {} mm".format(tandem_twv))
usy.move_relative(tandem_twv) usy.move_rel(tandem_twv)
dsy.move_relative(tandem_twv) dsy.move_rel(tandem_twv)
elif dir == "down": elif dir == "down":
_log.info("tamdem move post sample tube DOWN {} mm".format(tandem_twv)) _log.info("tamdem move post sample tube DOWN {} mm".format(tandem_twv))
usy.move_relative(-tandem_twv) usy.move_rel(-tandem_twv)
dsy.move_relative(-tandem_twv) dsy.move_rel(-tandem_twv)
def _OLD_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: if layout is None:
@@ -3520,8 +3535,8 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
def _OLD_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") _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, fy_motor, bx_motor, bz_motor, omega_motor = self.get_gonio_tweakers()
fx_motor.move_motor_to_position(x) fx_motor.move_abs(x)
fy_motor.move_motor_to_position(y) fy_motor.move_abs(y)
def _OLD_toggle_maximized(self): def _OLD_toggle_maximized(self):
if self.isMaximized(): if self.isMaximized():
@@ -3657,6 +3672,7 @@ if __name__=="__main__":
app._geometry=geometry.geometry() app._geometry=geometry.geometry()
app._geometry._lut_pix2pos=cfg.value(cfg.GEO_PIX2POS) app._geometry._lut_pix2pos=cfg.value(cfg.GEO_PIX2POS)
app._geometry._opt_ctr=cfg.value(cfg.GEO_OPT_CTR) app._geometry._opt_ctr=cfg.value(cfg.GEO_OPT_CTR)
startupWin.set(15, f'connect backlight') startupWin.set(15, f'connect backlight')