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:
commit
42f00b69a4
3 changed files with 61 additions and 35 deletions
|
|
@ -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"]
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue