I have:
* Moved the autofocus and focus-prediction code into a
new `FocusManager` class. This hopefully keeps the logic relating to
axial motion in one place.
* Moved set-up code relating to autofocus and background detection
into separate functions.
* Changed the scan path from a ragged list-of-lists to a one dimensional
list. I've left the old 2D function and added a new 1D function that
calls it and coverts, so it's not a breaking change.
The actual sequence of moves executed, and the accompanying logic, is
unchanged from the previous commit. I've tested this a couple of times,
on my microscope with actual hardware.
I don't think it's necessary to test more widely as this is only a
refactoring change, not an algorithm change.
The shift from 2D to 1D scan path was one I initially decided against,
because I was trying to keep the new code as small as possible, and
avoid refactoring what's already there. Since I'm doing that anyway,
I have taken the opportunity to eliminate the concept of scan
"lines".
The old behaviour was to always use the position of the last point
as the starting point for the next autofocus. There was an exception
to this for raster scans, where the big jump used the first point
of the last line instead. The new behaviour always uses the closest
point, which reproduces this behaviour without the need for a hard
coded exception.
If the "fast" scan axis (y) has a longer step size than the "slow"
scan axis (x), we may base the autofocus off the previous row, rather
than the previous point in the current row. I don't see that this
should be any less reliable than the current behaviour, and is
arguably better. It's also unlikely to be noticed, because our
default scan settings have longer spacing in X. I think the
reduced complexity of the code is definitely worth the small
chance of changing some edge-case behaviour.