Updated docs
This commit is contained in:
parent
fdbba08b66
commit
235aa984f9
12 changed files with 143 additions and 77 deletions
|
|
@ -1 +1,2 @@
|
||||||
sphinxcontrib.httpdomain
|
sphinxcontrib.httpdomain
|
||||||
|
sphinx_rtd_theme
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
__all__ = ['AutofocusPlugin']
|
||||||
from .plugin import AutofocusPlugin
|
from .plugin import AutofocusPlugin
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
__all__ = ['Plugin']
|
||||||
from .plugin import Plugin
|
from .plugin import Plugin
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
__all__ = ['ScanPlugin']
|
||||||
from .plugin import ScanPlugin
|
from .plugin import ScanPlugin
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue