Merge branch 'neighbour-ratio' into 'v3'
Change neighbour ratio to dx and dy See merge request openflexure/openflexure-microscope-server!371
This commit is contained in:
commit
9973221ed9
1 changed files with 31 additions and 16 deletions
|
|
@ -19,12 +19,6 @@ XYPosList: TypeAlias = list[XYPos]
|
||||||
XYZPosList: TypeAlias = list[XYZPos]
|
XYZPosList: TypeAlias = list[XYZPos]
|
||||||
|
|
||||||
|
|
||||||
# how many times the minimum distance between images to include as a "nearby" image
|
|
||||||
# default 1.4 includes images offset in x or y, but not diagonally.
|
|
||||||
# This wis based of a 4:3 aspect ratio. So x moves are 1.33 times larger than y
|
|
||||||
NEIGHBOUR_CUTOFF = 1.4
|
|
||||||
|
|
||||||
|
|
||||||
def enforce_xy_tuple(value: XYPos) -> XYPos:
|
def enforce_xy_tuple(value: XYPos) -> XYPos:
|
||||||
"""Check input is a tuple and is of length 2.
|
"""Check input is a tuple and is of length 2.
|
||||||
|
|
||||||
|
|
@ -242,18 +236,30 @@ class SmartSpiral(ScanPlanner):
|
||||||
|
|
||||||
Each time and image is taken the four neighbouring images are added
|
Each time and image is taken the four neighbouring images are added
|
||||||
to the list of positions to image (unless they are already listed or
|
to the list of positions to image (unless they are already listed or
|
||||||
tried). However, if a location is not imaged due no sample being detected
|
tried). However, if a location is not imaged due no sample being detected,
|
||||||
then neibouring positions are not imaged.
|
then neighbouring positions are not imaged.
|
||||||
|
|
||||||
The next image taken is the closes to the centre (considering the largest
|
The next image taken is the fewest scan sites (moves in dx and dy) from the current
|
||||||
of vertical or horizontal distance), ties are broken by the distance from
|
site, with ties broken by minimising the moves away from the start of the scan.
|
||||||
the current position.
|
Final tiebreak is the distance to each site, in motor steps rather than multiple of
|
||||||
|
dx and dy.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_max_dist: int = 0
|
_max_dist: int = 0
|
||||||
_dx: int = 0
|
_dx: int = 0
|
||||||
_dy: int = 0
|
_dy: int = 0
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, initial_position: XYPos, planner_settings: Optional[dict] = None
|
||||||
|
) -> None:
|
||||||
|
"""Set up the lists inherited from ScanPlanner, plus a distance cutoff.
|
||||||
|
|
||||||
|
Use the supplied _dx and _dy to set a distance cutoff for an image to be
|
||||||
|
considered neighbouring another
|
||||||
|
"""
|
||||||
|
super().__init__(initial_position, planner_settings)
|
||||||
|
self._distance_cutoff: float = max([self._dx, self._dy]) * 1.1
|
||||||
|
|
||||||
def _parse(self, planner_settings: Optional[dict] = None) -> None:
|
def _parse(self, planner_settings: Optional[dict] = None) -> None:
|
||||||
"""Parse SmartSpiral Settings dictionary.
|
"""Parse SmartSpiral Settings dictionary.
|
||||||
|
|
||||||
|
|
@ -369,10 +375,12 @@ class SmartSpiral(ScanPlanner):
|
||||||
|
|
||||||
Lowest position is best, as starting too high causes smart stacking to
|
Lowest position is best, as starting too high causes smart stacking to
|
||||||
autofocus and restart. Starting too low just requires extra movements in +z.
|
autofocus and restart. Starting too low just requires extra movements in +z.
|
||||||
Nearby is defined as within NEIGHBOUR_CUTOFF times the distance to the closest
|
Nearby is defined as within 1.1 times the larger of the x and y scan offsets.
|
||||||
neighbour.
|
|
||||||
|
|
||||||
Returns None if there if no focused locations are present
|
If no focused sites are within this range, use the height of the nearest
|
||||||
|
focused site.
|
||||||
|
|
||||||
|
Returns None if no focused locations are present
|
||||||
"""
|
"""
|
||||||
if not self._focused_locations:
|
if not self._focused_locations:
|
||||||
return None
|
return None
|
||||||
|
|
@ -385,9 +393,16 @@ class SmartSpiral(ScanPlanner):
|
||||||
# Note linalg.norm always uses float64
|
# Note linalg.norm always uses float64
|
||||||
dists = np.linalg.norm((path_pos - current_pos), axis=1)
|
dists = np.linalg.norm((path_pos - current_pos), axis=1)
|
||||||
|
|
||||||
# Get indices of all focused sites within NEIGHBOUR_CUTOFF the minimum distance.
|
# Get indices of all focused sites within distance_cutoff.
|
||||||
# Note np.where always returns a tuple of arrays, hence the trailing [0]
|
# Note np.where always returns a tuple of arrays, hence the trailing [0]
|
||||||
indices = np.where(dists <= NEIGHBOUR_CUTOFF * np.min(dists))[0]
|
indices = np.where(dists <= self._distance_cutoff)[0]
|
||||||
|
|
||||||
|
# Handle the case that no focused positions are within this range, and
|
||||||
|
# instead use the nearest focused position. This will always return a
|
||||||
|
# height, due to the check that self._focused_locations exists.
|
||||||
|
if len(indices) == 0:
|
||||||
|
distance_cutoff = min(dists)
|
||||||
|
indices = np.where(dists <= distance_cutoff)[0]
|
||||||
|
|
||||||
# Turning into an array allows slicing based on a list
|
# Turning into an array allows slicing based on a list
|
||||||
focused_locations_array = np.array(self._focused_locations)
|
focused_locations_array = np.array(self._focused_locations)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue