moving ROI with stage and zoom
This commit is contained in:
@@ -141,8 +141,8 @@ class EmblWidget(QWidget):
|
|||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
super(EmblWidget, self).__init__(parent)
|
super(EmblWidget, self).__init__(parent)
|
||||||
|
|
||||||
parent.pixelsPerMillimeter.connect(self.save_ppm)
|
#parent.pixelsPerMillimeter.connect(self.save_ppm)
|
||||||
parent.beamCameraCoordinatesChanged.connect(self.save_beam_coordinates)
|
#parent.beamCameraCoordinatesChanged.connect(self.save_beam_coordinates)
|
||||||
self.setLayout(QVBoxLayout())
|
self.setLayout(QVBoxLayout())
|
||||||
|
|
||||||
w = QWidget()
|
w = QWidget()
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ _log = logging.getLogger(__name__)
|
|||||||
#logger.setLevel(logging.INFO)
|
#logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
class SimMotor:
|
class SimMotor:
|
||||||
def __init__(self,motor_base, short_name):
|
def __init__(self,rec_name, short_name):
|
||||||
self._llm = -10
|
self._llm = -10
|
||||||
self._hlm = 10
|
self._hlm = 10
|
||||||
self._prec = 5
|
self._prec = 5
|
||||||
|
self._twv = 0.1
|
||||||
self._units = 'mm'
|
self._units = 'mm'
|
||||||
self._pos = 3.1415
|
self._pos = 3.1415
|
||||||
self._short_name=short_name
|
self._short_name=short_name
|
||||||
|
self._rec_name=rec_name
|
||||||
|
|
||||||
class SimMotorTweak(QWidget, Ui_MotorTweak):
|
class SimMotorTweak(QWidget, Ui_MotorTweak):
|
||||||
event_val = pyqtSignal(str, dict)
|
event_val = pyqtSignal(str, dict)
|
||||||
@@ -54,12 +56,9 @@ class SimMotorTweak(QWidget, Ui_MotorTweak):
|
|||||||
self._templates = {}
|
self._templates = {}
|
||||||
|
|
||||||
|
|
||||||
def connect_motor(self, motor_base, short_name=None, *args, **kwargs):
|
def connect_motor(self, rec_name, short_name=None, *args, **kwargs):
|
||||||
self.label.setToolTip('{} => {}'.format(motor_base, motor_base))
|
self.label.setToolTip('{} => {}'.format(rec_name, short_name))
|
||||||
self.motor=SimMotor(motor_base, short_name)
|
self.motor=SimMotor(rec_name, short_name)
|
||||||
|
|
||||||
twv=0.1
|
|
||||||
|
|
||||||
self.set_motor_validator()
|
self.set_motor_validator()
|
||||||
self._drive_val.setText(str(self.motor._pos))
|
self._drive_val.setText(str(self.motor._pos))
|
||||||
self._drive_val.returnPressed.connect(self.move_motor_to_position)
|
self._drive_val.returnPressed.connect(self.move_motor_to_position)
|
||||||
@@ -69,7 +68,7 @@ class SimMotorTweak(QWidget, Ui_MotorTweak):
|
|||||||
|
|
||||||
tweak_min = kwargs.get("tweak_min", 0.0001)
|
tweak_min = kwargs.get("tweak_min", 0.0001)
|
||||||
tweak_max = kwargs.get("tweak_max", 20.0)
|
tweak_max = kwargs.get("tweak_max", 20.0)
|
||||||
self._tweak_val.setText(str(twv))
|
self._tweak_val.setText(str(self.motor._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_relative(float(self._tweak_val.text())))
|
||||||
@@ -108,6 +107,7 @@ class SimMotorTweak(QWidget, Ui_MotorTweak):
|
|||||||
sleep(delay)
|
sleep(delay)
|
||||||
_log.debug('{} rel move => {}'.format(self.motor._short_name, dist))
|
_log.debug('{} rel move => {}'.format(self.motor._short_name, dist))
|
||||||
self.update_label()
|
self.update_label()
|
||||||
|
self.emit_signals(source_field='VAL')
|
||||||
|
|
||||||
def get_position(self):
|
def get_position(self):
|
||||||
return self.motor._pos
|
return self.motor._pos
|
||||||
@@ -148,23 +148,24 @@ class SimMotorTweak(QWidget, Ui_MotorTweak):
|
|||||||
_log.debug('{} abs move => {}'.format(self.motor._short_name, drive))
|
_log.debug('{} abs move => {}'.format(self.motor._short_name, drive))
|
||||||
self.motor._pos=drive
|
self.motor._pos=drive
|
||||||
self.update_label()
|
self.update_label()
|
||||||
|
self.emit_signals(source_field='VAL')
|
||||||
|
|
||||||
def emit_signals(self, **kw):
|
def emit_signals(self, **kw):
|
||||||
field = kw['source_field']
|
field = kw['source_field']
|
||||||
if field == 'VAL':
|
if field == 'VAL':
|
||||||
self.event_val.emit(self._pvname, kw)
|
self.event_val.emit(self.motor._rec_name, kw)
|
||||||
elif field == 'RBV':
|
elif field == 'RBV':
|
||||||
self.event_readback.emit(self._pvname, kw)
|
self.event_readback.emit(self.motor._rec_name, kw)
|
||||||
elif field == 'LVIO':
|
elif field == 'LVIO':
|
||||||
self.event_soft_limit.emit(self._pvname, kw)
|
self.event_soft_limit.emit(self.motor._rec_name, kw)
|
||||||
elif field == 'HLS':
|
elif field == 'HLS':
|
||||||
self.event_high_hard_limit.emit(self._pvname, kw)
|
self.event_high_hard_limit.emit(self.motor._rec_name, kw)
|
||||||
self.event_axis_fault.emit(self._pvname, kw)
|
self.event_axis_fault.emit(self.motor._rec_name, kw)
|
||||||
elif field == 'LVIO':
|
elif field == 'LVIO':
|
||||||
self.event_low_hard_limit.emit(self._pvname, kw)
|
self.event_low_hard_limit.emit(self.motor._rec_name, kw)
|
||||||
self.event_axis_fault.emit(self._pvname, kw)
|
self.event_axis_fault.emit(self.motor._rec_name, kw)
|
||||||
elif field == 'STAT':
|
elif field == 'STAT':
|
||||||
self.event_axis_fault.emit(self._pvname, kw)
|
self.event_axis_fault.emit(self.motor._rec_name, kw)
|
||||||
|
|
||||||
|
|
||||||
def set_val_on_status_change(self, **kw):
|
def set_val_on_status_change(self, **kw):
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ class geometry:
|
|||||||
pix2pos[0, 1]=np.interp(zoom, K, AA[:, 0, 1])
|
pix2pos[0, 1]=np.interp(zoom, K, AA[:, 0, 1])
|
||||||
pix2pos[1, 0]=np.interp(zoom, K, AA[:, 1, 0])
|
pix2pos[1, 0]=np.interp(zoom, K, AA[:, 1, 0])
|
||||||
pix2pos[1, 1]=np.interp(zoom, K, AA[:, 1, 1])
|
pix2pos[1, 1]=np.interp(zoom, K, AA[:, 1, 1])
|
||||||
_log.debug('interpolation array:{}'.format(tuple(pix2pos.ravel())))
|
_log.debug(f'{zoom} -> {pix2pos.ravel()}')
|
||||||
|
|
||||||
def update_pix2pos(self, meas):
|
def update_pix2pos(self, meas):
|
||||||
# calculates _lut_pix2pos out of measurements
|
# calculates _lut_pix2pos out of measurements
|
||||||
|
|||||||
106
swissmx.py
106
swissmx.py
@@ -180,19 +180,19 @@ class Sequencer(QObject):
|
|||||||
Ui_MainWindow, QMainWindow = loadUiType("swissmx.ui")
|
Ui_MainWindow, QMainWindow = loadUiType("swissmx.ui")
|
||||||
|
|
||||||
class Main(QMainWindow, Ui_MainWindow):
|
class Main(QMainWindow, Ui_MainWindow):
|
||||||
pixelsPerMillimeter = pyqtSignal(float)
|
#pixelsPerMillimeter = pyqtSignal(float)
|
||||||
beamCameraCoordinatesChanged = pyqtSignal(float, float)
|
#beamCameraCoordinatesChanged = pyqtSignal(float, float)
|
||||||
addGridRequest = pyqtSignal(float, float)
|
addGridRequest = pyqtSignal(float, float)
|
||||||
zoomChanged = pyqtSignal(float)
|
#zoomChanged = pyqtSignal(float)
|
||||||
folderChanged = pyqtSignal(str)
|
folderChanged = pyqtSignal(str)
|
||||||
prefixChanged = pyqtSignal(str)
|
prefixChanged = pyqtSignal(str)
|
||||||
projectChanged = pyqtSignal(str)
|
projectChanged = pyqtSignal(str)
|
||||||
gridUpdated = pyqtSignal(int) # index in self._grids
|
gridUpdated = pyqtSignal(int) # index in self._grids
|
||||||
gonioMoveRequest = pyqtSignal(float, float, float, float, float)
|
gonioMoveRequest = pyqtSignal(float, float, float, float, float)
|
||||||
fast_x_position = pyqtSignal(float)
|
#fast_x_position = pyqtSignal(float)
|
||||||
fast_y_position = pyqtSignal(float)
|
#fast_y_position = pyqtSignal(float)
|
||||||
fast_dx_position = pyqtSignal(float)
|
#fast_dx_position = pyqtSignal(float)
|
||||||
fast_dy_position = pyqtSignal(float)
|
#fast_dy_position = pyqtSignal(float)
|
||||||
fiducialPositionSelected = pyqtSignal(float, float, float, float) # camx, camy, gonx, gony
|
fiducialPositionSelected = pyqtSignal(float, float, float, float) # camx, camy, gonx, gony
|
||||||
appendPrelocatedPosition = pyqtSignal(float, float, float, float)
|
appendPrelocatedPosition = pyqtSignal(float, float, float, float)
|
||||||
appendPrelocatedFiducial = pyqtSignal(bool, float, float, float, float)
|
appendPrelocatedFiducial = pyqtSignal(bool, float, float, float, float)
|
||||||
@@ -346,18 +346,21 @@ class Main(QMainWindow, Ui_MainWindow):
|
|||||||
#--- beam marker ---
|
#--- beam marker ---
|
||||||
bm_sz=np.array((50, 40)) # it is immidiatly repositioned in zoom_changed_cb
|
bm_sz=np.array((50, 40)) # it is immidiatly repositioned in zoom_changed_cb
|
||||||
self._goBeamMarker=bm=UsrGO.Marker(-opt_ctr-bm_sz/2,bm_sz,mode=0)
|
self._goBeamMarker=bm=UsrGO.Marker(-opt_ctr-bm_sz/2,bm_sz,mode=0)
|
||||||
self.vb.addItem(bm)
|
vb.addItem(bm)
|
||||||
|
|
||||||
#--- opctical center ----
|
#--- opctical center ----
|
||||||
oc_sz=np.array((50,50))
|
oc_sz=np.array((50,50))
|
||||||
self._goOptCtr=obj=UsrGO.Marker(-opt_ctr-oc_sz/2, oc_sz,mode=1)
|
self._goOptCtr=obj=UsrGO.Marker(-opt_ctr-oc_sz/2, oc_sz,mode=1)
|
||||||
bm.setTransform(tr) # assign transform
|
bm.setTransform(tr) # assign transform
|
||||||
self.vb.addItem(obj)
|
vb.addItem(obj)
|
||||||
|
|
||||||
#--- testing scan grid ---
|
#--- testing scan grid ---
|
||||||
vi=UsrGO.Grid((120, -100), (200, 150), (30, 22), 2)
|
self.track_objects() # first call is needed to initialize the structure self._goTracked
|
||||||
vi.setTransform(tr) # assign transform
|
go=UsrGO.Grid((120, -100), (200, 150), (30, 22), 2)
|
||||||
self.vb.addItem(vi)
|
go.setTransform(tr) # assign transform
|
||||||
|
vb.addItem(go)
|
||||||
|
self._goTracked['objLst'].append(go)
|
||||||
|
self.track_objects() #tracking now the objects
|
||||||
#UsrGO.obj_tree(vb)
|
#UsrGO.obj_tree(vb)
|
||||||
|
|
||||||
|
|
||||||
@@ -1037,7 +1040,7 @@ class Main(QMainWindow, Ui_MainWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def zoom_changed_cb(self, value):
|
def zoom_changed_cb(self, value):
|
||||||
self.zoomChanged.emit(value)
|
#self.zoomChanged.emit(value)
|
||||||
app=QApplication.instance()
|
app=QApplication.instance()
|
||||||
cfg=app._cfg
|
cfg=app._cfg
|
||||||
geo=app._geometry
|
geo=app._geometry
|
||||||
@@ -1055,8 +1058,73 @@ class Main(QMainWindow, Ui_MainWindow):
|
|||||||
bm.setPos(bm_pos,finish=False)
|
bm.setPos(bm_pos,finish=False)
|
||||||
bm.setSize(bm_sz)
|
bm.setSize(bm_sz)
|
||||||
_log.debug(f"zoom->{value} beam marker pos:{bm_pos} sz:{bm_sz})")
|
_log.debug(f"zoom->{value} beam marker pos:{bm_pos} sz:{bm_sz})")
|
||||||
|
self.track_objects()
|
||||||
#self.update_beam_marker(value)
|
#self.update_beam_marker(value)
|
||||||
|
|
||||||
|
def track_objects(self):
|
||||||
|
#self._goTracked= dictionary with infos about tracked objects
|
||||||
|
# objLst = list of objects to track
|
||||||
|
# state = (zoom, fx, fy) (created at first call of self.track_objects() )
|
||||||
|
app=QApplication.instance()
|
||||||
|
geo=app._geometry
|
||||||
|
zoom = app._zoom.get()
|
||||||
|
fast_x=self.tweakers["fast_x"];fast_y=self.tweakers["fast_y"]
|
||||||
|
fx=fast_x.get_position()
|
||||||
|
fy=fast_y.get_position()
|
||||||
|
try:
|
||||||
|
tracked=self._goTracked
|
||||||
|
zoom_old,fx_old,fy_old=tracked['state']
|
||||||
|
except AttributeError: # at initialization
|
||||||
|
self._goTracked={'objLst':list(), 'state':(zoom,fx,fy)}
|
||||||
|
return
|
||||||
|
_log.debug(f"zoom:{zoom_old}->{zoom} fx:{fx_old}->{fx} fy:{fy_old}->{fy}")
|
||||||
|
opt_ctr=geo._opt_ctr
|
||||||
|
if zoom_old!=zoom:
|
||||||
|
geo.interp_zoom(zoom_old)
|
||||||
|
pix2pos_old=geo._pix2pos
|
||||||
|
geo.interp_zoom(zoom)
|
||||||
|
pix2pos_new=geo._pix2pos
|
||||||
|
for o in tracked['objLst']:
|
||||||
|
# names consists of abrevations
|
||||||
|
# part 0: po=position sz=size dt=delta
|
||||||
|
# part 1: px=pixel eu=engineering units (e.g. mm)
|
||||||
|
po_px=o.pos()
|
||||||
|
sz_px=o.size()
|
||||||
|
tr=o.transform()
|
||||||
|
geo._pix2pos=pix2pos_old
|
||||||
|
dt_px=-opt_ctr-po_px
|
||||||
|
dt_eu=geo.pix2pos(dt_px)
|
||||||
|
sz_eu=geo.pix2pos(sz_px)
|
||||||
|
|
||||||
|
geo._pix2pos=pix2pos_new
|
||||||
|
dt_px2=geo.pos2pix(dt_eu)
|
||||||
|
sz_px2=geo.pos2pix(sz_eu)
|
||||||
|
po_px2=-opt_ctr-dt_px2
|
||||||
|
o.setPos(po_px2)
|
||||||
|
o.setSize(sz_px2)
|
||||||
|
|
||||||
|
#np.asarray(self._pix2pos*np.mat(p).T).ravel()
|
||||||
|
geo.interp_zoom(zoom)
|
||||||
|
|
||||||
|
if fx_old!=fx or fy_old!=fy:
|
||||||
|
p1=geo.pos2pix((fx_old,fy_old))
|
||||||
|
p2=geo.pos2pix((fx,fy))
|
||||||
|
d=p2-p1
|
||||||
|
|
||||||
|
for o in tracked['objLst']:
|
||||||
|
pos=o.pos()
|
||||||
|
sz=o.size()
|
||||||
|
tr=o.transform()
|
||||||
|
o.setPos(pos+d)
|
||||||
|
tracked['state']=(zoom, fx, fy)
|
||||||
|
#imgPos=self._goImg.mapFromScene(event.scenePos())
|
||||||
|
#x=imgPos.x();y=imgPos.y()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def append_to_beam_markers(self, x, y, zoom):
|
def append_to_beam_markers(self, x, y, zoom):
|
||||||
self._beam_markers[zoom] = (x, y)
|
self._beam_markers[zoom] = (x, y)
|
||||||
_log.info("beam markers {}".format(self._beam_markers))
|
_log.info("beam markers {}".format(self._beam_markers))
|
||||||
@@ -1195,7 +1263,7 @@ class Main(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)
|
#geo.interp_zoom(1)
|
||||||
bm=self._goBeamMarker
|
bm=self._goBeamMarker
|
||||||
p1=self._goImg.mapFromScene(pos)
|
p1=self._goImg.mapFromScene(pos)
|
||||||
p2=bm.pos()+bm.size()/2
|
p2=bm.pos()+bm.size()/2
|
||||||
@@ -1657,9 +1725,11 @@ class Main(QMainWindow, Ui_MainWindow):
|
|||||||
for key, tweaker in self.tweakers.items():
|
for key, tweaker in self.tweakers.items():
|
||||||
tweaker.event_axis_fault.connect(self.axis_fault)
|
tweaker.event_axis_fault.connect(self.axis_fault)
|
||||||
|
|
||||||
self.tweakers["fast_x"].event_readback.connect(lambda alias, value, kw: self.fast_x_position.emit(value))
|
#self.tweakers["fast_x"].event_readback.connect(lambda alias, value, kw: self.fast_x_position.emit(value))
|
||||||
self.tweakers["fast_y"].event_readback.connect(lambda alias, value, kw: self.fast_y_position.emit(value))
|
#self.tweakers["fast_y"].event_readback.connect(lambda alias, value, kw: self.fast_y_position.emit(value))
|
||||||
|
|
||||||
|
self.tweakers["fast_x"].event_val.connect(lambda rec_name, kw: self.track_objects())
|
||||||
|
self.tweakers["fast_y"].event_val.connect(lambda rec_name, kw: self.track_objects())
|
||||||
# layout.addStretch()
|
# layout.addStretch()
|
||||||
|
|
||||||
def axis_fault(self, pvname, kw):
|
def axis_fault(self, pvname, kw):
|
||||||
@@ -1968,7 +2038,7 @@ class Main(QMainWindow, Ui_MainWindow):
|
|||||||
usy.move_relative(-tandem_twv)
|
usy.move_relative(-tandem_twv)
|
||||||
dsy.move_relative(-tandem_twv)
|
dsy.move_relative(-tandem_twv)
|
||||||
|
|
||||||
def get_tweaker(self, pv, alias=None, label=None, mtype="epics_motor", layout=None, **kwargs):
|
def get_tweaker(self, rec, alias=None, label=None, mtype="epics_motor", layout=None, **kwargs):
|
||||||
app = QApplication.instance()
|
app = QApplication.instance()
|
||||||
sim=app._args.sim
|
sim=app._args.sim
|
||||||
if mtype == "epics_motor":
|
if mtype == "epics_motor":
|
||||||
@@ -1981,7 +2051,7 @@ class Main(QMainWindow, Ui_MainWindow):
|
|||||||
m=SimMotorTweak()
|
m=SimMotorTweak()
|
||||||
else:
|
else:
|
||||||
m = SmaractMotorTweak()
|
m = SmaractMotorTweak()
|
||||||
m.connect_motor(pv, label, **kwargs)
|
m.connect_motor(rec, label, **kwargs)
|
||||||
self.tweakers[alias] = m
|
self.tweakers[alias] = m
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user