Files
x11ma/script/templates/FocusScan.py
2021-12-14 14:25:13 +01:00

200 lines
7.0 KiB
Python

SETTLING_TIME =0.5
MAX_CONTRAST = 10e14
MAX_SHIFT = 300
import java.awt.Rectangle as Rectangle
class RoiContrast(ReadonlyRegisterBase):
def doRead(self):
if hasattr(self, "roi"):
return image.getData().getGradientVariance(False, self.roi)
return 0.0
def getName(self):
return "roi_contrast"
def set_roi(self, roi):
self.roi=roi
if get_device("image_contrast") is None:
add_device(image.getContrast(), False)
if get_device("roi_contrast") is None:
add_device(RoiContrast(), False)
def get_focus_scan_pos():
return objective.read(),obj_stig_a.read(),obj_stig_b.read()
def apply_focus_scan_pos(pos):
objective.write(pos[0])
obj_stig_a.write(pos[1])
obj_stig_b.write(pos[2])
focus_scan_roi=None
focus_scan_renderer=None
def show_focus_scan_roi():
global focus_scan_roi, focus_scan_renderer
if focus_scan_renderer is None:
pn=show_panel(image)
ov=Overlays.Rect(Pen(Color.BLUE), Point(focus_scan_roi.x,focus_scan_roi.y),Dimension(focus_scan_roi.width,focus_scan_roi.height))
pn.clearOverlays()
#ov.setMovable(True)
pn.addOverlay(ov)
else:
pn = focus_scan_renderer
if len(pn.overlays)==0:
pn.addOverlay(Overlays.Rect(pn.getPenProfile()))
pn.overlays[0].setMovable(True)
ov=pn.overlays[0]
ov.update(Point(focus_scan_roi.x,focus_scan_roi.y),Dimension(focus_scan_roi.width,focus_scan_roi.height))
pn.refresh()
def set_focus_scan_roi(roi, renderer=None):
global focus_scan_roi, focus_scan_renderer
focus_scan_renderer = renderer
focus_scan_roi = roi
show_focus_scan_roi()
def get_focus_scan_roi():
return focus_scan_roi
def scan_contrast(positioner, pos_range, pos_step, roi = None, average = 1, update_position = True):
def after_read(rec):
if rec[positioner] > MAX_CONTRAST:
print "Invalid contrast value"
time.sleep(eiger.exposure)
rec.invalidate()
def before_pass(scan, num_pass):
print "Waiting to reach scan init pos"
time.sleep(1.0)
cur = positioner.read()
if (cur < positioner.minValue+pos_range) or (cur > positioner.maxValue-pos_range):
raise Exception("Cannot perform contrast scan: " + positioner.name + " too close to limit")
if roi is None:
sensor = image_contrast
else:
sensor = roi_contrast
roi_contrast.set_roi(roi)
if average > 1:
sensor = create_averager(sensor, average, interval = eiger.exposure, name = image_contrast.name, monitored = False)
r = lscan( positioner, [sensor,], -pos_range, pos_range, pos_step, \
latency=eiger.exposure+SETTLING_TIME, relative=True, after_read=after_read, before_pass=before_pass)
ydata, xdata = r[sensor], r[positioner]
if average > 1:
ydata = [v.doubleValue() for v in ydata]
(norm, mn, std ) = fit (ydata, xdata, limit_to_range=True)
range_scan = (min(r[positioner]), max(r[positioner]))
if (mn is not None) and (range_scan[0] <= mn <= range_scan[1]):
print "Valid fit for ", positioner.name, mn
if update_position:
time.sleep(0.5) # Wait restoring positions
print "Updating position: ", positioner.name, mn
positioner.write(mn)
else:
print "Invalid fit for ", positioner.name, mn, range_scan
time.sleep(1.0) # Wait restoring positions
return r
def update_roi_pos(cur_data, former_data):
roi=get_focus_scan_roi()
calc_roi = Roi(roi.x,roi.y,roi.width, roi.height)
try:
xoff, yoff, error, diffphase = calculate_shift(former_data,cur_data, calc_roi)
print "Calculated shift: ", xoff, yoff, error, diffphase
if (0<abs(xoff) < MAX_SHIFT) and (0<abs(yoff) < MAX_SHIFT):
x,y=int(roi.x - xoff), int(roi.y - yoff)
print "Updating ROI location to ", x, y
x,y=max(x,0), max(y,0)
x,y=min(x,cur_data.width-roi.width), min(y,cur_data.height-roi.height)
roi.setLocation(x,y)
show_focus_scan_roi()
else:
print "Error - shift too big: xoff, yoff"
except:
print "Error calculating shift: " + str(sys.exc_info()[1])
former_data=None
def scan_focus(positioner, pos_range, pos_step, average = 1, update_position = True):
global former_data
roi=get_focus_scan_roi()
former_data = image.data
initial_state = get_focus_scan_pos()
initial_roi_location = roi.location if roi is not None else None
def before_read(pos,scan):
global former_data
cur_data = image.data
try:
print "----- Pos: ", pos
update_roi_pos(cur_data, former_data)
finally:
former_data = cur_data
print "New ROI pos: " , roi_contrast.roi.location
def after_read(rec, scam):
global former_data
if rec[positioner] > MAX_CONTRAST:
print "Invalid contrast value"
time.sleep(eiger.exposure)
rec.invalidate()
def before_pass(scan, num_pass):
pass
#print "Waiting to reach scan init pos"
#time.sleep(1.0)
if roi is None:
sensor = image_contrast
else:
sensor = roi_contrast
roi_contrast.set_roi(roi)
if average > 1:
sensor = create_averager(sensor, average, interval = eiger.exposure, name = image_contrast.name, monitored = False)
r = lscan( positioner, [sensor,], -pos_range, pos_range, pos_step, \
latency=eiger.exposure+SETTLING_TIME, relative=True, initial_move=False, restore_position=False, \
before_read=before_read, after_read=after_read, before_pass=before_pass)
ydata, xdata = r[sensor], r[positioner]
if average > 1:
ydata = [v.doubleValue() for v in ydata]
(norm, mn, std ) = fit (ydata, xdata, limit_to_range=True)
range_scan = (min(r[positioner]), max(r[positioner]))
if (mn is not None) and (range_scan[0] <= mn <= range_scan[1]):
print "Valid fit for ", positioner.name, mn
if update_position:
#time.sleep(1.0) # Wait restoring positions
#print "Updating position: ", positioner.name, mn
#show_message("Setting mx pos", blocking = True)
#time.sleep(3.0)
former_data = image.data
positioner.write(mn)
time.sleep(eiger.exposure+SETTLING_TIME)
#show_message("Updating ROI", blocking = True)
update_roi_pos(image.data, former_data)
else:
apply_focus_scan_pos(initial_state)
if initial_roi_location: roi.location=initial_roi_location
else:
print "Invalid fit for ", positioner.name, mn, range_scan
apply_focus_scan_pos(initial_state)
if initial_roi_location: roi.location=initial_roi_location
time.sleep(1.0) # Wait restoring positions
return r