More Marshmallow argument updates

This commit is contained in:
Richard Bowman 2022-08-09 13:16:10 +01:00
parent e22f36b308
commit 9dbb083ee7
18 changed files with 102 additions and 87 deletions

View file

@ -46,7 +46,7 @@ class ExampleIdentifyView(View):
class ExampleRenameView(View): class ExampleRenameView(View):
# Expect a request parameter called "name", which is a string. # Expect a request parameter called "name", which is a string.
# Passed to the argument "args". # Passed to the argument "args".
args = fields.String(required=True, example="My Example Microscope") args = fields.String(required=True, metadata={"example": "My Example Microscope"})
def post(self, args): def post(self, args):
# Look for our new name in the request body # Look for our new name in the request body

View file

@ -49,7 +49,7 @@ class ExampleRenameView(View):
# Format our returned object using MicroscopeIdentifySchema # Format our returned object using MicroscopeIdentifySchema
schema = MicroscopeIdentifySchema() schema = MicroscopeIdentifySchema()
# Expect a request parameter called "name", which is a string. Pass to argument "args". # Expect a request parameter called "name", which is a string. Pass to argument "args".
args = {"name": fields.String(required=True, example="My Example Microscope")} args = {"name": fields.String(required=True, metadata={"example": "My Example Microscope"})}
def post(self, args): def post(self, args):
# Look for our "name" parameter in the request arguments # Look for our "name" parameter in the request arguments

View file

@ -53,7 +53,7 @@ class ExampleIdentifyView(PropertyView):
# We can use a single schema as the input and output will be formatted identically # We can use a single schema as the input and output will be formatted identically
# Eg. We always expect a "name" string argument, and always return a "name" string attribute # Eg. We always expect a "name" string argument, and always return a "name" string attribute
class ExampleRenameView(PropertyView): class ExampleRenameView(PropertyView):
schema = {"name": fields.String(required=True, example="My Example Microscope")} schema = {"name": fields.String(required=True, metadata={"example": "My Example Microscope"})}
def get(self): def get(self):
""" """

View file

@ -56,7 +56,7 @@ class ExampleIdentifyView(PropertyView):
# We can use a single schema as the input and output will be formatted identically # We can use a single schema as the input and output will be formatted identically
# Eg. We always expect a "name" string argument, and always return a "name" string attribute # Eg. We always expect a "name" string argument, and always return a "name" string attribute
class ExampleRenameView(PropertyView): class ExampleRenameView(PropertyView):
schema = {"name": fields.String(required=True, example="My Example Microscope")} schema = {"name": fields.String(required=True, metadata={"example": "My Example Microscope"})}
def get(self): def get(self):
""" """

View file

@ -66,10 +66,10 @@ class TimelapseAPIView(ActionView):
args = { args = {
"n_images": fields.Integer( "n_images": fields.Integer(
required=True, example=5, description="Number of images" required=True, metadata={"example": 5, "description": "Number of images"}
), ),
"t_between": fields.Number( "t_between": fields.Number(
load_default=1, example=1, description="Time (seconds) between images" load_default=1, metadata={"example": 1, "description": "Time (seconds) between images"}
), ),
} }

View file

@ -99,10 +99,10 @@ class TimelapseAPIView(ActionView):
args = { args = {
"n_images": fields.Integer( "n_images": fields.Integer(
required=True, example=5, description="Number of images" required=True, metadata={"example": 5, "description": "Number of images"}
), ),
"t_between": fields.Number( "t_between": fields.Number(
load_default=1, example=1, description="Time (seconds) between images" load_default=1, metadata={"example": 1, "description": "Time (seconds) between images"}
), ),
} }

View file

