Skip to content

Commit a9b6cf5

Browse files
author
Joel Collins
committed
First draft of auto-property builder
1 parent 12b6dda commit a9b6cf5

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

examples/builder.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import uuid
2+
3+
from labthings.server.quick import create_app
4+
from labthings.server.view import View
5+
from labthings.server.decorators import (
6+
ThingProperty,
7+
PropertySchema,
8+
use_args,
9+
)
10+
11+
from labthings.server.types import value_to_field
12+
13+
from components.pdf_component import PdfComponent
14+
15+
16+
class BasePropertyResource(View):
17+
def __init__(self):
18+
super().__init__()
19+
"""
20+
Properties to be added by constructor function:
21+
property_object: Object containing the property
22+
property_name: String name of property of object
23+
"""
24+
25+
def get(self):
26+
return getattr(self.property_object, self.property_name)
27+
28+
def post(self, args):
29+
setattr(self.property_object, self.property_name, args)
30+
return getattr(self.property_object, self.property_name)
31+
32+
33+
def gen_property(property_object, property_name, name: str = None, post=True):
34+
35+
# Create a class name
36+
if not name:
37+
name = type(property_object).__name__ + f"_{property_name}"
38+
39+
# Generate a basic property class
40+
generated_class = type(
41+
name,
42+
(BasePropertyResource, object),
43+
{"property_object": property_object, "property_name": property_name,},
44+
)
45+
46+
# Override read-write capabilities
47+
if not post:
48+
generated_class.post = None
49+
50+
# Add decorators for arguments etc
51+
initial_property_value = getattr(property_object, property_name)
52+
generated_class = PropertySchema(value_to_field(initial_property_value))(
53+
generated_class
54+
)
55+
generated_class = ThingProperty(generated_class)
56+
57+
return generated_class
58+
59+
60+
# Create LabThings Flask app
61+
app, labthing = create_app(
62+
__name__,
63+
prefix="/api",
64+
title=f"My Lab Device API",
65+
description="Test LabThing-based API",
66+
version="0.1.0",
67+
)
68+
69+
# Attach an instance of our component
70+
my_component = PdfComponent()
71+
labthing.add_component(my_component, "org.labthings.example.mycomponent")
72+
73+
# Add routes for the API views we created
74+
labthing.add_view(gen_property(my_component, "magic_denoise"), "/denoise")
75+
76+
# Start the app
77+
if __name__ == "__main__":
78+
app.run(host="0.0.0.0", port="5000", threaded=True, debug=True, use_reloader=False)

examples/components/__init__.py

Whitespace-only changes.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import random
2+
import math
3+
import time
4+
5+
"""
6+
Class for our lab component functionality. This could include serial communication,
7+
equipment API calls, network requests, or a "virtual" device as seen here.
8+
"""
9+
10+
11+
class PdfComponent:
12+
def __init__(self):
13+
self.x_range = range(-100, 100)
14+
self.magic_denoise = 200
15+
16+
def noisy_pdf(self, x, mu=0.0, sigma=25.0):
17+
"""
18+
Generate a noisy gaussian function (to act as some pretend data)
19+
20+
Our noise is inversely proportional to self.magic_denoise
21+
"""
22+
x = float(x - mu) / sigma
23+
return (
24+
math.exp(-x * x / 2.0) / math.sqrt(2.0 * math.pi) / sigma
25+
+ (1 / self.magic_denoise) * random.random()
26+
)
27+
28+
@property
29+
def data(self):
30+
"""Return a 1D data trace."""
31+
return [self.noisy_pdf(x) for x in self.x_range]
32+
33+
def average_data(self, n: int):
34+
"""Average n-sets of data. Emulates a measurement that may take a while."""
35+
summed_data = self.data
36+
37+
for i in range(n):
38+
summed_data = [summed_data[i] + el for i, el in enumerate(self.data)]
39+
time.sleep(0.25)
40+
41+
summed_data = [i / n for i in summed_data]
42+
43+
return summed_data

0 commit comments

Comments
 (0)