Get codespell passing and add it as a CI job.
This commit is contained in:
parent
e33fecaef0
commit
7e6017f648
25 changed files with 113 additions and 85 deletions
|
|
@ -31,7 +31,7 @@ def configure_logging(log_folder):
|
|||
"""
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.setLevel(logging.INFO)
|
||||
# Explictly make OFM_LOG_FILE a global so it can be updated based on log settings
|
||||
# Explicitly make OFM_LOG_FILE a global so it can be updated based on log settings
|
||||
global OFM_LOG_FILE
|
||||
OFM_LOG_FILE = os.path.join(log_folder, "openflexure_microscope.log")
|
||||
|
||||
|
|
@ -64,11 +64,11 @@ def retrieve_log() -> PlainTextResponse:
|
|||
|
||||
This log is the one shown in the UI and on the logging page.
|
||||
|
||||
It does not include any of the ``uvicorn.access`` logs as these are emmitted
|
||||
It does not include any of the ``uvicorn.access`` logs as these are emitted
|
||||
every time any API route is called.
|
||||
|
||||
All logs, including ``uvicorn.access`` are logged to the OFM_LOG_FILE (see above)
|
||||
ths is the best place to get logs about crashes.
|
||||
this is the best place to get logs about crashes.
|
||||
"""
|
||||
return PlainTextResponse(OFM_HANDLER.log_history)
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ class OFMHandler(logging.Handler):
|
|||
"""A logging.Handler that stores the most recent logs for access by the server."""
|
||||
|
||||
def __init__(self, level=logging.INFO, max_logs=250):
|
||||
"""Inialise the handler with a set logging level and message buffer size.
|
||||
"""Initialise the handler with a set logging level and message buffer size.
|
||||
|
||||
:param level: The level of logs captured. As standard logs of INFO and above
|
||||
are captured.
|
||||
|
|
|
|||
|
|
@ -67,9 +67,9 @@ class ScanPlanner:
|
|||
|
||||
* ``_parse()`` - to parse the planner_settings dictionary, saving values to class
|
||||
variables
|
||||
* ``_intial_location_list()`` - Sets the list of locations for the scan to follow
|
||||
* ``_initial_location_list()`` - Sets the list of locations for the scan to follow
|
||||
|
||||
For a simple scan pattern this should be sufficent. For more complex ones that
|
||||
For a simple scan pattern this should be sufficient. For more complex ones that
|
||||
dynamically adjust the path it is suggested to override ``mark_location_visited()``
|
||||
calling ``super().mark_location_visited()`` at the start of the method so that all
|
||||
locations are adjusted.
|
||||
|
|
@ -78,17 +78,19 @@ class ScanPlanner:
|
|||
any user data before running.
|
||||
"""
|
||||
|
||||
def __init__(self, intial_position: XYPos, planner_settings: Optional[dict] = None):
|
||||
def __init__(
|
||||
self, initial_position: XYPos, planner_settings: Optional[dict] = None
|
||||
):
|
||||
"""Set up lists for the path planning, and scan history."""
|
||||
self._initial_position = enforce_xy_tuple(intial_position)
|
||||
self._initial_position = enforce_xy_tuple(initial_position)
|
||||
self._parse(planner_settings)
|
||||
|
||||
# The remaining (x,y) locations to scan
|
||||
# (This was `path` before refactoring from the long `sample_scan` code)
|
||||
self._remaining_locations: XYPosList = self._intial_location_list()
|
||||
self._remaining_locations: XYPosList = self._initial_location_list()
|
||||
|
||||
# This holds a list of all (x,y,z) locations where images were taken
|
||||
# this may not be equivalent to the x,y poistions ins self._path_history
|
||||
# this may not be equivalent to the x,y positions ins self._path_history
|
||||
# if background detect is used
|
||||
# (This was not used in the `sample_scan` code)
|
||||
self._imaged_locations: XYZPosList = []
|
||||
|
|
@ -132,10 +134,10 @@ class ScanPlanner:
|
|||
"""Parse any settings sent to this planner and store them if needed."""
|
||||
raise NotImplementedError("Did you call the ScanPlanner base class?")
|
||||
|
||||
def _intial_location_list(self) -> XYPosList:
|
||||
def _initial_location_list(self) -> XYPosList:
|
||||
"""Set the initial list of locations for this scan planner.
|
||||
|
||||
This is called on initalisation.
|
||||
This is called on initialisation.
|
||||
|
||||
For a simple grid scan/snake scan this would be all locations to move to.
|
||||
|
||||
|
|
@ -270,7 +272,7 @@ class SmartSpiral(ScanPlanner):
|
|||
self._dy = int(planner_settings["dy"])
|
||||
self._max_dist = int(planner_settings["max_dist"])
|
||||
|
||||
def _intial_location_list(self) -> XYPosList:
|
||||
def _initial_location_list(self) -> XYPosList:
|
||||
"""Set the initial list of locations for this scan planner.
|
||||
|
||||
This is salled on initialisation.
|
||||
|
|
@ -327,7 +329,7 @@ class SmartSpiral(ScanPlanner):
|
|||
self._remaining_locations.append(new_pos)
|
||||
|
||||
def _re_sort_remaining_locations(self, current_pos: XYPos) -> None:
|
||||
"""Sort the remaining positions besed on the current location."""
|
||||
"""Sort the remaining positions based on the current location."""
|
||||
|
||||
# Defined rather than use a lambda for readability
|
||||
def sort_key(pos):
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class StackParams:
|
|||
images_dir: str,
|
||||
save_resolution: tuple[int, int],
|
||||
) -> None:
|
||||
"""Initalise the parameters. All arguments are keyword only.
|
||||
"""Initialise the parameters. All arguments are keyword only.
|
||||
|
||||
:param stack_dz: The number of motor steps between images
|
||||
:param images_to_save: The number of images to save to disk
|
||||
|
|
@ -205,7 +205,7 @@ class JPEGSharpnessMonitor:
|
|||
"""
|
||||
|
||||
def __init__(self, stage: Stage, camera: Camera, portal: lt.deps.BlockingPortal):
|
||||
"""Initalise a new JPEGSharpnessMonitor. The args are injected automatically.
|
||||
"""Initialise a new JPEGSharpnessMonitor. The args are injected automatically.
|
||||
|
||||
:param stage: A direct_thing_client dependency for the the microscope stage.
|
||||
:param camera: A raw_thing_client depeendency for the camera. This is a raw
|
||||
|
|
@ -245,7 +245,7 @@ class JPEGSharpnessMonitor:
|
|||
"""Move the stage by dz, monitoring the position over time.
|
||||
|
||||
This performs exactly one move. Multiple calls of this method
|
||||
will append to the internal postition storage for more complex
|
||||
will append to the internal position storage for more complex
|
||||
autofocus procedures.
|
||||
|
||||
This should be run from within the JPEGSharpnessMonitor.run
|
||||
|
|
@ -505,9 +505,9 @@ class AutofocusThing(lt.Thing):
|
|||
save_resolution=save_resolution,
|
||||
)
|
||||
|
||||
trys = 0
|
||||
tries = 0
|
||||
# Loop until a stack is successful
|
||||
while trys < stack_parameters.max_attempts:
|
||||
while tries < stack_parameters.max_attempts:
|
||||
success, captures, sharpest_id = self.z_stack(
|
||||
stack_parameters=stack_parameters,
|
||||
cam=cam,
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class BackgroundDetectThing(lt.Thing):
|
|||
def background_mask(self, image: np.ndarray) -> np.ndarray:
|
||||
"""Calculate a binary image, showing whether each pixel is background.
|
||||
|
||||
The image should be in LUV format, the ouput will be binary with the
|
||||
The image should be in LUV format, the output will be binary with the
|
||||
same shape in the first two dimensions.
|
||||
"""
|
||||
d = self.background_distributions
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"""OpenFlexure Microscope Camera.
|
||||
|
||||
This module defines the interface for cameras. Any compatible lt.Thing
|
||||
should enabe the server to work.
|
||||
should enable the server to work.
|
||||
|
||||
See repository root for licensing information.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ class OpenCVCamera(BaseCamera):
|
|||
It's likely to be highly inefficient - raw and/or uncompressed captures using
|
||||
binary image formats will be added in due course.
|
||||
"""
|
||||
logging.warning(f"OpenCV camera doen't respect {resolution} setting")
|
||||
logging.warning(f"OpenCV camera doesn't respect {resolution} setting")
|
||||
ret, frame = self.cap.read()
|
||||
if not ret:
|
||||
raise RuntimeError(
|
||||
|
|
@ -104,7 +104,7 @@ class OpenCVCamera(BaseCamera):
|
|||
|
||||
This function will produce a JPEG image.
|
||||
"""
|
||||
logging.warning(f"OpenCV camera doen't respect {resolution} setting")
|
||||
logging.warning(f"OpenCV camera doesn't respect {resolution} setting")
|
||||
frame = self.capture_array()
|
||||
jpeg = cv2.imencode(".jpg", frame)[1].tobytes()
|
||||
exif_dict = {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class SensorMode(BaseModel):
|
|||
class SensorModeSelector(BaseModel):
|
||||
"""A Pydantic model holding the two values needed to select a PiCamera Sensor mode.
|
||||
|
||||
Theses values are the output size and the bit depth.
|
||||
These values are the output size and the bit depth.
|
||||
|
||||
This is a Pydantic model so that it can be saved to disk.
|
||||
"""
|
||||
|
|
@ -95,7 +95,7 @@ class LensShading(BaseModel):
|
|||
(12, 16) in size. The arrays are luminance, red-difference chroma (Cr), and
|
||||
blue-difference chroma (Cb).
|
||||
|
||||
This is a Pydantic modell so that it can be saved to the disk.
|
||||
This is a Pydantic model so that it can be saved to the disk.
|
||||
"""
|
||||
|
||||
luminance: list[list[float]]
|
||||
|
|
@ -162,7 +162,7 @@ class StreamingPiCamera2(BaseCamera):
|
|||
This method is run by any Thing when a ThingSetting is saved. However, the
|
||||
method reads the thing_setting. As reading the thing setting talks to the
|
||||
camera and calls save_settings if the value is not as expected, this could
|
||||
cause recursion. Aslo this means that saving one setting causes all others
|
||||
cause recursion. Also this means that saving one setting causes all others
|
||||
to be read each time.
|
||||
"""
|
||||
try:
|
||||
|
|
@ -197,7 +197,7 @@ class StreamingPiCamera2(BaseCamera):
|
|||
|
||||
@lt.thing_setting
|
||||
def colour_gains(self) -> tuple[float, float]:
|
||||
"""The red and blue colour gains, must be betwen 0.0 and 32.0."""
|
||||
"""The red and blue colour gains, must be between 0.0 and 32.0."""
|
||||
if not self._setting_save_in_progress and self.streaming:
|
||||
with self._streaming_picamera() as cam:
|
||||
cam_value = cam.capture_metadata()["ColourGains"]
|
||||
|
|
@ -759,7 +759,7 @@ class StreamingPiCamera2(BaseCamera):
|
|||
same as the default behaviour, which is to use an adaptive lens shading
|
||||
table.
|
||||
|
||||
This flat table is used to take an image wth no lens shading so that the
|
||||
This flat table is used to take an image with no lens shading so that the
|
||||
correct lens shading table can be calibrated.
|
||||
"""
|
||||
with self._streaming_picamera(pause_stream=True):
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ def set_minimum_exposure(camera: Picamera2) -> None:
|
|||
Note ISO is left at auto, because this is needed for the gains
|
||||
to be set correctly.
|
||||
"""
|
||||
# Disable Automatic exposure and gain algoritm (AeEnable), and set analogue
|
||||
# Disable Automatic exposure and gain algorithm (AeEnable), and set analogue
|
||||
# gain and exposure time.
|
||||
# Setting the shutter speed to 1us will result in it being set
|
||||
# to the minimum possible, which is ~8us for PiCamera v2
|
||||
|
|
@ -427,7 +427,7 @@ def set_static_lst(
|
|||
cr: np.ndarray,
|
||||
cb: np.ndarray,
|
||||
) -> None:
|
||||
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correcton.
|
||||
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correction.
|
||||
|
||||
``tuning`` will be updated in-place to set its shading to static, and disable any
|
||||
adaptive tweaking by the algorithm.
|
||||
|
|
@ -452,7 +452,7 @@ def set_static_ccm(
|
|||
float, float, float, float, float, float, float, float, float
|
||||
],
|
||||
) -> None:
|
||||
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correcton.
|
||||
"""Update the ``rpi.alsc`` section of a camera tuning dict to use a static correction.
|
||||
|
||||
``tuning`` will be updated in-place to set its shading to static, and disable any
|
||||
adaptive tweaking by the algorithm.
|
||||
|
|
@ -480,7 +480,7 @@ def set_static_geq(
|
|||
"""Update the ``rpi.geq`` section of a camera tuning dict.
|
||||
|
||||
:param tuning: the raspberry pi tuning file. This will be updated in-place to
|
||||
set the geq offest to the given value.
|
||||
set the geq offset to the given value.
|
||||
:param offset: The desired green equalisation offset. Default 65535. The default is
|
||||
the maximum allowed value. This means the brightness will always be below the
|
||||
threshold where averaging is used. This is default as we always need the green
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class SimulatedCamera(BaseCamera):
|
|||
canvas_shape: tuple[int, int, int] = (3000, 4000, 3),
|
||||
frame_interval: float = 0.1,
|
||||
):
|
||||
"""Initalise the simulated with settings for how images are generated.
|
||||
"""Initialise the simulated with settings for how images are generated.
|
||||
|
||||
:param shape: The shape (size) of the generated image.
|
||||
:param glyph_shape: The size randomly positioned glyphs.
|
||||
|
|
@ -128,7 +128,7 @@ class SimulatedCamera(BaseCamera):
|
|||
"""Wrap the attach_to_server method so the server instance can be stored.
|
||||
|
||||
Direct access to the server instance is needed to get the stage position while
|
||||
maintianing the same public API as a real camera that doesn't need this access.
|
||||
maintaining the same public API as a real camera that doesn't need this access.
|
||||
"""
|
||||
self._server = server
|
||||
return super().attach_to_server(server, path, setting_storage_path)
|
||||
|
|
@ -198,7 +198,7 @@ class SimulatedCamera(BaseCamera):
|
|||
It's likely to be highly inefficient - raw and/or uncompressed captures using
|
||||
binary image formats will be added in due course.
|
||||
"""
|
||||
logging.warning(f"Simulation camera doen't respect {resolution} setting")
|
||||
logging.warning(f"Simulation camera doesn't respect {resolution} setting")
|
||||
return self.generate_frame()
|
||||
|
||||
@lt.thing_action
|
||||
|
|
@ -211,7 +211,7 @@ class SimulatedCamera(BaseCamera):
|
|||
|
||||
This function will produce a JPEG image.
|
||||
"""
|
||||
logging.warning(f"Simulation camera doen't respect {resolution} setting")
|
||||
logging.warning(f"Simulation camera doesn't respect {resolution} setting")
|
||||
frame = self.capture_array()
|
||||
jpeg = cv2.imencode(".jpg", frame)[1].tobytes()
|
||||
exif_dict = {
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ class CSMUncalibratedError(HTTPException):
|
|||
"""An HTTP Exception raised if camera stage mapping data is needed but unavailable.
|
||||
|
||||
Camera Stage Mapping data is needed to convert from distances specified in fractions
|
||||
of the feild of view to distances in motor steps. This is used when clicking on the
|
||||
of the field of view to distances in motor steps. This is used when clicking on the
|
||||
live preview to move, or when performing a scan.
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"""The core sample scanning functionality for the OpenFlexure Microscope.
|
||||
|
||||
SmartScan provides sample scanning functionality including automatic background
|
||||
dectection (via the `BackgroundDetectThing`) and automatic path planning via
|
||||
detection (via the `BackgroundDetectThing`) and automatic path planning via
|
||||
`scan_planners`. It manages the directories of past scans via `scan_directories`.
|
||||
It also controls external processes for live stitching composite images, and
|
||||
the creation of the final stitched images.
|
||||
|
|
@ -229,7 +229,7 @@ class SmartScanThing(lt.Thing):
|
|||
def _move_to_next_point(
|
||||
self, next_point: tuple[int, int], z_estimate: Optional[int] = None
|
||||
) -> tuple[int, int, int]:
|
||||
"""Move the stage to the next poistion.
|
||||
"""Move the stage to the next position.
|
||||
|
||||
If no z_estimate is given then the current stage position is used. Must move
|
||||
to the estimated focused position (although moving below would be marginally
|
||||
|
|
@ -256,7 +256,7 @@ class SmartScanThing(lt.Thing):
|
|||
:param overlap: The desired overlap as a fraction of the image. i.e. 0.5 means
|
||||
that each image should overlap its nearest neighbour by 50%.
|
||||
|
||||
:returns: (dx, dy) - the x and y displacments in steps
|
||||
:returns: (dx, dy) - the x and y displacements in steps
|
||||
"""
|
||||
test_jpg = self._cam.grab_jpeg()
|
||||
test_image = np.array(Image.open(test_jpg.open()))
|
||||
|
|
@ -488,7 +488,7 @@ class SmartScanThing(lt.Thing):
|
|||
"max_dist": self._scan_data["max_dist"],
|
||||
}
|
||||
route_planner = scan_planners.SmartSpiral(
|
||||
intial_position=(self._stage.position["x"], self._stage.position["y"]),
|
||||
initial_position=(self._stage.position["x"], self._stage.position["y"]),
|
||||
planner_settings=planner_settings,
|
||||
)
|
||||
|
||||
|
|
@ -788,7 +788,7 @@ class SmartScanThing(lt.Thing):
|
|||
This uses popen and returns immediately
|
||||
|
||||
- self._preview_stitch_popen holds the popen for polling
|
||||
- self._preview_stitch_popen_lock is a lock aquired while interacting
|
||||
- self._preview_stitch_popen_lock is a lock acquired while interacting
|
||||
with Popen
|
||||
"""
|
||||
# Set minimum overlap to 90% of the scan overlap to catch only images directly adjacent,
|
||||
|
|
@ -856,7 +856,7 @@ class SmartScanThing(lt.Thing):
|
|||
os.set_blocking(process.stdout.fileno(), False)
|
||||
logger.info(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())))
|
||||
|
||||
# Poll returns None while running, will return the error code when finnished
|
||||
# Poll returns None while running, will return the error code when finished
|
||||
while process.poll() is None:
|
||||
log_buffer(process.stdout)
|
||||
# Once buffer is clear sleep for 0.2s before trying again.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue