Updated docs

This commit is contained in:
jtc42 2019-06-07 13:37:20 +01:00
parent fdbba08b66
commit 235aa984f9
12 changed files with 143 additions and 77 deletions

View file

@ -1 +1,2 @@
sphinxcontrib.httpdomain sphinxcontrib.httpdomain
sphinx_rtd_theme

View file

@ -42,21 +42,23 @@ CURL
.. code-block:: none .. code-block:: none
curl -X POST -H "Content-Type: application/json" -d \\ curl -X POST -H "Content-Type: application/json" -d \\
'{"picamera_settings": {"shutter_speed": 2000}, "jpeg_quality": 90}' http://192.168.1.126:5000/api/v1/config '{"camera_settings": {"picamera_settings": {"shutter_speed": 2000}, "jpeg_quality": 90}}' http://192.168.1.126:5000/api/v1/config
HTTPie HTTPie
++++++ ++++++
.. code-block:: none .. code-block:: none
http POST http://192.168.1.126:5000/api/v1/config jpeg_quality:=90 picamera_settings:='{"shutter_speed": 2000}' http POST http://192.168.1.126:5000/api/v1/config camera_settings:='{"jpeg_quality": 90, "picamera_settings": {"shutter_speed": 2000}}'
Python Requests Python Requests
+++++++++++++++ +++++++++++++++
.. code-block:: python .. code-block:: python
json_payload = { json_payload = {
"jpeg_quality": 90, camera_settings: {
"picamera_settings": {"shutter_speed": 2000} "jpeg_quality": 90,
"picamera_settings": {"shutter_speed": 2000}
}
} }
requests.post('http://192.168.1.126:5000/api/v1/config', json=json_payload) requests.post('http://192.168.1.126:5000/api/v1/config', json=json_payload)

View file

@ -1,5 +1,5 @@
Microscope configuration Microscope configuration
======================================================= ========================
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
@ -18,7 +18,7 @@ in separate "auxillary" config files, and are linked together by adding the conf
microscope RC file. This is set up by default, as shown below: microscope RC file. This is set up by default, as shown below:
Default microscope_settings.yaml Default microscope_settings.yaml
+++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++
.. code-block:: yaml .. code-block:: yaml
# Resolutions for streaming and capture # Resolutions for streaming and capture
@ -58,7 +58,7 @@ Example picamera_settings.yaml
Loading the runtime-config Loading the runtime-config
+++++++ ++++++++++++++++++++++++++
By default, a microscope object will load the a runtime-config from the default location. 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 This RC can then be passed to any hardware attached to the microscope. This can be particularly

View file

@ -22,12 +22,17 @@ Lock module
Default plugins Default plugins
--------------- ---------------
Microscope plugin Autofocus
+++++++++++++++++ +++++++++
.. automodule:: openflexure_microscope.plugins.default.plugin .. automodule:: openflexure_microscope.plugins.default.autofocus
:members: :members:
Web API plugin Camera calibration
++++++++++++++ ++++++++++++++++++
.. automodule:: openflexure_microscope.plugins.default.api .. automodule:: openflexure_microscope.plugins.default.camera_calibration
:members: :members:
Scan and Stack
++++++++++++++
.. automodule:: openflexure_microscope.plugins.default.scan
:members:

View file

@ -26,7 +26,7 @@ Generally, for adding anything other than very simple functionality, plugins sho
The main restriction is that the plugin package must be importable using an absolute import from within the Python environment being used to load your microscope. The main restriction is that the plugin package must be importable using an absolute import from within the Python environment being used to load your microscope.
Loading plugins with microscope_settings.yaml Loading plugins with microscope_settings.yaml
-------------------------------------- ---------------------------------------------
Both types of plugin are loaded by specifying the plugin class in your :ref:`MicroscopeRC`. In the case of a single-file plugin, specify the path to the plugin file, followed by the name of your :py:class:`openflexure_microscope.plugins.MicroscopePlugin` child class, separated by a colon. For packaged plugins, specify the absolute module name in place of the path. Both types of plugin are loaded by specifying the plugin class in your :ref:`MicroscopeRC`. In the case of a single-file plugin, specify the path to the plugin file, followed by the name of your :py:class:`openflexure_microscope.plugins.MicroscopePlugin` child class, separated by a colon. For packaged plugins, specify the absolute module name in place of the path.
For example, the plugins section of your microscope_settings.yaml file may look like: For example, the plugins section of your microscope_settings.yaml file may look like:

