A side effect of re-locking dependencies is having a newer marshmallow.
This deprecates having `description=` as a keyword, and puts it in a
separate metadata arg instead.
This commit is the start of my search-and-replaceing to update to the new
format.
The update to pylint means we were failing because open()
doesn't specify the encoding everywhere. I have now specified utf-8
everywhere. This was patchy before, and is default behaviour on the
Pi. There's a slim chance it will cause some issues on Windows, but
that shouldn't affect anyone outside the developers.
I've also ignored a couple of new spurious warnings, and explicitly
ignored some unused variables.
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.
The primary change here is that there's now an option
to skip autofocus if the background detect plugin says
the current image is background.
I have also overhauled the way it picks the next Z position
based on Joe's code; instead of just using the last point, it will
pick the closest point where we have a successful autofocus
recorded. This will usually be the last point, except for raster
scans where it neatly reproduces the behaviour of the old code
but without needing to treat it as a special case (when we jump
back to the start of a line, it will use the z position of the start
of the previous line, rather than the end of the previous line).
This does represent a minor change to previous behaviour, but
it should not break anything that isn't already broken, i.e. it might
cause slightly odd behaviour if autofocus gives random results -
but probably indistinguishable from the current behaviour.
The action wrapper was using an unbound function - it
now passes the extension object as self.
We were incorrectly passing endpoint names as positional arguments -
this is fixed and I now use a keyword argument.
The code checks for the camera-stage mapper matrix by looking at its truth value.
However, this is ambiguous because the matrix has many elements. That means that
if it's missing, we get the expected result, but if it's present
we get an error.
I have avoided dict.get() and instead look it up with [] notation.
This will raise a KeyError if it's missing, which I
handle helpfully.
If the key is present but the value is not castable to an array, we'll
get an exception anyway.
adjust_shutter_and_gain_from_raw now uses a simpler algorithm.
The code is longer overall but hides some details in fuctions.
I've also split the loop into one for shutter speed and one for gain.
This isn't the algorithm that I originally wrote, but it seems to
work and is more readable.
I don't know why these didn't fail before - possibly because of
incomplete type information from old numpy...
I removed a few annotations because they were failing (e.g.
np.sum can return a scalar or an array), but I don't think
this should be a problem - the function inputs and return values
are still typed.
numpy 1.20 deprecates np.float, which was only ever an alias for
``float``. I've replaced all occurrences of np.float with float, as
recommended. There should be no change in functionality.
The picamera object isn't thread safe; I have now wrapped all access
in context managers that acquire the BaseCamera.lock
I also added an endpoint to reset the LST without auto-gain.
When testing the UI I noticed that the different recalibrate routines
don't use locks properly, so they try to run
concurrently.
This commit isn't tested yet...
The previous "auto calibrate" button for the camera relied on a
combination of the built-in autoexposure/AWB and
some JPEG-based tweaks to get the exposure settings right.
This often led to confusing results, e.g. oscillating between green and
pink images.
I have rewritten the auto-exposure code to adjust gain and shutter
speed based on the raw image. This seems to be
very reliable, at the expense of being quite slow. That's a price I'm
happy to pay.
I have replaced both the camera's auto white balance and my
JPEG-based AWB hack with a single-shot AWB method that
looks at the raw image.
The scan API view now uses a schema with validation
constraints to enforce a minimum size of 1 in any dimension.
This requires better error handling in the app, which I've added.
It also needs a fix in LabThings so the error propagates correctly