I'm now running stitching in subprocesses during the scan.
This seems to be working well - I'm using multiple CPU
cores and getting images out. However, the only way to
avoid circular dependencies was to combine the Things.
I'm still getting not-infrequent memory allocation errors from the camera, which may or may not be related.
To save some CPU cycles, we will return immediately if the
images don't look newer than the stitch. NB this does mean
that the stitched image will be repeatedly transferred, as its
URL will change each time it's re-requested.
Alternatively, we could fail with an error, which may be more efficient, at the expense of being uglier.
NB there's a confusing feature, where stage.move will
fail after the task has been cancelled, because it is cancellable.
For now, we can work around it by passing `block_cancellation` but
this may want to be solved more generally in LabThings
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.
This may not be in the codebase forever, but it's a very useful
sanity check to have during development.
The current implementation is clearly not a performance or
security risk.
`logging.basicConfig` doesn't work when run via `uvicorn`.
I now explicitly get the root logger and set its level to INFO,
which means we now see logs on the terminal.
Retrieving metadata pre-action risks stale metadata being
returned if DirectThingClients are used. I've switched to
the safer callable dependency, which is guaranteed to be fresh.
Connect looks for /routes and /api/v2/streams/snapshot
These are now present and working.
I've also hard coded the static files directory - fixing this
properly is a work in progress.
Previously, we raised an exception (and thus HTTP error
code) if the CSM matrix was requested and not yet set.
Now, we just return None, and I've added a (not-network-exposed)
function that will raise an HTTPException if it's missing.
It's helpful to raise an exception if we access the calibration
before it's been set - but thing state should not raise exceptions,
just return an empty dict if the data is not there yet.