Merge remote-tracking branch 'origin/master' into auto-exposure-gain-awb

This was primarily done to disable the warning about f strings in
logging statements, globally rather than per-file.
This commit is contained in:
Richard Bowman 2021-04-27 17:16:19 +01:00
commit 42f00b69a4
3 changed files with 61 additions and 35 deletions

View file

@ -1,50 +1,47 @@
import logging
from typing import List, Tuple
from labthings import fields, find_component
from labthings.views import ActionView
from openflexure_microscope.utilities import axes_to_array
class MoveStageAPI(ActionView):
args = {
"absolute": fields.Boolean(
missing=False, example=False, description="Move to an absolute position"
),
"x": fields.Int(missing=0, example=100),
"y": fields.Int(missing=0, example=100),
"z": fields.Int(missing=0, example=20),
"x": fields.Int(missing=None, example=100),
"y": fields.Int(missing=None, example=100),
"z": fields.Int(missing=None, example=20),
}
def post(self, args):
"""
Move the microscope stage in x, y, z
Any axes that are not specifed will not move.
"""
microscope = find_component("org.openflexure.microscope")
# Handle absolute positioning (calculate a relative move from current position and target)
if (args.get("absolute")) and (microscope.stage): # Only if stage exists
target_position: List[int] = axes_to_array(args, ["x", "y", "z"])
logging.debug("TARGET: %s", (target_position))
position: Tuple[int, int, int] = (
target_position[i] - microscope.stage.position[i] for i in range(3)
)
logging.debug("DELTA: %s", (position))
else:
# Get coordinates from payload
position = axes_to_array(args, ["x", "y", "z"], [0, 0, 0])
logging.debug(position)
# Move if stage exists
if microscope.stage:
# Explicitally acquire lock with 1s timeout
with microscope.stage.lock(timeout=1):
microscope.stage.move_rel(position)
else:
if not microscope.stage:
logging.warning("Unable to move. No stage found.")
return microscope.state["stage"]["position"]
absolute_move = args.get("absolute")
move = [0, 0, 0] # Default to no motion
for i, axis in enumerate(["x", "y", "z"]):
if axis in args and args[axis] is not None:
if absolute_move:
# We emulate absolute moves by calculating a relative move that
# will take us to the right position.
move[i] = args[axis] - microscope.stage.position[i]
else:
move[i] = args[axis]
logging.debug(f"Moving stage by {move}, request was {args}")
# Explicitly acquire lock with 1s timeout
with microscope.stage.lock(timeout=1):
microscope.stage.move_rel(move)
return microscope.state["stage"]["position"]

View file

@ -4,7 +4,7 @@ import logging
import sys
import time
from contextlib import contextmanager
from typing import Dict, List, Optional, Tuple, Type, Union
from typing import Dict, List, Optional, Sequence, Tuple, Type, Union
import numpy as np
@ -102,12 +102,29 @@ def set_properties(obj, **kwargs):
def axes_to_array(
coordinate_dictionary: Dict[str, int],
axis_keys=("x", "y", "z"),
coordinate_dictionary: Dict[str, Optional[int]],
axis_keys: Sequence[str] = ("x", "y", "z"),
base_array: Optional[List[int]] = None,
asint: bool = True,
) -> List[int]:
"""Takes key-value pairs of a JSON value, and maps onto an array"""
"""Takes key-value pairs of a JSON value, and maps onto an array
This is designed to take a dictionary like `{"x": 1, "y":2, "z":3}`
and return a list like `[1, 2, 3]` to convert between the argument
format expected by most of our stages, and the usual argument
format in JSON.
`axis_keys` is an ordered sequence of key names to extract from
the input dictionary.
`base_array` specifies a default value for each axis. It must
have the same length as `axis_keys`.
`asint` casts values to integers if it is `True` (default).
Missing keys, or keys that have a `None` value will be left
at the specified default value, or zero if none is specified.
"""
# If no base array is given
if not base_array:
# Create an array of zeros
@ -119,8 +136,14 @@ def axes_to_array(
# Do the mapping
for axis, key in enumerate(axis_keys):
if key in coordinate_dictionary:
base_array[axis] = (
int(coordinate_dictionary[key]) if asint else coordinate_dictionary[key]
)
value = coordinate_dictionary[key]
if value is None:
# Values set to None should be treated as if they
# are missing
# i.e. we leave the default value in place.
break
if asint:
value = int(value)
base_array[axis] = value
return base_array

View file

@ -25,7 +25,13 @@ ensure_newline_before_comments = true
line_length = 88
[tool.pylint.'MESSAGES CONTROL']
disable = "fixme,C,R"
# W1203 warns about using f strings in logging statements.
# I'm really not concerned about the performance implications of this,
# particularly as we often have the log level set quite high. I think
# for our current purposes, using f strings in logging statements is
# more readable and thus a good idea in many places - I've disabled
# this warning code globally for that reason.
disable = "fixme,C,R,W1203"
max-line-length = 88
[tool.poe.executor]