Introduced apply_config and read_config methods
This commit is contained in:
parent
e5c10adf8d
commit
5471ffa62b
2 changed files with 93 additions and 91 deletions
|
|
@ -25,13 +25,7 @@ from __future__ import division
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import time
|
import time
|
||||||
import datetime
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import yaml
|
|
||||||
import copy
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from PIL import Image
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# Used for conversion only
|
# Used for conversion only
|
||||||
|
|
@ -44,9 +38,6 @@ import picamera.array
|
||||||
# Type hinting
|
# Type hinting
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
# Threading
|
|
||||||
import threading
|
|
||||||
|
|
||||||
from .base import BaseCamera, CaptureObject
|
from .base import BaseCamera, CaptureObject
|
||||||
# Richard's fix gain
|
# Richard's fix gain
|
||||||
from .set_picamera_gain import set_analog_gain, set_digital_gain
|
from .set_picamera_gain import set_analog_gain, set_digital_gain
|
||||||
|
|
@ -70,9 +61,9 @@ CONFIG_KEYS = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Useful methods
|
# Useful methods
|
||||||
|
|
||||||
# TODO: Remove this
|
|
||||||
def fractions_to_floats(value):
|
def fractions_to_floats(value):
|
||||||
"""Deal with horrible, horrible PiCamera fractions"""
|
"""Deal with horrible, horrible PiCamera fractions"""
|
||||||
result = value
|
result = value
|
||||||
|
|
@ -85,15 +76,15 @@ def fractions_to_floats(value):
|
||||||
result = float(value)
|
result = float(value)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# MAIN CLASS
|
|
||||||
|
|
||||||
|
# MAIN CLASS
|
||||||
class StreamingCamera(BaseCamera):
|
class StreamingCamera(BaseCamera):
|
||||||
"""Raspberry Pi camera implementation of StreamingCamera.
|
"""Raspberry Pi camera implementation of StreamingCamera.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
config (dict): Dictionary of config parameters to apply on init. If None, will default to basic config.
|
config (dict): Dictionary of config parameters to apply on init. If None, will default to basic config.
|
||||||
"""
|
"""
|
||||||
def __init__(self, config: dict=None, picamera_settings: dict=None):
|
def __init__(self, config: dict = None):
|
||||||
global CONFIG_KEYS
|
global CONFIG_KEYS
|
||||||
|
|
||||||
# Run BaseCamera init
|
# Run BaseCamera init
|
||||||
|
|
@ -111,11 +102,14 @@ class StreamingCamera(BaseCamera):
|
||||||
self.set_zoom(1.0)
|
self.set_zoom(1.0)
|
||||||
|
|
||||||
# Populate config and settings with all available keys
|
# Populate config and settings with all available keys
|
||||||
self._config.update(CONFIG_KEYS)
|
self.config.update(CONFIG_KEYS)
|
||||||
|
|
||||||
# Load config dictionary if passed
|
# Load config dictionary if passed
|
||||||
if config:
|
if config:
|
||||||
self.config = config
|
self.apply_config(config)
|
||||||
|
|
||||||
|
# Create an empty stream
|
||||||
|
self.stream = io.BytesIO()
|
||||||
|
|
||||||
# Start streaming
|
# Start streaming
|
||||||
self.start_worker()
|
self.start_worker()
|
||||||
|
|
@ -128,7 +122,7 @@ class StreamingCamera(BaseCamera):
|
||||||
"""Close the Raspberry Pi StreamingCamera."""
|
"""Close the Raspberry Pi StreamingCamera."""
|
||||||
# Run BaseCamera close method
|
# Run BaseCamera close method
|
||||||
BaseCamera.close(self)
|
BaseCamera.close(self)
|
||||||
# Detatch Pi camera
|
# Detach Pi camera
|
||||||
if self.camera:
|
if self.camera:
|
||||||
self.camera.close()
|
self.camera.close()
|
||||||
|
|
||||||
|
|
@ -146,8 +140,7 @@ class StreamingCamera(BaseCamera):
|
||||||
"""
|
"""
|
||||||
return hasattr(self.camera, "lens_shading_table")
|
return hasattr(self.camera, "lens_shading_table")
|
||||||
|
|
||||||
@property
|
def read_config(self):
|
||||||
def config(self):
|
|
||||||
"""
|
"""
|
||||||
Return config dictionary of the StreamingCamera.
|
Return config dictionary of the StreamingCamera.
|
||||||
"""
|
"""
|
||||||
|
|
@ -156,7 +149,7 @@ class StreamingCamera(BaseCamera):
|
||||||
}
|
}
|
||||||
|
|
||||||
# PiCamera parameters (obtained directly from PiCamera object)
|
# PiCamera parameters (obtained directly from PiCamera object)
|
||||||
for key, _ in self._config['picamera_settings'].items():
|
for key, _ in self.config['picamera_settings'].items():
|
||||||
try:
|
try:
|
||||||
value = getattr(self.camera, key)
|
value = getattr(self.camera, key)
|
||||||
value = fractions_to_floats(value)
|
value = fractions_to_floats(value)
|
||||||
|
|
@ -166,13 +159,12 @@ class StreamingCamera(BaseCamera):
|
||||||
|
|
||||||
# StreamingCamera parameters (obtained from StreamingCamera _config)
|
# StreamingCamera parameters (obtained from StreamingCamera _config)
|
||||||
for key in CONFIG_KEYS:
|
for key in CONFIG_KEYS:
|
||||||
if (key != 'picamera_settings') and (key in self._config):
|
if (key != 'picamera_settings') and (key in self.config):
|
||||||
conf_dict[key] = self._config[key]
|
conf_dict[key] = self.config[key]
|
||||||
|
|
||||||
return conf_dict
|
return conf_dict
|
||||||
|
|
||||||
@config.setter
|
def apply_config(self, config: dict) -> None:
|
||||||
def config(self, config: dict) -> None:
|
|
||||||
"""
|
"""
|
||||||
Write a config dictionary to the StreamingCamera config.
|
Write a config dictionary to the StreamingCamera config.
|
||||||
|
|
||||||
|
|
@ -202,7 +194,7 @@ class StreamingCamera(BaseCamera):
|
||||||
# PiCamera parameters (applied directly to PiCamera object)
|
# PiCamera parameters (applied directly to PiCamera object)
|
||||||
if 'picamera_settings' in config: # If new settings are given
|
if 'picamera_settings' in config: # If new settings are given
|
||||||
for key, value in config['picamera_settings'].items(): # For each given setting
|
for key, value in config['picamera_settings'].items(): # For each given setting
|
||||||
self._config['picamera_settings'][key] = None # Add the key to the list of returned settings
|
self.config['picamera_settings'][key] = None # Add the key to the list of returned settings
|
||||||
logging.debug("Setting parameter {}: {}".format(key, config['picamera_settings'][key]))
|
logging.debug("Setting parameter {}: {}".format(key, config['picamera_settings'][key]))
|
||||||
|
|
||||||
# Handle special attributes:
|
# Handle special attributes:
|
||||||
|
|
@ -217,7 +209,7 @@ class StreamingCamera(BaseCamera):
|
||||||
for key, value in config.items(): # For each provided setting
|
for key, value in config.items(): # For each provided setting
|
||||||
if key != 'picamera_settings': # We already handled this
|
if key != 'picamera_settings': # We already handled this
|
||||||
logging.debug("Setting parameter {}: {}".format(key, value))
|
logging.debug("Setting parameter {}: {}".format(key, value))
|
||||||
self._config[key] = value
|
self.config[key] = value
|
||||||
|
|
||||||
# If stream was paused to update config, unpause
|
# If stream was paused to update config, unpause
|
||||||
if paused_stream:
|
if paused_stream:
|
||||||
|
|
@ -228,9 +220,9 @@ class StreamingCamera(BaseCamera):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Cannot update camera config while recording is active.")
|
"Cannot update camera config while recording is active.")
|
||||||
|
|
||||||
def set_zoom(self, zoom_value: float=1.) -> None:
|
def set_zoom(self, zoom_value: float = 1.) -> None:
|
||||||
"""
|
"""
|
||||||
Change the camera zoom, handling recentering and scaling.
|
Change the camera zoom, handling re-centering and scaling.
|
||||||
"""
|
"""
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.state['zoom_value'] = float(zoom_value)
|
self.state['zoom_value'] = float(zoom_value)
|
||||||
|
|
@ -253,13 +245,13 @@ class StreamingCamera(BaseCamera):
|
||||||
# LAUNCH ACTIONS
|
# LAUNCH ACTIONS
|
||||||
|
|
||||||
def start_preview(self) -> bool:
|
def start_preview(self) -> bool:
|
||||||
"""Start the onboard GPU camera preview."""
|
"""Start the on board GPU camera preview."""
|
||||||
self.camera.start_preview()
|
self.camera.start_preview()
|
||||||
self.state['preview_active'] = True
|
self.state['preview_active'] = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def stop_preview(self) -> bool:
|
def stop_preview(self) -> bool:
|
||||||
"""Stop the onboard GPU camera preview."""
|
"""Stop the on board GPU camera preview."""
|
||||||
self.camera.stop_preview()
|
self.camera.stop_preview()
|
||||||
self.state['preview_active'] = False
|
self.state['preview_active'] = False
|
||||||
return True
|
return True
|
||||||
|
|
@ -267,17 +259,16 @@ class StreamingCamera(BaseCamera):
|
||||||
def start_recording(
|
def start_recording(
|
||||||
self,
|
self,
|
||||||
output,
|
output,
|
||||||
fmt: str='h264',
|
fmt: str = 'h264',
|
||||||
quality: int=15):
|
quality: int = 15):
|
||||||
"""Start recording.
|
"""Start recording.
|
||||||
|
|
||||||
Start a new video recording, writing to a output object.
|
Start a new video recording, writing to a output object.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
output (CaptureObject/str): Output object to write data bytes to.
|
output (CaptureObject/str): Output object to write data bytes to.
|
||||||
write_to_file (bool/NoneType): Should the StreamObject write to a file?
|
|
||||||
filename (str): Name of the stored file. Defaults to timestamp.
|
|
||||||
fmt (str): Format of the capture.
|
fmt (str): Format of the capture.
|
||||||
|
quality (int): Video recording quality.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
output_object (str/BytesIO): Target object.
|
output_object (str/BytesIO): Target object.
|
||||||
|
|
@ -317,7 +308,7 @@ class StreamingCamera(BaseCamera):
|
||||||
until the current recording has stopped.")
|
until the current recording has stopped.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def stop_recording(self) -> bool:
|
def stop_recording(self):
|
||||||
"""Stop the last started video recording on splitter port 2."""
|
"""Stop the last started video recording on splitter port 2."""
|
||||||
with self.lock:
|
with self.lock:
|
||||||
# Stop the camera video recording on port 2
|
# Stop the camera video recording on port 2
|
||||||
|
|
@ -330,8 +321,8 @@ class StreamingCamera(BaseCamera):
|
||||||
|
|
||||||
def stop_stream_recording(
|
def stop_stream_recording(
|
||||||
self,
|
self,
|
||||||
splitter_port: int=1,
|
splitter_port: int = 1,
|
||||||
resolution: Tuple[int, int]=None) -> None:
|
resolution: Tuple[int, int] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Sets the camera resolution to the still-image resolution, and stops recording if the stream is active.
|
Sets the camera resolution to the still-image resolution, and stops recording if the stream is active.
|
||||||
|
|
||||||
|
|
@ -355,8 +346,8 @@ class StreamingCamera(BaseCamera):
|
||||||
|
|
||||||
def start_stream_recording(
|
def start_stream_recording(
|
||||||
self,
|
self,
|
||||||
splitter_port: int=1,
|
splitter_port: int = 1,
|
||||||
resolution: Tuple[int, int]=None) -> None:
|
resolution: Tuple[int, int] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Sets the camera resolution to the video/stream resolution, and starts recording if the stream should be active.
|
Sets the camera resolution to the video/stream resolution, and starts recording if the stream should be active.
|
||||||
|
|
||||||
|
|
@ -364,9 +355,9 @@ class StreamingCamera(BaseCamera):
|
||||||
splitter_port (int): Splitter port to start recording on
|
splitter_port (int): Splitter port to start recording on
|
||||||
resolution ((int, int)): Resolution to set the camera to, before starting recording. Defaults to `self.config['video_resolution']`.
|
resolution ((int, int)): Resolution to set the camera to, before starting recording. Defaults to `self.config['video_resolution']`.
|
||||||
"""
|
"""
|
||||||
# If no stream object exists
|
# If stream object was destroyed
|
||||||
if not hasattr(self, 'stream'):
|
if not hasattr(self, 'stream'):
|
||||||
self.stream = io.BytesIO() # Create a stream object
|
self.stream = io.BytesIO() # Create a stream object
|
||||||
|
|
||||||
# If no explicit resolution is passed
|
# If no explicit resolution is passed
|
||||||
if not resolution:
|
if not resolution:
|
||||||
|
|
@ -389,10 +380,10 @@ class StreamingCamera(BaseCamera):
|
||||||
def capture(
|
def capture(
|
||||||
self,
|
self,
|
||||||
output,
|
output,
|
||||||
fmt: str='jpeg',
|
fmt: str = 'jpeg',
|
||||||
use_video_port: bool=False,
|
use_video_port: bool = False,
|
||||||
resize: Tuple[int, int]=None,
|
resize: Tuple[int, int] = None,
|
||||||
bayer: bool=True):
|
bayer: bool = True):
|
||||||
"""
|
"""
|
||||||
Capture a still image to a StreamObject.
|
Capture a still image to a StreamObject.
|
||||||
|
|
||||||
|
|
@ -404,6 +395,7 @@ class StreamingCamera(BaseCamera):
|
||||||
use_video_port (bool): Capture from the video port used for streaming. Lower resolution, faster.
|
use_video_port (bool): Capture from the video port used for streaming. Lower resolution, faster.
|
||||||
fmt (str): Format of the capture.
|
fmt (str): Format of the capture.
|
||||||
resize ((int, int)): Resize the captured image.
|
resize ((int, int)): Resize the captured image.
|
||||||
|
bayer (bool): Store raw bayer data in capture
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with self.lock:
|
with self.lock:
|
||||||
|
|
@ -416,7 +408,7 @@ class StreamingCamera(BaseCamera):
|
||||||
|
|
||||||
logging.info("Capturing to {}".format(output))
|
logging.info("Capturing to {}".format(output))
|
||||||
|
|
||||||
# Set resolution and stop stream recording if necesarry
|
# Set resolution and stop stream recording if necessary
|
||||||
if not use_video_port:
|
if not use_video_port:
|
||||||
self.stop_stream_recording()
|
self.stop_stream_recording()
|
||||||
|
|
||||||
|
|
@ -428,7 +420,7 @@ class StreamingCamera(BaseCamera):
|
||||||
bayer=(not use_video_port) and bayer,
|
bayer=(not use_video_port) and bayer,
|
||||||
use_video_port=use_video_port)
|
use_video_port=use_video_port)
|
||||||
|
|
||||||
# Set resolution and start stream recording if necesarry
|
# Set resolution and start stream recording if necessary
|
||||||
if not use_video_port:
|
if not use_video_port:
|
||||||
self.start_stream_recording()
|
self.start_stream_recording()
|
||||||
|
|
||||||
|
|
@ -436,9 +428,8 @@ class StreamingCamera(BaseCamera):
|
||||||
|
|
||||||
def yuv(
|
def yuv(
|
||||||
self,
|
self,
|
||||||
rgb=False,
|
use_video_port: bool = True,
|
||||||
use_video_port: bool=True,
|
resize: Tuple[int, int] = None) -> np.ndarray:
|
||||||
resize: Tuple[int, int]=None) -> np.ndarray:
|
|
||||||
"""Capture an uncompressed still YUV image to a Numpy array.
|
"""Capture an uncompressed still YUV image to a Numpy array.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
@ -473,16 +464,12 @@ class StreamingCamera(BaseCamera):
|
||||||
if not use_video_port:
|
if not use_video_port:
|
||||||
self.start_stream_recording()
|
self.start_stream_recording()
|
||||||
|
|
||||||
if rgb:
|
return output.array
|
||||||
logging.debug("Converting to RGB")
|
|
||||||
return output.rgb_array
|
|
||||||
else:
|
|
||||||
return output.array
|
|
||||||
|
|
||||||
def array(
|
def array(
|
||||||
self,
|
self,
|
||||||
use_video_port: bool=True,
|
use_video_port: bool = True,
|
||||||
resize: Tuple[int, int]=None) -> np.ndarray:
|
resize: Tuple[int, int] = None) -> np.ndarray:
|
||||||
"""Capture an uncompressed still RGB image to a Numpy array.
|
"""Capture an uncompressed still RGB image to a Numpy array.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
@ -537,7 +524,6 @@ class StreamingCamera(BaseCamera):
|
||||||
|
|
||||||
# Update state
|
# Update state
|
||||||
logging.debug("STREAM ACTIVE")
|
logging.debug("STREAM ACTIVE")
|
||||||
#self.state['stream_active'] = True
|
|
||||||
|
|
||||||
# While the iterator is not closed
|
# While the iterator is not closed
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -25,22 +25,29 @@ class Microscope(object):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
camera (:py:class:`openflexure_microscope.camera.pi.StreamingCamera`): camera object
|
camera (:py:class:`openflexure_microscope.camera.pi.StreamingCamera`): camera object
|
||||||
microscope (:py:class:`openflexure_stage.stage.OpenFlexureStage`): stage object
|
stage (:py:class:`openflexure_stage.stage.OpenFlexureStage`): stage object
|
||||||
config (dict): Dictionary of the runtime config to apply to the microscope. Does not automatically apply to camera and stage.
|
config_path (str): Path to a microscoperc.yaml runtime-config file
|
||||||
attach_plugins (bool): Should the microscope attach plugins listen in 'config' immediately.
|
attach_plugins (bool): Should the microscope attach plugins listen in 'config' immediately.
|
||||||
"""
|
"""
|
||||||
def __init__(self, camera: StreamingCamera, stage: OpenFlexureStage, config_path: str=None, attach_plugins: bool=True):
|
def __init__(
|
||||||
|
self,
|
||||||
|
camera: StreamingCamera,
|
||||||
|
stage: OpenFlexureStage,
|
||||||
|
config_path: str = None,
|
||||||
|
attach_plugins: bool = True):
|
||||||
|
|
||||||
# Create RC object
|
# Create RC object
|
||||||
self.rc = OpenflexureConfig(config_path=config_path, expand=True)
|
self.rc = OpenflexureConfig(config_path=config_path, expand=True)
|
||||||
|
|
||||||
# Attach initial hardware (may be NoneTypes)
|
# Attach initial hardware (may be NoneTypes)
|
||||||
|
self.camera = None
|
||||||
|
self.stage = None
|
||||||
self.attach(camera, stage)
|
self.attach(camera, stage)
|
||||||
|
|
||||||
# Create a task orchestrator
|
# Create a task orchestrator
|
||||||
self.task = TaskOrchestrator() #: :py:class:`openflexure_microscope.task.TaskOrchestrator`: Threaded task orchestrator
|
self.task = TaskOrchestrator() #: :py:class:`openflexure_microscope.task.TaskOrchestrator`: Threaded task orchestrator
|
||||||
|
|
||||||
# Create plugin mountpoint
|
# Create plugin mount-point
|
||||||
self.plugin = PluginMount(self) #: :py:class:`openflexure_microscope.plugins.PluginMount`: Mounting point for all microscope plugins
|
self.plugin = PluginMount(self) #: :py:class:`openflexure_microscope.plugins.PluginMount`: Mounting point for all microscope plugins
|
||||||
|
|
||||||
# Attach plugins
|
# Attach plugins
|
||||||
|
|
@ -48,16 +55,15 @@ class Microscope(object):
|
||||||
self.attach_plugins()
|
self.attach_plugins()
|
||||||
|
|
||||||
# Set default parameters
|
# Set default parameters
|
||||||
if not 'name' in self.rc.config:
|
if 'name' not in self.rc.config:
|
||||||
self.rc.config['name'] = uuid.uuid4().hex
|
self.rc.update({'name': uuid.uuid4().hex})
|
||||||
|
|
||||||
if not 'fov' in self.rc.config:
|
if 'fov' not in self.rc.config:
|
||||||
self.rc.config['fov'] = [0, 0]
|
self.rc.update({'fov': [0, 0]})
|
||||||
|
|
||||||
# Initialise with an empty composite lock
|
# Initialise with an empty composite lock
|
||||||
self.lock = CompositeLock([]) #: :py:class:`openflexure_microscope.lock.CompositeLock`: Composite lock controlling thread access to multiple pieces of hardware
|
self.lock = CompositeLock([]) #: :py:class:`openflexure_microscope.lock.CompositeLock`: Composite lock controlling thread access to multiple pieces of hardware
|
||||||
|
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
"""Create microscope on context enter."""
|
"""Create microscope on context enter."""
|
||||||
return self
|
return self
|
||||||
|
|
@ -82,14 +88,15 @@ class Microscope(object):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
camera (:py:class:`openflexure_microscope.camera.pi.StreamingCamera`): camera object
|
camera (:py:class:`openflexure_microscope.camera.pi.StreamingCamera`): camera object
|
||||||
microscope (:py:class:`openflexure_stage.stage.OpenFlexureStage`): stage object
|
stage (:py:class:`openflexure_stage.stage.OpenFlexureStage`): stage object
|
||||||
apply_config (bool): Should the microscope config dictionary be applied to the attached hardware?
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logging.debug("Attaching camera...")
|
logging.debug("Attaching camera...")
|
||||||
self.camera = camera #: :py:class:`openflexure_microscope.camera.pi.StreamingCamera`: Picamera object
|
self.camera = camera #: :py:class:`openflexure_microscope.camera.pi.StreamingCamera`: Picamera object
|
||||||
if isinstance(self.camera, StreamingCamera):
|
if isinstance(self.camera, StreamingCamera):
|
||||||
logging.info("Attached camera {}".format(camera))
|
logging.info("Attached camera {}".format(camera))
|
||||||
|
logging.info("Updating camera settings")
|
||||||
|
self.apply_config(self.camera.read_config())
|
||||||
elif not self.camera:
|
elif not self.camera:
|
||||||
logging.info("Attached dummy camera.")
|
logging.info("Attached dummy camera.")
|
||||||
# If camera has a lock
|
# If camera has a lock
|
||||||
|
|
@ -173,13 +180,37 @@ class Microscope(object):
|
||||||
|
|
||||||
return state
|
return state
|
||||||
|
|
||||||
@property
|
def apply_config(self, config: dict):
|
||||||
def config(self):
|
"""
|
||||||
|
Updates and applies a config dictionary. Missing parameters will be left untouched.
|
||||||
|
"""
|
||||||
|
# If attached to a camera
|
||||||
|
if self.camera:
|
||||||
|
# Update camera config
|
||||||
|
self.camera.config = config
|
||||||
|
|
||||||
|
# If attached to a stage
|
||||||
|
# TODO: Convert stage settings into a config expansion
|
||||||
|
if self.stage:
|
||||||
|
if 'backlash' in config:
|
||||||
|
# Construct backlash array
|
||||||
|
backlash = axes_to_array(config['backlash'], ['x', 'y', 'z'], [0, 0, 0])
|
||||||
|
self.stage.backlash = backlash
|
||||||
|
|
||||||
|
# Cache config
|
||||||
|
self.rc.update(config)
|
||||||
|
# Save to disk
|
||||||
|
self.rc.save()
|
||||||
|
|
||||||
|
def read_config(self):
|
||||||
|
"""
|
||||||
|
Read an updated config including camera settings.
|
||||||
|
"""
|
||||||
# If attached to a camera
|
# If attached to a camera
|
||||||
if self.camera:
|
if self.camera:
|
||||||
# Update camera config params from StreamingCamera object
|
# Update camera config params from StreamingCamera object
|
||||||
self.rc.update(self.camera.config)
|
self.rc.update(self.camera.config)
|
||||||
|
|
||||||
# If attached to a stage
|
# If attached to a stage
|
||||||
if self.stage:
|
if self.stage:
|
||||||
backlash = self.stage.backlash.tolist()
|
backlash = self.stage.backlash.tolist()
|
||||||
|
|
@ -196,27 +227,12 @@ class Microscope(object):
|
||||||
|
|
||||||
self.rc.update(backlash)
|
self.rc.update(backlash)
|
||||||
|
|
||||||
return self.rc.config
|
return self.rc.asdict()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config(self) -> dict:
|
||||||
|
return self.read_config()
|
||||||
|
|
||||||
@config.setter
|
@config.setter
|
||||||
def config(self, config: dict) -> None:
|
def config(self, config: dict) -> None:
|
||||||
"""
|
self.apply_config(config)
|
||||||
Technically doesn't SET the config, but rather updates it. Missing parameters
|
|
||||||
will be left untouched.
|
|
||||||
"""
|
|
||||||
# If attached to a camera
|
|
||||||
if self.camera:
|
|
||||||
# Update camera config
|
|
||||||
self.camera.config = config
|
|
||||||
|
|
||||||
# If attached to a stage
|
|
||||||
if self.stage:
|
|
||||||
if 'backlash' in config:
|
|
||||||
# Construct backlash array
|
|
||||||
backlash = axes_to_array(config['backlash'], ['x', 'y', 'z'], [0, 0, 0])
|
|
||||||
self.stage.backlash = backlash
|
|
||||||
|
|
||||||
# Cache config
|
|
||||||
self.rc.update(config)
|
|
||||||
# Save to disk
|
|
||||||
self.rc.save()
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue