The Stage is now implemented as a runtime-checkable Protocol.
Part of this led to the realisation that we can't create a DirectThingClient
based on a Protocol, only on a concrete Thing. While it might be
a good idea to address that in LabThings in due course, for now
we work around it by creating both a Protocol and a stub class. The stub class implements the protocol, and
can be used to declare a dependency.
I've now split the base camera code into a runtime-checkable Protocol
and a concrete base class (which is optional). This removes the requirement
for cameras to subclass `openflexure_microscope.things.camera.Camera`
and instead uses duck typing that should
work both statically and dynamically.
As part of this, I've moved the commonly-used dependencies
on the camera inside `openflexure_microscope.things.camera` for consistency, and to make it easy to update them if it changes in the future.
I've now defined parent classes for camera and stage, and depend only on those. This allows
proper typing while enabling the actual hardware
classes to be swapped.
The interfaces definitely aren't final - this is a first
draft, largely to enable me to test out the concept
of a configuration server.
Removed maximum scan size of 750 images
Save json of scan inputs and use it for future stitching (ensures consistent parameters)
Moved looping autofocus to autofocus thing from recentering thing
Rewrote looping autofocus to skip unneeded moves, as if peak is out of range, no need to nicely focus
Autofocus timing is pretty critical. I've introduced the ability
to abort moves, which introduces ~50ms timing jitter. This
commit reverts the tming-critical move in autofocus to the old behaviour.
I've only reverted the move that really matters - this means
that if you start a massive sweep by accident, you can still
abort it when it's moving down to the start of the sweep.
Currently only has fast_autofocus, and there
may be some work to do on timing, but it works :)
Getting timestamps from the camera rather than
time.time() would be ideal, but it would take some thought to tie that up with
the encoder.
I'm using a low-res stream, as it seems impossible to
turn the bitrate control of the MJPEG stream off,
at least within the picamera2 API.