@ -23,7 +23,7 @@ A **field** describes the data type of a single parameter, as well as any other
.. code-block:: python .. code-block:: python
fields.String(required=False, load_default="Default value", example="Example value") fields.String(required=False, load_default="Default value", metadata={"example: "Example value"})
A **schema** is a collection of keys and fields describing how an object should be serialized/deserialized. Schemas can be created in several ways, either by creating a ``Schema`` class, or by passing a dictionary of key-field pairs. Both methods will be discussed in the following examples. A **schema** is a collection of keys and fields describing how an object should be serialized/deserialized. Schemas can be created in several ways, either by creating a ``Schema`` class, or by passing a dictionary of key-field pairs. Both methods will be discussed in the following examples.
@ -146,7 +146,7 @@ Our ``rename`` view class may now look like:
# Format our returned object using MicroscopeIdentifySchema # Format our returned object using MicroscopeIdentifySchema
schema = MicroscopeIdentifySchema() schema = MicroscopeIdentifySchema()
# Expect a request parameter called "name", which is a string. Pass to argument "args". # Expect a request parameter called "name", which is a string. Pass to argument "args".
args = {"name": fields.String(required=True, example="My Example Microscope")} args = {"name": fields.String(required=True, metadata={"example": "My Example Microscope"})}
def post(self, args): def post(self, args):
# Look for our "name" parameter in the request arguments # Look for our "name" parameter in the request arguments

View file

@ -78,7 +78,7 @@ We will implement the ``schema`` attribute in our ``ExampleRenameView`` view fro
# We can use a single schema as the input and output will be formatted identically # We can use a single schema as the input and output will be formatted identically
# Eg. We always expect a "name" string argument, and always return a "name" string attribute # Eg. We always expect a "name" string argument, and always return a "name" string attribute
class ExampleRenameView(PropertyView): class ExampleRenameView(PropertyView):
schema = {"name": fields.String(required=True, example="My Example Microscope")} schema = {"name": fields.String(required=True, metadata={"example": "My Example Microscope"})}
def get(self): def get(self):
""" """

View file

@ -349,8 +349,10 @@ class AutofocusExtension(BaseExtension):
args={ args={
"dz": fields.List( "dz": fields.List(
fields.Int(), fields.Int(),
metadata={"description": "An ascending list of relative z positions"}, metadata={
example=[int(x) for x in np.linspace(-300, 300, 7)], "description": "An ascending list of relative z positions",
"example": [int(x) for x in np.linspace(-300, 300, 7)],
}
) )
} }
) )
@ -433,8 +435,10 @@ class AutofocusExtension(BaseExtension):
args={ args={
"dz": fields.Int( "dz": fields.Int(
load_default=2000, load_default=2000,
example=2000, metadata={
metadata={"description": "Total Z range to search over (in stage steps)"}, "description": "Total Z range to search over (in stage steps)",
"example": 2000,
},
) )
} }
) )
@ -529,13 +533,17 @@ class AutofocusExtension(BaseExtension):
args={ args={
"dz": fields.Int( "dz": fields.Int(
load_default=500, load_default=500,
example=500, metadata={
metadata={"description": "Total Z range to move down, then up (in stage steps)"}, "description": "Total Z range to move down, then up (in stage steps)",
"example": 500,
},
), ),
"delay": fields.Int( "delay": fields.Int(
load_default=5, load_default=5,
example=5, metadata={
metadata={"description": "How long to measure sharpness for after the move"}, "description": "How long to measure sharpness for after the move",
"example": 5,
},
), ),
} }
) )
@ -557,13 +565,17 @@ class AutofocusExtension(BaseExtension):
args={ args={
"dz": fields.Int( "dz": fields.Int(
load_default=2000, load_default=2000,
example=2000, metadata={
metadata={"description": "Total Z range to search over (in stage steps)"}, "description": "Total Z range to search over (in stage steps)",
"example": 2000,
},
), ),
"target_z": fields.Int( "target_z": fields.Int(
load_default=0, load_default=0,
example=-100, metadata={
metadata={"description": "Target finishing position, relative to the focus."}, "description": "Target finishing position, relative to the focus.",
"example": -100,
},
), ),
"initial_move_up": fields.Bool( "initial_move_up": fields.Bool(
load_default=True, load_default=True,
@ -571,8 +583,10 @@ class AutofocusExtension(BaseExtension):
), ),
"backlash": fields.Int( "backlash": fields.Int(
load_default=25, load_default=25,
minimum=0, metadata={
metadata={"description": "Distance to undershoot, before correction move."}, "description": "Distance to undershoot, before correction move.",
"minimum": 0,
},
), ),
} }
) )

View file

@ -242,7 +242,7 @@ class GetLocationsView(PropertyView):
class PreferredLocationView(PropertyView): class PreferredLocationView(PropertyView):
schema = fields.String(required=True, example="Default") schema = fields.String(required=True, metadata={"example": "Default"})
def get(self): def get(self):
self.extension.check_location() self.extension.check_location()

View file

@ -279,7 +279,7 @@ class CSMExtension(BaseExtension):
class Calibrate1DView(ActionView): class Calibrate1DView(ActionView):
args = {"direction": fields.List(fields.Float(), required=True, example=[1, 0, 0])} args = {"direction": fields.List(fields.Float(), required=True, metadata={"example": [1, 0, 0]})}
def post(self, args): def post(self, args):
"""Calibrate one axis of the microscope stage against the camera.""" """Calibrate one axis of the microscope stage against the camera."""
@ -298,10 +298,10 @@ class CalibrateXYView(ActionView):
class MoveInImageCoordinatesView(ActionView): class MoveInImageCoordinatesView(ActionView):
args = { args = {
"x": fields.Float( "x": fields.Float(
metadata={"description": "The number of pixels to move in X"}, required=True, example=100 metadata={"description": "The number of pixels to move in X", "example": 100,}, required=True,
), ),
"y": fields.Float( "y": fields.Float(
metadata={"description": "The number of pixels to move in Y"}, required=True, example=100 metadata={"description": "The number of pixels to move in Y", "example": 100,}, required=True,
), ),
} }
@ -316,10 +316,10 @@ class MoveInImageCoordinatesView(ActionView):
class ClosedLoopMoveInImageCoordinatesView(ActionView): class ClosedLoopMoveInImageCoordinatesView(ActionView):
args = { args = {
"x": fields.Float( "x": fields.Float(
metadata={"description": "The number of pixels to move in X"}, required=True, example=100 metadata={"description": "The number of pixels to move in X", "example": 100,}, required=True,
), ),
"y": fields.Float( "y": fields.Float(
metadata={"description": "The number of pixels to move in Y"}, required=True, example=100 metadata={"description": "The number of pixels to move in Y", "example": 100,}, required=True,
), ),
} }
@ -336,15 +336,14 @@ class ClosedLoopMoveInImageCoordinatesView(ActionView):
class TestClosedLoopSpiralScanView(ActionView): class TestClosedLoopSpiralScanView(ActionView):
args = { args = {
"x_step": fields.Float( "x_step": fields.Float(
metadata={"description": "The number of pixels to move in X"}, required=True, example=100 metadata={"description": "The number of pixels to move in X", "example": 100,}, required=True,
), ),
"y_step": fields.Float( "y_step": fields.Float(
metadata={"description": "The number of pixels to move in Y"}, required=True, example=100 metadata={"description": "The number of pixels to move in Y", "example": 100,}, required=True,
), ),
"N": fields.Int( "N": fields.Int(
metadata={"description": "The number of rings in the spiral scan"}, metadata={"description": "The number of rings in the spiral scan", "example": 100,},
required=True, required=True,
example=3,
), ),
} }

View file

@ -169,39 +169,49 @@ class DeleteLSTView(ActionView):
microscope.save_settings() microscope.save_settings()
percentile_field = fields.Float(
load_default=99.9,
metadata={
"example": 99.9,
"description": (
"A float between 0 and 100 setting the centile to use "
"to measure the white point of the image. A value "
"of 99.9 allows 0.1% of the pixels to be erroneously "
"bright - this helps stability in low light."
),
},
)
class AutoExposureFromRawView(ActionView): class AutoExposureFromRawView(ActionView):
args = { args = {
"target_white_level": fields.Int( "target_white_level": fields.Int(
load_default=700, load_default=700,
example=700, metadata={
description=( "example": 700,
"The pixel value (10-bit format) that we aim for when adjusting shutter/gain." "description": (
), "The pixel value (10-bit format) that we aim for when adjusting shutter/gain."
),
},
), ),
"max_iterations": fields.Int( "max_iterations": fields.Int(
load_default=20, load_default=20,metadata={
description=( "description": (
"The number of adjustments to the camera's settings to make before giving up." "The number of adjustments to the camera's settings to make before giving up."
), ),
},
), ),
"tolerance": fields.Float( "tolerance": fields.Float(
load_default=0.05, load_default=0.05,
example=0.05, metadata={
description=( "example": 0.05,
"We stop adjusting when we get within this fraction of the target " "description": (
"value. It is a number between 0 and 1, usually 0.01--0.1." "We stop adjusting when we get within this fraction of the target "
), "value. It is a number between 0 and 1, usually 0.01--0.1."
), ),
"percentile": fields.Float( },
load_default=99.9,
example=99.9,
description=(
"A float between 0 and 100 setting the centile to use "
"to measure the white point of the image. A value "
"of 99.9 allows 0.1% of the pixels to be erroneously "
"bright - this helps stability in low light."
),
), ),
"percentile": percentile_field,
} }
def post(self, args): def post(self, args):
@ -211,16 +221,7 @@ class AutoExposureFromRawView(ActionView):
class AutoWhiteBalanceFromRawView(ActionView): class AutoWhiteBalanceFromRawView(ActionView):
args = { args = {
"percentile": fields.Float( "percentile": percentile_field,
load_default=99.9,
example=99.9,
description=(
"A float between 0 and 100 setting the centile to use "
"to measure the white point of the image. A value "
"of 99.9 allows 0.1% of the pixels to be erroneously "
"bright - this helps stability in low light."
),
)
} }
def post(self, args): def post(self, args):
@ -231,8 +232,10 @@ class AutoWhiteBalanceFromRawView(ActionView):
class GetRawChannelPercentilesView(ActionView): class GetRawChannelPercentilesView(ActionView):
args = { args = {
"percentile": fields.Float( "percentile": fields.Float(
example=99.9, metadata={
metadata={"description": "A float between 0 and 100 setting the centile to calculate"}, "description": "A float between 0 and 100 setting the centile to calculate",
"example": 99.9,
},
) )
} }
schema = fields.List(fields.Integer) schema = fields.List(fields.Integer)

View file

@ -578,17 +578,17 @@ class ScanExtension(BaseExtension):
class TileScanArgs(FullCaptureArgs): class TileScanArgs(FullCaptureArgs):
namemode = fields.String(load_default="coordinates", example="coordinates") namemode = fields.String(load_default="coordinates", metadata={"example": "coordinates"})
grid = fields.List( grid = fields.List(
fields.Integer(validate=marshmallow.validate.Range(min=1)), fields.Integer(validate=marshmallow.validate.Range(min=1)),
load_default=[3, 3, 3], load_default=[3, 3, 3],
example=[3, 3, 3], metadata={"example": [3, 3, 3]},
) )
style = fields.String(load_default="raster") style = fields.String(load_default="raster")
autofocus_dz = fields.Integer(load_default=50) autofocus_dz = fields.Integer(load_default=50)
fast_autofocus = fields.Boolean(load_default=False) fast_autofocus = fields.Boolean(load_default=False)
stride_size = fields.List( stride_size = fields.List(
fields.Integer, load_default=[2000, 1500, 100], example=[2000, 1500, 100] fields.Integer, load_default=[2000, 1500, 100], metadata={"example":[2000, 1500, 100]}
) )
detect_empty_fields_and_skip_autofocus = fields.Boolean(load_default=False) detect_empty_fields_and_skip_autofocus = fields.Boolean(load_default=False)

View file

@ -24,7 +24,7 @@ class RaiseException(ActionView):
class SleepFor(ActionView): class SleepFor(ActionView):
schema = {"TimeAsleep": fields.Float()} schema = {"TimeAsleep": fields.Float()}
args = {"time": fields.Float(metadata={"description": "Time to sleep, in seconds"}, example=0.5)} args = {"time": fields.Float(metadata={"description": "Time to sleep, in seconds", "example": 0.5})}
def post(self, args): def post(self, args):
sleep_time: int = args.get("time", 0) sleep_time: int = args.get("time", 0)

View file

@ -10,8 +10,8 @@ from openflexure_microscope.api.v2.views.captures import CaptureSchema
class CaptureResizeSchema(Schema): class CaptureResizeSchema(Schema):
width = fields.Integer(example=640, required=True) width = fields.Integer(metadata={"example":640}, required=True)
height = fields.Integer(example=480, required=True) height = fields.Integer(metadata={"example": 480}, required=True)
class BasicCaptureArgs(Schema): class BasicCaptureArgs(Schema):
@ -23,10 +23,10 @@ class BasicCaptureArgs(Schema):
class FullCaptureArgs(BasicCaptureArgs): class FullCaptureArgs(BasicCaptureArgs):
filename = fields.String(example="MyFileName") filename = fields.String(metadata={"example": "MyFileName"})
temporary = fields.Boolean(load_default=False, metadata={"description": "Delete capture on shutdown"}) temporary = fields.Boolean(load_default=False, metadata={"description": "Delete capture on shutdown"})
annotations = fields.Dict(load_default={}, example={"Client": "SwaggerUI"}) annotations = fields.Dict(load_default={}, metadata={"example": {"Client": "SwaggerUI"}})
tags = fields.List(fields.String, load_default=[], example=["docs"]) tags = fields.List(fields.String, load_default=[], metadata={"example": ["docs"]})
class CaptureAPI(ActionView): class CaptureAPI(ActionView):
@ -113,7 +113,7 @@ class GPUPreviewStartAPI(ActionView):
in the format ``[x, y, width, height]``. in the format ``[x, y, width, height]``.
""" """
args = {"window": fields.List(fields.Integer, load_default=[], example=[0, 0, 640, 480])} args = {"window": fields.List(fields.Integer, load_default=[], metadata={"example": [0, 0, 640, 480]})}
def post(self, args): def post(self, args):
""" """

View file

@ -7,11 +7,11 @@ from labthings.views import ActionView
class MoveStageAPI(ActionView): class MoveStageAPI(ActionView):
args = { args = {
"absolute": fields.Boolean( "absolute": fields.Boolean(
load_default=False, example=False, metadata={"description": "Move to an absolute position"} load_default=False, metadata={"description": "Move to an absolute position", "example": False}
), ),
"x": fields.Int(load_default=None, example=100, allow_none=False), "x": fields.Int(load_default=None, metadata={"example": 100}, allow_none=False),
"y": fields.Int(load_default=None, example=100, allow_none=False), "y": fields.Int(load_default=None, metadata={"example": 100}, allow_none=False),
"z": fields.Int(load_default=None, example=20, allow_none=False), "z": fields.Int(load_default=None, metadata={"example": 20}, allow_none=False),
} }
def post(self, args): def post(self, args):

View file

@ -24,7 +24,7 @@ class InstrumentSchema(Schema):
class ImageSchema(Schema): class ImageSchema(Schema):
id = fields.UUID() id = fields.UUID()
time = fields.String(format="date") time = fields.String(metadata={"format": "date"})
format = fields.String() format = fields.String()
name = fields.String() name = fields.String()
tags = fields.List(fields.String()) tags = fields.List(fields.String())

View file

@ -8,9 +8,8 @@ class StageTypeProperty(PropertyView):
schema = fields.String( schema = fields.String(
load_default=None, load_default=None,
example="SangaStage",
validate=validate.OneOf(["SangaStage", "SangaDeltaStage"]), validate=validate.OneOf(["SangaStage", "SangaDeltaStage"]),
metadata={"description": "The translation stage geometry"}, metadata={"description": "The translation stage geometry", "example": "SangaStage",},
allow_none=False, allow_none=False,
) )