212 lines
7.5 KiB
Python
212 lines
7.5 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):
|
|
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)
|
|
|
|
|
|
def after_read(rec):
|
|
if rec[sensor] > 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")
|
|
|
|
|
|
|
|
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(SETTLING_TIME) # Wait restoring positions
|
|
return r
|
|
|
|
|
|
def update_roi_pos(cur_data, former_data):
|
|
try:
|
|
roi=get_focus_scan_roi()
|
|
calc_roi = Roi(roi.x,roi.y,roi.width, roi.height)
|
|
xoff, yoff, error, diffphase, _ = calculate_shift(former_data,cur_data, calc_roi)
|
|
print "Calculated shift: ", xoff, yoff, error, diffphase,
|
|
if (abs(xoff) <= MAX_SHIFT) and (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, save_images=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
|
|
|
|
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)
|
|
|
|
|
|
def before_read(pos,scan):
|
|
global former_data
|
|
if str(eiger.grabMode)=="Single":
|
|
eiger.start()
|
|
else:
|
|
time.sleep(eiger.exposure)
|
|
image.waitNext(20000)
|
|
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, scan):
|
|
global former_data
|
|
if rec[sensor] > MAX_CONTRAST:
|
|
print "Invalid contrast value"
|
|
time.sleep(eiger.exposure)
|
|
rec.invalidate()
|
|
else:
|
|
if (save_images):
|
|
filename = get_exec_pars().path + "/images/" + str(rec.index) + ".tif"
|
|
meta={positioner.name:rec[positioner], "contrast": rec[sensor]}
|
|
save_as_tiff(former_data, filename, check=True, parallel=True, metadata=meta)
|
|
|
|
|
|
def before_pass(scan, num_pass):
|
|
pass
|
|
#print "Waiting to reach scan init pos"
|
|
#time.sleep(1.0)
|
|
|
|
|
|
r = lscan( positioner, [sensor,], -pos_range, pos_range, pos_step, \
|
|
latency=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(0.) # Wait restoring positions
|
|
return r
|