Improved runtime-config docs
This commit is contained in:
parent
aae3a11a7e
commit
88b946b473
3 changed files with 108 additions and 36 deletions
|
|
@ -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:
|
||||||
|
|
@ -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():
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue