Initial 0.7.0 conversion

This commit is contained in:
Joel Collins 2020-06-29 15:24:59 +01:00
parent 3bb870a3a3
commit e6cb9f6b35
11 changed files with 129 additions and 130 deletions

View file

@ -1,7 +1,7 @@
from labthings.server.find import find_component from labthings.server.find import find_component
from labthings.server.extensions import BaseExtension from labthings.server.extensions import BaseExtension
from labthings.server.view import View, ActionView, PropertyView from labthings.server.view import View, ActionView, PropertyView
from labthings.server.decorators import ThingAction, ThingProperty from labthings.server import fields
from openflexure_microscope.devel import JsonResponse, request, abort from openflexure_microscope.devel import JsonResponse, request, abort
from openflexure_microscope.utilities import set_properties from openflexure_microscope.utilities import set_properties
@ -336,7 +336,9 @@ class AutofocusAPI(ActionView):
""" """
Run a standard autofocus Run a standard autofocus
""" """
def post(self): args = {"dz": fields.List(fields.Int())}
def post(self, args):
payload = JsonResponse(request) payload = JsonResponse(request)
microscope = find_component("org.openflexure.microscope") microscope = find_component("org.openflexure.microscope")
@ -344,7 +346,7 @@ class AutofocusAPI(ActionView):
abort(503, "No microscope connected. Unable to autofocus.") abort(503, "No microscope connected. Unable to autofocus.")
# Figure out the range of z values to use # Figure out the range of z values to use
dz = payload.param("dz", default=np.linspace(-300, 300, 7), convert=np.array) dz = np.array(args.get("dz", np.linspace(-300, 300, 7)))
if microscope.has_real_stage(): if microscope.has_real_stage():
logging.debug("Running autofocus...") logging.debug("Running autofocus...")
@ -360,18 +362,20 @@ class FastAutofocusAPI(ActionView):
""" """
Run a fast autofocus Run a fast autofocus
""" """
def post(self): args = {
payload = JsonResponse(request) "dz": fields.Int(default=2000),
"backlash": fields.Int(default=25, minimum=0)
}
def post(self, args):
microscope = find_component("org.openflexure.microscope") microscope = find_component("org.openflexure.microscope")
if not microscope: if not microscope:
abort(503, "No microscope connected. Unable to autofocus.") abort(503, "No microscope connected. Unable to autofocus.")
# Figure out the parameters to use # Figure out the parameters to use
dz = payload.param("dz", default=2000, convert=int) dz = args.get("dz")
backlash = payload.param("backlash", default=25, convert=int) backlash = args.get("backlash")
if backlash < 0:
backlash = 0
if microscope.has_real_stage(): if microscope.has_real_stage():
logging.debug("Running autofocus...") logging.debug("Running autofocus...")

View file

@ -1,6 +1,5 @@
from labthings.server.extensions import BaseExtension from labthings.server.extensions import BaseExtension
from labthings.server.view import View, PropertyView from labthings.server.view import View, PropertyView
from labthings.server.decorators import ThingProperty, PropertySchema, use_args
from labthings.server import fields from labthings.server import fields
from labthings.server.find import find_component from labthings.server.find import find_component
@ -198,8 +197,9 @@ class GetLocationsView(PropertyView):
return autostorage_extension_v2.get_locations() return autostorage_extension_v2.get_locations()
@PropertySchema(fields.String(required=True, example="Default"))
class PreferredLocationView(PropertyView): class PreferredLocationView(PropertyView):
schema = fields.String(required=True, example="Default")
def get(self): def get(self):
global autostorage_extension_v2 global autostorage_extension_v2
@ -219,7 +219,8 @@ class PreferredLocationView(PropertyView):
class PreferredLocationGUIView(View): class PreferredLocationGUIView(View):
@use_args({"new_path_title": fields.String(required=True)}) args = {"new_path_title": fields.String(required=True)}
def post(self, args): def post(self, args):
global autostorage_extension_v2 global autostorage_extension_v2

View file

@ -8,7 +8,6 @@ from functools import reduce
from openflexure_microscope.captures.capture_manager import generate_basename from openflexure_microscope.captures.capture_manager import generate_basename
from labthings.server.find import find_component, find_extension from labthings.server.find import find_component, find_extension
from labthings.server.extensions import BaseExtension from labthings.server.extensions import BaseExtension
from labthings.server.decorators import use_args
from labthings.server import fields from labthings.server import fields
from openflexure_microscope.devel import abort, update_task_progress from openflexure_microscope.devel import abort, update_task_progress
@ -91,7 +90,7 @@ class ScanExtension(BaseExtension):
def __init__(self): def __init__(self):
self._images_to_be_captured: int = 1 self._images_to_be_captured: int = 1
self._images_captured_so_far: int = 0 self._images_captured_so_far: int = 0
return BaseExtension.__init__(self, "org.openflexure.scan", version="2.0.0") BaseExtension.__init__(self, "org.openflexure.scan", version="2.0.0")
def progress(self): def progress(self):
progress = (self._images_captured_so_far / self._images_to_be_captured) * 100 progress = (self._images_captured_so_far / self._images_to_be_captured) * 100
@ -289,24 +288,23 @@ class ScanExtension(BaseExtension):
scan_extension_v2 = ScanExtension() scan_extension_v2 = ScanExtension()
class TileScanAPI(ActionView): class TileScanAPI(ActionView):
@use_args( args = {
{ "filename": fields.String(missing=None, example=None),
"filename": fields.String(missing=None, example=None), "temporary": fields.Boolean(missing=False),
"temporary": fields.Boolean(missing=False), "stride_size": fields.List(
"stride_size": fields.List( fields.Integer, missing=[2000, 1500, 100], example=[2000, 1500, 100]
fields.Integer, missing=[2000, 1500, 100], example=[2000, 1500, 100] ),
), "grid": fields.List(fields.Integer, missing=[3, 3, 3], example=[3, 3, 3]),
"grid": fields.List(fields.Integer, missing=[3, 3, 3], example=[3, 3, 3]), "style": fields.String(missing="raster"),
"style": fields.String(missing="raster"), "autofocus_dz": fields.Integer(missing=50),
"autofocus_dz": fields.Integer(missing=50), "fast_autofocus": fields.Boolean(missing=False),
"fast_autofocus": fields.Boolean(missing=False), "use_video_port": fields.Boolean(missing=False),
"use_video_port": fields.Boolean(missing=False), "bayer": fields.Boolean(missing=False),
"bayer": fields.Boolean(missing=False), "annotations": fields.Dict(missing={}, example={"Foo": "Bar"}),
"annotations": fields.Dict(missing={}, example={"Foo": "Bar"}), "tags": fields.List(fields.String, missing=[]),
"tags": fields.List(fields.String, missing=[]), "resize": fields.Dict(missing=None), # TODO: Validate keys
"resize": fields.Dict(missing=None), # TODO: Validate keys }
}
)
def post(self, args): def post(self, args):
microscope = find_component("org.openflexure.microscope") microscope = find_component("org.openflexure.microscope")

View file

@ -14,16 +14,10 @@ import logging
from labthings.server.find import find_component from labthings.server.find import find_component
from labthings.server.view import View, ActionView, PropertyView from labthings.server.view import View, ActionView, PropertyView
from labthings.server.schema import Schema from labthings.server.schema import Schema, pre_dump
from labthings.server import fields from labthings.server import fields
from labthings.server.extensions import BaseExtension from labthings.server.extensions import BaseExtension
from labthings.server.utilities import description_from_view from labthings.server.utilities import description_from_view
from labthings.server.decorators import (
ThingAction,
ThingProperty,
marshal_with,
pre_dump,
)
class ZipObjectSchema(Schema): class ZipObjectSchema(Schema):
@ -140,7 +134,6 @@ default_zip_manager = ZipManager()
class ZipBuilderAPIView(ActionView): class ZipBuilderAPIView(ActionView):
def post(self): def post(self):
ids = list(JsonResponse(request).json) ids = list(JsonResponse(request).json)
microscope = find_component("org.openflexure.microscope") microscope = find_component("org.openflexure.microscope")
@ -151,7 +144,8 @@ class ZipBuilderAPIView(ActionView):
class ZipListAPIView(PropertyView): class ZipListAPIView(PropertyView):
@marshal_with(ZipObjectSchema(many=True)) schema = ZipObjectSchema(many=True)
def get(self): def get(self):
return default_zip_manager.session_zips.values() return default_zip_manager.session_zips.values()

View file

@ -58,7 +58,6 @@ def enabled_root_actions():
return {k: v for k, v in _actions.items() if v["conditions"]} return {k: v for k, v in _actions.items() if v["conditions"]}
# @Tag("actions")
class ActionsView(View): class ActionsView(View):
def get(self): def get(self):
""" """

View file

@ -1,19 +1,11 @@
from openflexure_microscope.api.utilities import get_bool, JsonResponse from openflexure_microscope.api.utilities import get_bool, JsonResponse
from labthings.server.view import View, ActionView from labthings.server.view import View, ActionView
from labthings.server.find import find_component from labthings.server.find import find_component
from labthings.server.decorators import (
use_args,
marshal_with,
doc,
tag,
ThingAction,
doc_response,
)
from labthings.server import fields from labthings.server import fields
from openflexure_microscope.utilities import filter_dict from openflexure_microscope.utilities import filter_dict
from openflexure_microscope.api.v2.views.captures import capture_schema from openflexure_microscope.api.v2.views.captures import CaptureSchema
import logging import logging
import io import io
@ -25,24 +17,23 @@ class CaptureAPI(ActionView):
Create a new image capture. Create a new image capture.
""" """
@use_args( args = {
{ "filename": fields.String(example="MyFileName"),
"filename": fields.String(example="MyFileName"), "temporary": fields.Boolean(
"temporary": fields.Boolean( missing=False, description="Delete capture on shutdown"
missing=False, description="Delete capture on shutdown" ),
), "use_video_port": fields.Boolean(missing=False),
"use_video_port": fields.Boolean(missing=False), "bayer": fields.Boolean(
"bayer": fields.Boolean( missing=False, description="Store raw bayer data in file"
missing=False, description="Store raw bayer data in file" ),
), "annotations": fields.Dict(missing={}, example={"Client": "SwaggerUI"}),
"annotations": fields.Dict(missing={}, example={"Client": "SwaggerUI"}), "tags": fields.List(fields.String, missing=[], example=["docs"]),
"tags": fields.List(fields.String, missing=[], example=["docs"]), "resize": fields.Dict(
"resize": fields.Dict( missing=None, example={"width": 640, "height": 480}
missing=None, example={"width": 640, "height": 480} ), # TODO: Validate keys
), # TODO: Validate keys }
} schema = CaptureSchema()
)
@marshal_with(capture_schema)
def post(self, args): def post(self, args):
""" """
Create a new capture Create a new capture
@ -78,18 +69,22 @@ class RAMCaptureAPI(ActionView):
Take a non-persistant image capture. Take a non-persistant image capture.
""" """
@use_args( args = {
{ "use_video_port": fields.Boolean(missing=True),
"use_video_port": fields.Boolean(missing=True), "bayer": fields.Boolean(
"bayer": fields.Boolean( missing=False, description="Return with raw bayer data"
missing=False, description="Return with raw bayer data" ),
), "resize": fields.Dict(
"resize": fields.Dict( missing=None, example={"width": 640, "height": 480}
missing=None, example={"width": 640, "height": 480} ), # TODO: Validate keys
), # TODO: Validate keys }
responses = {
200: {
"content_type": "image/jpeg"
} }
) }
@doc_response(200, mimetype="image/jpeg")
def post(self, args): def post(self, args):
""" """
Take a non-persistant image capture. Take a non-persistant image capture.
@ -128,9 +123,8 @@ class GPUPreviewStartAPI(ActionView):
in the format ``[x, y, width, height]``. in the format ``[x, y, width, height]``.
""" """
@use_args( args = {"window": fields.List(fields.Integer, missing=[], example=[0, 0, 640, 480])}
{"window": fields.List(fields.Integer, missing=[], example=[0, 0, 640, 480])}
)
def post(self, args): def post(self, args):
""" """
Start the onboard GPU preview. Start the onboard GPU preview.

View file

@ -1,7 +1,6 @@
from openflexure_microscope.api.utilities import JsonResponse from openflexure_microscope.api.utilities import JsonResponse
from labthings.server.view import View, ActionView from labthings.server.view import View, ActionView
from labthings.server.find import find_component from labthings.server.find import find_component
from labthings.server.decorators import use_args, marshal_with, doc, ThingAction
from labthings.server import fields from labthings.server import fields
from openflexure_microscope.utilities import axes_to_array, filter_dict from openflexure_microscope.utilities import axes_to_array, filter_dict
@ -12,16 +11,15 @@ import logging
class MoveStageAPI(ActionView): class MoveStageAPI(ActionView):
@use_args( args = {
{ "absolute": fields.Boolean(
"absolute": fields.Boolean( default=False, example=False, description="Move to an absolute position"
default=False, example=False, description="Move to an absolute position" ),
), "x": fields.Int(default=0, example=100),
"x": fields.Int(default=0, example=100), "y": fields.Int(default=0, example=100),
"y": fields.Int(default=0, example=100), "z": fields.Int(default=0, example=20),
"z": fields.Int(default=0, example=20), }
}
)
def post(self, args): def post(self, args):
""" """
Move the microscope stage in x, y, z Move the microscope stage in x, y, z

View file

@ -3,8 +3,6 @@ import subprocess
import os import os
from sys import platform from sys import platform
from labthings.server.decorators import ThingAction, doc_response
def is_raspberrypi(raise_on_errors=False): def is_raspberrypi(raise_on_errors=False):
""" """
@ -19,7 +17,6 @@ class ShutdownAPI(ActionView):
Attempt to shutdown the device Attempt to shutdown the device
""" """
@doc_response(201)
def post(self): def post(self):
""" """
Attempt to shutdown the device Attempt to shutdown the device
@ -31,7 +28,7 @@ class ShutdownAPI(ActionView):
) )
out, err = p.communicate() out, err = p.communicate()
return {"out": out, "err": err}, 201 return {"out": out, "err": err}
class RebootAPI(ActionView): class RebootAPI(ActionView):
@ -39,7 +36,6 @@ class RebootAPI(ActionView):
Attempt to reboot the device Attempt to reboot the device
""" """
@doc_response(201)
def post(self): def post(self):
""" """
Attempt to reboot the device Attempt to reboot the device
@ -51,4 +47,4 @@ class RebootAPI(ActionView):
) )
out, err = p.communicate() out, err = p.communicate()
return {"out": out, "err": err}, 201 return {"out": out, "err": err}

View file

@ -7,7 +7,6 @@ from labthings.server.schema import Schema
from labthings.server import fields from labthings.server import fields
from labthings.server.view import View, PropertyView from labthings.server.view import View, PropertyView
from labthings.server.utilities import description_from_view from labthings.server.utilities import description_from_view
from labthings.server.decorators import marshal_with, doc_response, Tag, ThingProperty
from labthings.server.find import find_component from labthings.server.find import find_component
@ -84,16 +83,10 @@ class CaptureSchema(Schema):
return data return data
capture_schema = CaptureSchema()
capture_list_schema = CaptureSchema(many=True)
from pprint import pprint
@Tag("captures")
class CaptureList(PropertyView): class CaptureList(PropertyView):
@marshal_with(CaptureSchema(many=True)) tags = ["captures"]
schema = CaptureSchema(many=True)
def get(self): def get(self):
""" """
List all image captures List all image captures
@ -103,9 +96,10 @@ class CaptureList(PropertyView):
return image_list return image_list
@Tag("captures")
class CaptureView(View): class CaptureView(View):
@marshal_with(CaptureSchema()) tags = ["captures"]
schema = CaptureSchema()
def get(self, id): def get(self, id):
""" """
Description of a single image capture Description of a single image capture
@ -136,9 +130,14 @@ class CaptureView(View):
return "", 204 return "", 204
@Tag("captures")
class CaptureDownload(View): class CaptureDownload(View):
@doc_response(200, mimetype="image/jpeg") tags = ["captures"]
responses = {
200: {
"content_type": "image/jpeg"
}
}
def get(self, id, filename): def get(self, id, filename):
""" """
Image data for a single image capture Image data for a single image capture
@ -172,8 +171,9 @@ class CaptureDownload(View):
return send_file(img, mimetype="image/jpeg") return send_file(img, mimetype="image/jpeg")
@Tag("captures")
class CaptureTags(View): class CaptureTags(View):
tags = ["captures"]
def get(self, id): def get(self, id):
""" """
Get tags associated with a single image capture Get tags associated with a single image capture
@ -227,8 +227,9 @@ class CaptureTags(View):
return capture_obj.tags return capture_obj.tags
@Tag("captures")
class CaptureAnnotations(View): class CaptureAnnotations(View):
tags = ["captures"]
def get(self, id): def get(self, id):
""" """
Get annotations associated with a single image capture Get annotations associated with a single image capture

View file

@ -5,8 +5,6 @@ from labthings.core.utilities import get_by_path, set_by_path, create_from_path
from labthings.server.find import find_component from labthings.server.find import find_component
from labthings.server.view import View, PropertyView from labthings.server.view import View, PropertyView
from labthings.server.decorators import ThingProperty, Tag, doc_response
from flask import request, abort from flask import request, abort
import logging import logging
@ -35,9 +33,12 @@ class SettingsProperty(PropertyView):
return self.get() return self.get()
@Tag("properties")
class NestedSettingsProperty(View): class NestedSettingsProperty(View):
@doc_response(404, description="Settings key cannot be found") tags = ["properties"]
responses = {
404: {"description": "Settings key cannot be found"}
}
def get(self, route): def get(self, route):
""" """
Show a nested section of the current microscope settings Show a nested section of the current microscope settings
@ -52,7 +53,6 @@ class NestedSettingsProperty(View):
return value return value
@doc_response(404, description="Settings key cannot be found")
def put(self, route): def put(self, route):
""" """
Update a nested section of the current microscope settings Update a nested section of the current microscope settings
@ -79,9 +79,12 @@ class StateProperty(PropertyView):
return microscope.state return microscope.state
@Tag("properties")
class NestedStateProperty(View): class NestedStateProperty(View):
@doc_response(404, description="Status key cannot be found") tags = ["properties"]
responses = {
404: {"description": "Status key cannot be found"}
}
def get(self, route): def get(self, route):
""" """
Show a nested section of the current microscope state Show a nested section of the current microscope state
@ -106,9 +109,12 @@ class ConfigurationProperty(PropertyView):
return microscope.configuration return microscope.configuration
@Tag("properties")
class NestedConfigurationProperty(View): class NestedConfigurationProperty(View):
@doc_response(404, description="Configuration key cannot be found") tags = ["properties"]
responses = {
404: {"description": "Status key cannot be found"}
}
def get(self, route): def get(self, route):
""" """
Show a nested section of the current microscope state Show a nested section of the current microscope state

View file

@ -4,17 +4,19 @@ from labthings.core.utilities import get_by_path, set_by_path, create_from_path
from labthings.server.find import find_component from labthings.server.find import find_component
from labthings.server.view import View, PropertyView from labthings.server.view import View, PropertyView
from labthings.server.decorators import doc_response, ThingProperty from labthings.server.responses import Response
from flask import Response
class MjpegStream(PropertyView): class MjpegStream(PropertyView):
""" """
Real-time MJPEG stream from the microscope camera Real-time MJPEG stream from the microscope camera
""" """
responses = {
200: {
"content_type": "multipart/x-mixed-replace"
}
}
@doc_response(200, mimetype="multipart/x-mixed-replace")
def get(self): def get(self):
""" """
MJPEG stream from the microscope camera. MJPEG stream from the microscope camera.
@ -42,7 +44,13 @@ class SnapshotStream(PropertyView):
Single JPEG snapshot from the camera stream Single JPEG snapshot from the camera stream
""" """
@doc_response(200, description="Snapshot taken", mimetype="image/jpeg") responses = {
200: {
"content_type": "image/jpeg",
"description": "Snapshot taken"
}
}
def get(self): def get(self):
""" """
Single snapshot from the camera stream Single snapshot from the camera stream