View file

@ -148,6 +148,12 @@ app.register_blueprint(task_blueprint, url_prefix=uri('/task', 'v1'))
def routes(): def routes():
""" """
List of all connected API routes List of all connected API routes
.. :quickref: System; Routes
:>header Accept: application/json
:>header Content-Type: application/json
:status 200: stream active
""" """
return jsonify(list_routes(app)) return jsonify(list_routes(app))
@ -156,6 +162,12 @@ def routes():
def err_log(): def err_log():
""" """
Most recent 1mb of log output Most recent 1mb of log output
.. :quickref: System; Log
:>header Accept: application/json
:>header Content-Type: application/json
:status 200: stream active
""" """
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
return send_file( return send_file(

View file

@ -100,35 +100,36 @@ class ConfigAPI(MicroscopeView):
Content-Type: application/json Content-Type: application/json
{ {
"image_resolution": [ "id": "0e2c6fac5421429aac67c7903107bdd8",
2592, "name": "docuscope-2000",
1944 "fov": [4100, 3146],
], "camera_settings": {
"jpeg_quality": 75, "image_resolution": [2592, 1944],
"name": "0e2c6fac5421429aac67c7903107bdd8", "numpy_resolution": [1312, 976],
"numpy_resolution": [ "video_resolution": [832, 624],
1312, "jpeg_quality": 75,
976 "picamera_settings": {
], "analog_gain": 1.0,
"picamera_settings": { "digital_gain": 1.0,
"analog_gain": 1.0, "awb_gains": [0.92578125, 2.94921875],
"digital_gain": 1.0, "awb_mode": "off",
"awb_gains": [ "exposure_mode": "off",
0.92578125, "framerate": 24.0,
2.94921875 "saturation": 0,
], "shutter_speed": 5378
"awb_mode": "off", },
"exposure_mode": "off", },
"framerate": 24.0, "stage_settings": {
"saturation": 0, "backlash": {
"shutter_speed": 5378 "x": 256,
}, "y": 256,
"z": 0
}
}
"plugins": [ "plugins": [
"openflexure_microscope.plugins.default:Plugin" "openflexure_microscope.plugins.default.autofocus:AutofocusPlugin",
], "openflexure_microscope.plugins.default.scan:ScanPlugin",
"stream_resolution": [ "openflexure_microscope.plugins.default.camera_calibration:Plugin"
832,
624
] ]
} }
@ -152,18 +153,52 @@ class ConfigAPI(MicroscopeView):
Accept: application/json Accept: application/json
{ {
"analog_gain": 1.0, "id": "0e2c6fac5421429aac67c7903107bdd8",
"digital_gain": 1.0, "name": "docuscope-2000",
"jpeg_quality": 75, "fov": [4100, 3146],
"picamera_params": { "camera_settings": {
"framerate": 24.0, "image_resolution": [2592, 1944],
"saturation": 0, "numpy_resolution": [1312, 976],
"shutter_speed": 5000 "video_resolution": [832, 624],
"jpeg_quality": 75,
"picamera_settings": {
"analog_gain": 1.0,
"digital_gain": 1.0,
"awb_gains": [0.92578125, 2.94921875],
"awb_mode": "off",
"exposure_mode": "off",
"framerate": 24.0,
"saturation": 0,
"shutter_speed": 5378
},
},
"stage_settings": {
"backlash": {
"x": 256,
"y": 256,
"z": 0
}
} }
"plugins": [
"openflexure_microscope.plugins.default.autofocus:AutofocusPlugin",
"openflexure_microscope.plugins.default.scan:ScanPlugin",
"openflexure_microscope.plugins.default.camera_calibration:Plugin"
]
} }
:>header Accept: application/json :>header Accept: application/json
:<json string id: Unique string identifier of the microscope.
:<json string name: Friendly name for the microscope
:<json array fov: Field of view (motor steps per full width and height of frame)
:<json json camera_settings: - **image_resolution** *(array)*: Resolution of full image captures
- **numpy_resolution** *(array)*: Resolution of full numpy array captures
- **video_resolution** *(array)*: Resolution of video recordings, low res image captures, and the preview stream
- **jpeg_quality** *(int)*: Quality in which to store JPEG capture data
- **picamera_settings** *(json)*: Key-value pairs to apply directly to any attached PiCamera object
:<json json stage_settings: - **backlash** *(json)*: x, y, and z backlash compensation, in motor steps
:<json array plugins: Array of plugin paths to load. Requires reloading the microscope object after applying
:<header Content-Type: application/json :<header Content-Type: application/json
:status 200: capture created :status 200: capture created

View file

@ -6,9 +6,9 @@ import logging
import pkg_resources import pkg_resources
import uuid import uuid
from openflexure_stage import OpenFlexureStage from .stage.base import BaseStage
from .camera.pi import StreamingCamera from .camera.base import BaseCamera
from .plugins import PluginMount from .plugins import PluginMount
from .utilities import axes_to_array from .utilities import axes_to_array
@ -28,8 +28,8 @@ class Microscope:
automatically created if None. automatically created if None.
lock (:py:class:`openflexure_microscope.lock.CompositeLock`): Composite lock controlling thread access lock (:py:class:`openflexure_microscope.lock.CompositeLock`): Composite lock controlling thread access
to multiple pieces of hardware. to multiple pieces of hardware.
camera (:py:class:`openflexure_microscope.camera.pi.StreamingCamera`): Camera object camera (:py:class:`openflexure_microscope.camera.base.BaseCamera`): Camera object
stage (:py:class:`openflexure_stage.stage.OpenFlexureStage`): Stage object stage (:py:class:`openflexure_microscope.stage.base.BaseStage`): Stage object
task: (:py:class:`openflexure_microscope.task.TaskOrchestrator`): Threaded ask orchestrator for managing task: (:py:class:`openflexure_microscope.task.TaskOrchestrator`): Threaded ask orchestrator for managing
background tasks using microscope hardware background tasks using microscope hardware
plugin (:py:class:`openflexure_microscope.plugins.PluginMount`): Mounting point for all microscope plugins plugin (:py:class:`openflexure_microscope.plugins.PluginMount`): Mounting point for all microscope plugins
@ -76,7 +76,7 @@ class Microscope:
self.stage.close() self.stage.close()
logging.info("Closed {}".format(self)) logging.info("Closed {}".format(self))
def attach(self, camera: StreamingCamera, stage: OpenFlexureStage): def attach(self, camera: BaseCamera, stage: BaseStage):
""" """
Retroactively attaches a camera and stage to the microscope object. Retroactively attaches a camera and stage to the microscope object.
@ -84,8 +84,8 @@ class Microscope:
opened at a later time. opened at a later time.
Args: Args:
camera (:py:class:`openflexure_microscope.camera.pi.StreamingCamera`): camera object camera (:py:class:`openflexure_microscope.camera.base.BaseCamera`): camera object
stage (:py:class:`openflexure_stage.stage.OpenFlexureStage`): stage object stage (:py:class:`openflexure_microscope.stage.base.BaseStage`): stage object
""" """
settings_full = self.read_config() settings_full = self.read_config()
@ -94,7 +94,7 @@ class Microscope:
# Maybe even attach dummy hardware at __init__, and replace with real hardware if it exists # Maybe even attach dummy hardware at __init__, and replace with real hardware if it exists
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.base.BaseCamera`: Picamera object
if not self.camera: if not self.camera:
logging.info("No camera attached.") logging.info("No camera attached.")
else: else:
@ -106,7 +106,7 @@ class Microscope:
self.lock.locks.append(self.camera.lock) self.lock.locks.append(self.camera.lock)
logging.debug("Attaching stage...") logging.debug("Attaching stage...")
self.stage = stage #: :py:class:`openflexure_stage.stage.OpenFlexureStage`: OpenFlexure stage object self.stage = stage #: :py:class:`openflexure_microscope.stage.base.BaseStage`: OpenFlexure stage object
if not self.stage: if not self.stage:
logging.info("No stage attached.") logging.info("No stage attached.")
else: else:

View file

@ -1 +1,2 @@
__all__ = ['AutofocusPlugin']
from .plugin import AutofocusPlugin from .plugin import AutofocusPlugin

View file

@ -89,28 +89,36 @@ class AutofocusPlugin(MicroscopePlugin):
This autofocus method is very efficient, as it only passes the peak once. This autofocus method is very efficient, as it only passes the peak once.
The sequence of moves it performs is: The sequence of moves it performs is:
1. Move to the top of the range `dz/2` (can be disabled)
2. Move down by `dz` while monitoring JPEG size to find the focus. 1. Move to the top of the range `dz/2` (can be disabled)
3. Move back up to the `target_z` position, relative to the sharpest image.
4. Measure the sharpness, and compare against the curve recorded in (2) to 2. Move down by `dz` while monitoring JPEG size to find the focus.
estimate how much further we need to go. Make this move, to reach our
target position. 3. Move back up to the `target_z` position, relative to the sharpest image.
4. Measure the sharpness, and compare against the curve recorded in (2) to \\
estimate how much further we need to go. Make this move, to reach our \\
target position.
Moving back to the target position in two steps allows us to correct for Moving back to the target position in two steps allows us to correct for
backlash, by using the sharpness-vs-z curve as a rough encoder for Z. backlash, by using the sharpness-vs-z curve as a rough encoder for Z.
Parameters: Parameters:
dz: number of steps over which to scan (optional, default 2000) dz: number of steps over which to scan (optional, default 2000)
target_z: we aim to finish at this position, relative to focus. This may
be useful if, for example, you want to acquire a stack of images in Z. target_z: we aim to finish at this position, relative to focus. This may
It is optional, and the default value of 0 will finish at the focus. be useful if, for example, you want to acquire a stack of images in Z.
initial_move_up: (optional, default True) set this to `False` to move down It is optional, and the default value of 0 will finish at the focus.
from the starting position. Mostly useful if you're able to combine
the initial move with something else, e.g. moving to the next scan point. initial_move_up: (optional, default True) set this to `False` to move down
mini_backlash: (optional, default 50) is a small extra move made in step from the starting position. Mostly useful if you're able to combine
3 to help counteract backlash. It should be small enough that you the initial move with something else, e.g. moving to the next scan point.
would always expect there to be greater backlash than this. Too small
might slightly hurt accuracy, but is unlikely to be a big issue. Too big mini_backlash: (optional, default 50) is a small extra move made in step
may cause you to overshoot, which is a problem. 3 to help counteract backlash. It should be small enough that you
would always expect there to be greater backlash than this. Too small
might slightly hurt accuracy, but is unlikely to be a big issue. Too big
may cause you to overshoot, which is a problem.
""" """
with self.monitor_sharpness() as m, self.microscope.camera.lock: with self.monitor_sharpness() as m, self.microscope.camera.lock:
# Ensure the MJPEG stream has started # Ensure the MJPEG stream has started

View file

@ -1 +1,2 @@
__all__ = ['Plugin']
from .plugin import Plugin from .plugin import Plugin

View file

@ -1 +1,2 @@
__all__ = ['ScanPlugin']
from .plugin import ScanPlugin from .plugin import ScanPlugin