Improved runtime-config docs

This commit is contained in:
Joel Collins 2019-02-07 11:19:00 +00:00
parent aae3a11a7e
commit 88b946b473
3 changed files with 108 additions and 36 deletions

View file

@ -10,57 +10,86 @@ Microscope configuration
Microscope RC file Microscope RC file
------------------ ------------------
Example Microscope configuration is made persistent via a microscope runtime-config (RC) file. By default, this
+++++++ file exists at ``~/.openflexure/microscoperc.yaml``, and contains basic parameters to set up the microscope.
.. code-block:: python
from openflexure_microscope import Microscope, config Additionally, by default, configurations for specific pieces of hardware (i.e. the Pi camera) are located
from openflexure_microscope.camera.pi import StreamingCamera in separate "auxillary" config files, and are linked together by adding the config file's path to your main
from openflexure_stage import OpenFlexureStage microscope RC file. This is set up by default, as shown below:
# Load default user config from ~/.openflexure/microscoperc.yaml
openflexurerc = config.load_config()
# Create a picamera StreamingCamera, using our config
camera_obj = StreamingCamera(config=openflexurerc)
# Create an OpenFlexure Stage attached to /dev/ttyUSB0
stage_obj = OpenFlexureStage("/dev/ttyUSB0")
# Attach devices and config to a Microscope object
api_microscope = Microscope(camera_obj, stage_obj, config=openflexurerc)
Default microscoperc.yaml Default microscoperc.yaml
+++++++++++++++++++++++++ +++++++++++++++++++++++++
.. code-block:: yaml .. code-block:: yaml
# The analog gain offers higher sensitivity and less noise than using digital gain only
analog_gain: 1.
digital_gain: 1.
# Resolutions for streaming and capture # Resolutions for streaming and capture
video_resolution: [832, 624] video_resolution: [832, 624]
image_resolution: [2592, 1944] image_resolution: [2592, 1944]
numpy_resolution: [1312, 976] numpy_resolution: [1312, 976]
# Field of view, in stage steps
fov: [4100, 3146]
# Capture quality # Capture quality
jpeg_quality: 75 jpeg_quality: 75
# Parameters specific to PiCamera objects # Parameters specific to PiCamera objects
picamera_params: picamera_settings: ~/.openflexure/picamera_settings.yaml
exposure_mode: 'off'
awb_mode: 'off'
awb_gains: [0.9, 2.8]
framerate: 24
shutter_speed: 30000
saturation: 0
led: false
# Default plugins # Default plugins
plugins: plugins:
- openflexure_microscope.plugins.default:Plugin - openflexure_microscope.plugins.default.autofocus:AutofocusPlugin
- openflexure_microscope.plugins.default.camera_calibration:Plugin
Config module Example picamera_settings.yaml
------------- ++++++++++++++++++++++++++++++
Loading the runtime-config
+++++++
By default, a microscope object will load the a runtime-config from the default location.
This RC can then be passed to any hardware attached to the microscope. This can be particularly
useful when creating a dummy microscope object before attaching hardware. For example:
.. code-block:: python
from openflexure_microscope import Microscope
from openflexure_microscope.camera.pi import StreamingCamera
from openflexure_stage import OpenFlexureStage
# Create an empty microscope
api_microscope = Microscope(None, None)
# Create a picamera StreamingCamera, using our config
camera_obj = StreamingCamera(config=api_microscope.rc.read())
# Create an OpenFlexure Stage attached to /dev/ttyUSB0
stage_obj = OpenFlexureStage("/dev/ttyUSB0")
# Attach devices to the Microscope object
api_microscope.attach(camera_obj, stage_obj)
Alternatively, a config can be loaded prior to creating a microscope, allowing the microscope
hardware to be created and attached in a single line. For example:
.. code-block:: python
from openflexure_microscope.config import OpenflexureConfig
from openflexure_microscope import Microscope
from openflexure_microscope.camera.pi import StreamingCamera
from openflexure_stage import OpenFlexureStage
# Create a runtime-config from the default location
rc = OpenflexureConfig(expand=True)
# Create a populated microscope
api_microscope = Microscope(
StreamingCamera(config=rc),
OpenFlexureStage("/dev/ttyUSB0"),
config=rc
)
Config module and OpenflexureConfig class
-----------------------------------------
.. automodule:: openflexure_microscope.config .. automodule:: openflexure_microscope.config
:members: :members:

View file

@ -144,7 +144,13 @@ def initialise_file(config_path, populate: str = ""):
class OpenflexureConfig: class OpenflexureConfig:
"""
An object to handle expansion, conversion, and saving of the microscope configuration.
Args:
config_path (str): Path to the config YAML file (None falls back to default location)
expand (bool): Expand paths to valid auxillary config files.
"""
def __init__(self, config_path: str = None, expand: bool = True): def __init__(self, config_path: str = None, expand: bool = True):
global DEFAULT_CONFIG, USER_CONFIG_FILE global DEFAULT_CONFIG, USER_CONFIG_FILE
@ -168,9 +174,18 @@ class OpenflexureConfig:
@property @property
def config(self): def config(self):
"""
Return a dictionary representation of the current config as a property.
"""
return self.read() return self.read()
def read(self, json_safe=False): def read(self, json_safe=False):
"""
Read the current full config.
Args:
json_safe (bool): Converts invalid data types to JSON types, and removes any excessively large values (e.g. lens-shading tables).
"""
if json_safe: if json_safe:
logging.info("Reading config as JSON-safe dictionary") logging.info("Reading config as JSON-safe dictionary")
return json_map(self._config) return json_map(self._config)
@ -179,9 +194,18 @@ class OpenflexureConfig:
return self._config return self._config
def write(self, update_dict: dict): def write(self, update_dict: dict):
"""
Write properties to the config. Merges dictionaries, rather than fully replacing.
Args:
update_dict (dict): Dictionary of config data to merge.
"""
self._config.update(update_dict) self._config.update(update_dict)
def load(self): def load(self):
"""
Loads config from a file on-disk, and expands auxillary config files if available.
"""
# Unexpanded config dictionary (used at load/save time) # Unexpanded config dictionary (used at load/save time)
self._config = load_yaml_file(self.config_path) self._config = load_yaml_file(self.config_path)
@ -191,6 +215,9 @@ class OpenflexureConfig:
self._config = self.expand_config(self._config) self._config = self.expand_config(self._config)
def save(self, backup: bool = True): def save(self, backup: bool = True):
"""
Save config to a file on-disk, and splits into auxillary config files if available.
"""
# If the loaded config was in contracted format # If the loaded config was in contracted format
if self.expand: if self.expand:
# Contract self._config into self.raw_config # Contract self._config into self.raw_config
@ -205,6 +232,13 @@ class OpenflexureConfig:
save_yaml_file(self.config_path, save_config) save_yaml_file(self.config_path, save_config)
def expand_config(self, config_dict): def expand_config(self, config_dict):
"""
Search a config dictionary for paths to valid auxillary config files,
and expand into the config dictionary if available.
Args:
config_dict (dict): Dictionary of config data to expand
"""
return_config = {} return_config = {}
# For each value in the raw loaded config # For each value in the raw loaded config
for key, value in config_dict.items(): for key, value in config_dict.items():
@ -226,6 +260,12 @@ class OpenflexureConfig:
return return_config return return_config
def contract_config(self, config_dict): def contract_config(self, config_dict):
"""
Split a config dictionary into auxillary config files, if available.
Args:
config_dict (dict): Dictionary of config data to contract/split
"""
return_config = {} return_config = {}
# For each value in the expanded config # For each value in the expanded config
for key, value in config_dict.items(): for key, value in config_dict.items():

View file

@ -25,18 +25,21 @@ 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
stage (:py:class:`openflexure_stage.stage.OpenFlexureStage`): stage object stage (:py:class:`openflexure_stage.stage.OpenFlexureStage`): stage object
config_path (str): Path to a microscoperc.yaml runtime-config file config (:py:class:`openflexure_microscope.config.OpenflexureConfig`): Runtime-config object, automatically created if None.
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__( def __init__(
self, self,
camera: StreamingCamera, camera: StreamingCamera,
stage: OpenFlexureStage, stage: OpenFlexureStage,
config_path: str = None, config = None,
attach_plugins: bool = True): attach_plugins: bool = True):
# Create RC object # Create RC object
self.rc = OpenflexureConfig(config_path=config_path, expand=True) if config:
self.rc = config
else:
self.rc = OpenflexureConfig(expand=True) # Load config from default path
# Attach initial hardware (may be NoneTypes) # Attach initial hardware (may be NoneTypes)
self.camera = None self.camera = None