removed old style syntax
- removed secop/metaclass.py - moved code from ModuleMeta to modules.HasAccessibles.__init_subclass__ - reworked properties: assignment obj.property = value now always allowed - reworked Parameters and Command to be true descriptors - Command must now be solely used as decorator - renamed 'usercommand' to 'Command' - command methods no longer start with 'do_' - reworked mechanism to determine accessible order: the attribute paramOrder, if given, determines order of accessibles + fixed some issues makeing the IDE more happy + simplified code for StatusType and added a test for it Change-Id: I8045cf38ee6f4d4862428272df0b12a7c8abaca7 Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/25049 Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de> Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de> Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
@ -27,18 +27,16 @@ from math import atan
|
||||
|
||||
from secop.datatypes import EnumType, FloatRange, TupleOf, StringType, BoolType
|
||||
from secop.lib import clamp, mkthread
|
||||
from secop.modules import Drivable, Override, Parameter
|
||||
from secop.modules import Drivable, Parameter, Command
|
||||
|
||||
# test custom property (value.test can be changed in config file)
|
||||
from secop.properties import Property
|
||||
|
||||
Parameter.properties['test'] = Property('A Property for testing purposes', StringType(), default='', export=True)
|
||||
Parameter.propertyDict['test'] = Property('A Property for testing purposes', StringType(), default='', export=True)
|
||||
|
||||
|
||||
class CryoBase(Drivable):
|
||||
properties = {
|
||||
'is_cryo': Property('private Flag if this is a cryostat', BoolType(), default=True, export=True),
|
||||
}
|
||||
is_cryo = Property('private Flag if this is a cryostat', BoolType(), default=True, export=True)
|
||||
|
||||
|
||||
class Cryostat(CryoBase):
|
||||
@ -49,93 +47,88 @@ class Cryostat(CryoBase):
|
||||
- thermal transfer between regulation and samplen
|
||||
"""
|
||||
|
||||
parameters = dict(
|
||||
jitter=Parameter("amount of random noise on readout values",
|
||||
datatype=FloatRange(0, 1), unit="K",
|
||||
default=0.1, readonly=False, export=False,
|
||||
),
|
||||
T_start=Parameter("starting temperature for simulation",
|
||||
datatype=FloatRange(0), default=10,
|
||||
export=False,
|
||||
),
|
||||
looptime=Parameter("timestep for simulation",
|
||||
datatype=FloatRange(0.01, 10), unit="s", default=1,
|
||||
readonly=False, export=False,
|
||||
jitter = Parameter("amount of random noise on readout values",
|
||||
datatype=FloatRange(0, 1), unit="K",
|
||||
default=0.1, readonly=False, export=False,
|
||||
),
|
||||
ramp=Parameter("ramping speed of the setpoint",
|
||||
datatype=FloatRange(0, 1e3), unit="K/min", default=1,
|
||||
readonly=False,
|
||||
),
|
||||
setpoint=Parameter("current setpoint during ramping else target",
|
||||
datatype=FloatRange(), default=1, unit='K',
|
||||
),
|
||||
maxpower=Parameter("Maximum heater power",
|
||||
datatype=FloatRange(0), default=1, unit="W",
|
||||
readonly=False,
|
||||
group='heater_settings',
|
||||
),
|
||||
heater=Parameter("current heater setting",
|
||||
datatype=FloatRange(0, 100), default=0, unit="%",
|
||||
group='heater_settings',
|
||||
),
|
||||
heaterpower=Parameter("current heater power",
|
||||
datatype=FloatRange(0), default=0, unit="W",
|
||||
group='heater_settings',
|
||||
),
|
||||
target=Override("target temperature",
|
||||
datatype=FloatRange(0), default=0, unit="K",
|
||||
T_start = Parameter("starting temperature for simulation",
|
||||
datatype=FloatRange(0), default=10,
|
||||
export=False,
|
||||
),
|
||||
looptime = Parameter("timestep for simulation",
|
||||
datatype=FloatRange(0.01, 10), unit="s", default=1,
|
||||
readonly=False, export=False,
|
||||
),
|
||||
ramp = Parameter("ramping speed of the setpoint",
|
||||
datatype=FloatRange(0, 1e3), unit="K/min", default=1,
|
||||
readonly=False,
|
||||
),
|
||||
value=Override("regulation temperature",
|
||||
datatype=FloatRange(0), default=0, unit="K",
|
||||
test='TEST',
|
||||
setpoint = Parameter("current setpoint during ramping else target",
|
||||
datatype=FloatRange(), default=1, unit='K',
|
||||
),
|
||||
maxpower = Parameter("Maximum heater power",
|
||||
datatype=FloatRange(0), default=1, unit="W",
|
||||
readonly=False,
|
||||
group='heater_settings',
|
||||
),
|
||||
heater = Parameter("current heater setting",
|
||||
datatype=FloatRange(0, 100), default=0, unit="%",
|
||||
group='heater_settings',
|
||||
),
|
||||
heaterpower = Parameter("current heater power",
|
||||
datatype=FloatRange(0), default=0, unit="W",
|
||||
group='heater_settings',
|
||||
),
|
||||
target = Parameter("target temperature",
|
||||
datatype=FloatRange(0), default=0, unit="K",
|
||||
readonly=False,
|
||||
),
|
||||
value = Parameter("regulation temperature",
|
||||
datatype=FloatRange(0), default=0, unit="K",
|
||||
test='TEST',
|
||||
),
|
||||
pid = Parameter("regulation coefficients",
|
||||
datatype=TupleOf(FloatRange(0), FloatRange(0, 100),
|
||||
FloatRange(0, 100)),
|
||||
default=(40, 10, 2), readonly=False,
|
||||
group='pid',
|
||||
),
|
||||
pid=Parameter("regulation coefficients",
|
||||
datatype=TupleOf(FloatRange(0), FloatRange(0, 100),
|
||||
FloatRange(0, 100)),
|
||||
default=(40, 10, 2), readonly=False,
|
||||
# pylint: disable=invalid-name
|
||||
p = Parameter("regulation coefficient 'p'",
|
||||
datatype=FloatRange(0), default=40, unit="%/K", readonly=False,
|
||||
group='pid',
|
||||
),
|
||||
p=Parameter("regulation coefficient 'p'",
|
||||
datatype=FloatRange(0), default=40, unit="%/K", readonly=False,
|
||||
group='pid',
|
||||
),
|
||||
i=Parameter("regulation coefficient 'i'",
|
||||
datatype=FloatRange(0, 100), default=10, readonly=False,
|
||||
group='pid',
|
||||
),
|
||||
d=Parameter("regulation coefficient 'd'",
|
||||
datatype=FloatRange(0, 100), default=2, readonly=False,
|
||||
group='pid',
|
||||
),
|
||||
mode=Parameter("mode of regulation",
|
||||
datatype=EnumType('mode', ramp=None, pid=None, openloop=None),
|
||||
default='ramp',
|
||||
readonly=False,
|
||||
),
|
||||
pollinterval=Override("polling interval",
|
||||
datatype=FloatRange(0), default=5,
|
||||
),
|
||||
tolerance=Parameter("temperature range for stability checking",
|
||||
datatype=FloatRange(0, 100), default=0.1, unit='K',
|
||||
i = Parameter("regulation coefficient 'i'",
|
||||
datatype=FloatRange(0, 100), default=10, readonly=False,
|
||||
group='pid',
|
||||
),
|
||||
d = Parameter("regulation coefficient 'd'",
|
||||
datatype=FloatRange(0, 100), default=2, readonly=False,
|
||||
group='pid',
|
||||
),
|
||||
mode = Parameter("mode of regulation",
|
||||
datatype=EnumType('mode', ramp=None, pid=None, openloop=None),
|
||||
default='ramp',
|
||||
readonly=False,
|
||||
),
|
||||
pollinterval = Parameter("polling interval",
|
||||
datatype=FloatRange(0), default=5,
|
||||
),
|
||||
tolerance = Parameter("temperature range for stability checking",
|
||||
datatype=FloatRange(0, 100), default=0.1, unit='K',
|
||||
readonly=False,
|
||||
group='stability',
|
||||
),
|
||||
window = Parameter("time window for stability checking",
|
||||
datatype=FloatRange(1, 900), default=30, unit='s',
|
||||
readonly=False,
|
||||
group='stability',
|
||||
),
|
||||
timeout = Parameter("max waiting time for stabilisation check",
|
||||
datatype=FloatRange(1, 36000), default=900, unit='s',
|
||||
readonly=False,
|
||||
group='stability',
|
||||
),
|
||||
window=Parameter("time window for stability checking",
|
||||
datatype=FloatRange(1, 900), default=30, unit='s',
|
||||
readonly=False,
|
||||
group='stability',
|
||||
),
|
||||
timeout=Parameter("max waiting time for stabilisation check",
|
||||
datatype=FloatRange(1, 36000), default=900, unit='s',
|
||||
readonly=False,
|
||||
group='stability',
|
||||
),
|
||||
)
|
||||
commands = dict(
|
||||
stop=Override(
|
||||
"Stop ramping the setpoint\n\nby setting the current setpoint as new target"),
|
||||
)
|
||||
|
||||
def initModule(self):
|
||||
self._stopflag = False
|
||||
@ -180,8 +173,11 @@ class Cryostat(CryoBase):
|
||||
def read_pid(self):
|
||||
return (self.p, self.i, self.d)
|
||||
|
||||
def do_stop(self):
|
||||
# stop the ramp by setting current setpoint as target
|
||||
@Command()
|
||||
def stop(self):
|
||||
"""Stop ramping the setpoint
|
||||
|
||||
by setting the current setpoint as new target"""
|
||||
# XXX: discussion: take setpoint or current value ???
|
||||
self.write_target(self.setpoint)
|
||||
|
||||
|
@ -28,42 +28,39 @@ import time
|
||||
from secop.datatypes import ArrayOf, BoolType, EnumType, \
|
||||
FloatRange, IntRange, StringType, StructOf, TupleOf
|
||||
from secop.lib.enum import Enum
|
||||
from secop.modules import Drivable, Override, Parameter as SECoP_Parameter, Readable
|
||||
from secop.modules import Drivable, Parameter as SECoP_Parameter, Readable
|
||||
from secop.properties import Property
|
||||
|
||||
|
||||
class Parameter(SECoP_Parameter):
|
||||
properties = {
|
||||
'test' : Property('A property for testing purposes', StringType(), default='', mandatory=False, extname='test'),
|
||||
}
|
||||
test = Property('A property for testing purposes', StringType(), default='', mandatory=False, extname='test')
|
||||
|
||||
|
||||
PERSIST = 101
|
||||
|
||||
|
||||
class Switch(Drivable):
|
||||
"""switch it on or off....
|
||||
"""
|
||||
parameters = {
|
||||
'value': Override('current state (on or off)',
|
||||
|
||||
value = Parameter('current state (on or off)',
|
||||
datatype=EnumType(on=1, off=0), default=0,
|
||||
)
|
||||
target = Parameter('wanted state (on or off)',
|
||||
datatype=EnumType(on=1, off=0), default=0,
|
||||
),
|
||||
'target': Override('wanted state (on or off)',
|
||||
datatype=EnumType(on=1, off=0), default=0,
|
||||
readonly=False,
|
||||
),
|
||||
'switch_on_time': Parameter('seconds to wait after activating the switch',
|
||||
readonly=False,
|
||||
)
|
||||
switch_on_time = Parameter('seconds to wait after activating the switch',
|
||||
datatype=FloatRange(0, 60), unit='s',
|
||||
default=10, export=False,
|
||||
)
|
||||
switch_off_time = Parameter('cool-down time in seconds',
|
||||
datatype=FloatRange(0, 60), unit='s',
|
||||
default=10, export=False,
|
||||
),
|
||||
'switch_off_time': Parameter('cool-down time in seconds',
|
||||
datatype=FloatRange(0, 60), unit='s',
|
||||
default=10, export=False,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
properties = {
|
||||
'description' : Property('The description of the Module', StringType(),
|
||||
default='no description', mandatory=False, extname='description'),
|
||||
}
|
||||
description = Property('The description of the Module', StringType(),
|
||||
default='no description', mandatory=False, extname='description')
|
||||
|
||||
def read_value(self):
|
||||
# could ask HW
|
||||
@ -109,30 +106,29 @@ class Switch(Drivable):
|
||||
class MagneticField(Drivable):
|
||||
"""a liquid magnet
|
||||
"""
|
||||
parameters = {
|
||||
'value': Override('current field in T',
|
||||
|
||||
value = Parameter('current field in T',
|
||||
unit='T', datatype=FloatRange(-15, 15), default=0,
|
||||
)
|
||||
target = Parameter('target field in T',
|
||||
unit='T', datatype=FloatRange(-15, 15), default=0,
|
||||
),
|
||||
'target': Override('target field in T',
|
||||
unit='T', datatype=FloatRange(-15, 15), default=0,
|
||||
readonly=False,
|
||||
),
|
||||
'ramp': Parameter('ramping speed',
|
||||
unit='T/min', datatype=FloatRange(0, 1), default=0.1,
|
||||
readonly=False,
|
||||
),
|
||||
'mode': Parameter('what to do after changing field',
|
||||
default=1, datatype=EnumType(persistent=1, hold=0),
|
||||
readonly=False,
|
||||
),
|
||||
'heatswitch': Parameter('name of heat switch device',
|
||||
datatype=StringType(), export=False,
|
||||
),
|
||||
}
|
||||
readonly=False,
|
||||
)
|
||||
ramp = Parameter('ramping speed',
|
||||
unit='T/min', datatype=FloatRange(0, 1), default=0.1,
|
||||
readonly=False,
|
||||
)
|
||||
mode = Parameter('what to do after changing field',
|
||||
default=1, datatype=EnumType(persistent=1, hold=0),
|
||||
readonly=False,
|
||||
)
|
||||
heatswitch = Parameter('name of heat switch device',
|
||||
datatype=StringType(), export=False,
|
||||
)
|
||||
|
||||
Status = Enum(Drivable.Status, PERSIST=PERSIST, PREPARE=301, RAMPING=302, FINISH=303)
|
||||
overrides = {
|
||||
'status' : Override(datatype=TupleOf(EnumType(Status), StringType())),
|
||||
}
|
||||
|
||||
status = Parameter(datatype=TupleOf(EnumType(Status), StringType()))
|
||||
|
||||
def initModule(self):
|
||||
self._state = Enum('state', idle=1, switch_on=2, switch_off=3, ramp=4).idle
|
||||
@ -202,21 +198,20 @@ class MagneticField(Drivable):
|
||||
time.sleep(max(0.01, ts + loopdelay - time.time()))
|
||||
self.log.error(self, 'main thread exited unexpectedly!')
|
||||
|
||||
def do_stop(self):
|
||||
def stop(self):
|
||||
self.write_target(self.read_value())
|
||||
|
||||
|
||||
class CoilTemp(Readable):
|
||||
"""a coil temperature
|
||||
"""
|
||||
parameters = {
|
||||
'value': Override('Coil temperatur',
|
||||
unit='K', datatype=FloatRange(), default=0,
|
||||
),
|
||||
'sensor': Parameter("Sensor number or calibration id",
|
||||
datatype=StringType(), readonly=True,
|
||||
),
|
||||
}
|
||||
|
||||
value = Parameter('Coil temperatur',
|
||||
unit='K', datatype=FloatRange(), default=0,
|
||||
)
|
||||
sensor = Parameter("Sensor number or calibration id",
|
||||
datatype=StringType(), readonly=True,
|
||||
)
|
||||
|
||||
def read_value(self):
|
||||
return round(2.3 + random.random(), 3)
|
||||
@ -225,18 +220,17 @@ class CoilTemp(Readable):
|
||||
class SampleTemp(Drivable):
|
||||
"""a sample temperature
|
||||
"""
|
||||
parameters = {
|
||||
'value': Override('Sample temperature',
|
||||
unit='K', datatype=FloatRange(), default=10,
|
||||
),
|
||||
'sensor': Parameter("Sensor number or calibration id",
|
||||
datatype=StringType(), readonly=True,
|
||||
),
|
||||
'ramp': Parameter('moving speed in K/min',
|
||||
datatype=FloatRange(0, 100), unit='K/min', default=0.1,
|
||||
readonly=False,
|
||||
),
|
||||
}
|
||||
|
||||
value = Parameter('Sample temperature',
|
||||
unit='K', datatype=FloatRange(), default=10,
|
||||
)
|
||||
sensor = Parameter("Sensor number or calibration id",
|
||||
datatype=StringType(), readonly=True,
|
||||
)
|
||||
ramp = Parameter('moving speed in K/min',
|
||||
datatype=FloatRange(0, 100), unit='K/min', default=0.1,
|
||||
readonly=False,
|
||||
)
|
||||
|
||||
def initModule(self):
|
||||
_thread = threading.Thread(target=self._thread)
|
||||
@ -272,20 +266,19 @@ class Label(Readable):
|
||||
of several subdevices. used for demoing connections between
|
||||
modules.
|
||||
"""
|
||||
parameters = {
|
||||
'system': Parameter("Name of the magnet system",
|
||||
datatype=StringType(), export=False,
|
||||
),
|
||||
'subdev_mf': Parameter("name of subdevice for magnet status",
|
||||
datatype=StringType(), export=False,
|
||||
),
|
||||
'subdev_ts': Parameter("name of subdevice for sample temp",
|
||||
datatype=StringType(), export=False,
|
||||
),
|
||||
'value': Override("final value of label string", default='',
|
||||
datatype=StringType(),
|
||||
),
|
||||
}
|
||||
|
||||
system = Parameter("Name of the magnet system",
|
||||
datatype=StringType(), export=False,
|
||||
)
|
||||
subdev_mf = Parameter("name of subdevice for magnet status",
|
||||
datatype=StringType(), export=False,
|
||||
)
|
||||
subdev_ts = Parameter("name of subdevice for sample temp",
|
||||
datatype=StringType(), export=False,
|
||||
)
|
||||
value = Parameter("final value of label string", default='',
|
||||
datatype=StringType(),
|
||||
)
|
||||
|
||||
def read_value(self):
|
||||
strings = [self.system]
|
||||
@ -317,29 +310,25 @@ class Label(Readable):
|
||||
class DatatypesTest(Readable):
|
||||
"""for demoing all datatypes
|
||||
"""
|
||||
parameters = {
|
||||
'enum': Parameter('enum', datatype=EnumType(boo=None, faar=None, z=9),
|
||||
readonly=False, default=1),
|
||||
'tupleof': Parameter('tuple of int, float and str',
|
||||
datatype=TupleOf(IntRange(), FloatRange(),
|
||||
StringType()),
|
||||
readonly=False, default=(1, 2.3, 'a')),
|
||||
'arrayof': Parameter('array: 2..3 times bool',
|
||||
datatype=ArrayOf(BoolType(), 2, 3),
|
||||
readonly=False, default=[1, 0, 1]),
|
||||
'intrange': Parameter('intrange', datatype=IntRange(2, 9),
|
||||
readonly=False, default=4),
|
||||
'floatrange': Parameter('floatrange', datatype=FloatRange(-1, 1),
|
||||
readonly=False, default=0, ),
|
||||
'struct': Parameter('struct(a=str, b=int, c=bool)',
|
||||
datatype=StructOf(a=StringType(), b=IntRange(),
|
||||
c=BoolType()),
|
||||
),
|
||||
}
|
||||
|
||||
enum = Parameter('enum', datatype=EnumType(boo=None, faar=None, z=9),
|
||||
readonly=False, default=1)
|
||||
tupleof = Parameter('tuple of int, float and str',
|
||||
datatype=TupleOf(IntRange(), FloatRange(),
|
||||
StringType()),
|
||||
readonly=False, default=(1, 2.3, 'a'))
|
||||
arrayof = Parameter('array: 2..3 times bool',
|
||||
datatype=ArrayOf(BoolType(), 2, 3),
|
||||
readonly=False, default=[1, 0, 1])
|
||||
intrange = Parameter('intrange', datatype=IntRange(2, 9),
|
||||
readonly=False, default=4)
|
||||
floatrange = Parameter('floatrange', datatype=FloatRange(-1, 1),
|
||||
readonly=False, default=0)
|
||||
struct = Parameter('struct(a=str, b=int, c=bool)',
|
||||
datatype=StructOf(a=StringType(), b=IntRange(),
|
||||
c=BoolType()))
|
||||
|
||||
|
||||
class ArrayTest(Readable):
|
||||
parameters = {
|
||||
"x": Parameter('value', datatype=ArrayOf(FloatRange(), 0, 100000),
|
||||
default = 100000 * [0]),
|
||||
}
|
||||
x = Parameter('value', datatype=ArrayOf(FloatRange(), 0, 100000),
|
||||
default=100000 * [0])
|
||||
|
@ -24,7 +24,7 @@
|
||||
import random
|
||||
|
||||
from secop.datatypes import FloatRange, StringType
|
||||
from secop.modules import Communicator, Drivable, Parameter, Readable, Override
|
||||
from secop.modules import Communicator, Drivable, Parameter, Readable
|
||||
from secop.params import Command
|
||||
|
||||
|
||||
@ -45,11 +45,10 @@ class Heater(Drivable):
|
||||
class name indicates it to be some heating element,
|
||||
but the implementation may do anything
|
||||
"""
|
||||
parameters = {
|
||||
'maxheaterpower': Parameter('maximum allowed heater power',
|
||||
datatype=FloatRange(0, 100), unit='W',
|
||||
),
|
||||
}
|
||||
|
||||
maxheaterpower = Parameter('maximum allowed heater power',
|
||||
datatype=FloatRange(0, 100), unit='W',
|
||||
)
|
||||
|
||||
def read_value(self):
|
||||
return round(100 * random.random(), 1)
|
||||
@ -64,22 +63,21 @@ class Temp(Drivable):
|
||||
class name indicates it to be some temperature controller,
|
||||
but the implementation may do anything
|
||||
"""
|
||||
parameters = {
|
||||
'sensor': Parameter(
|
||||
"Sensor number or calibration id",
|
||||
datatype=StringType(
|
||||
8,
|
||||
16),
|
||||
readonly=True,
|
||||
),
|
||||
'target': Override(
|
||||
"Target temperature",
|
||||
default=300.0,
|
||||
datatype=FloatRange(0),
|
||||
readonly=False,
|
||||
unit='K',
|
||||
),
|
||||
}
|
||||
|
||||
sensor = Parameter(
|
||||
"Sensor number or calibration id",
|
||||
datatype=StringType(
|
||||
8,
|
||||
16),
|
||||
readonly=True,
|
||||
)
|
||||
target = Parameter(
|
||||
"Target temperature",
|
||||
default=300.0,
|
||||
datatype=FloatRange(0),
|
||||
readonly=False,
|
||||
unit='K',
|
||||
)
|
||||
|
||||
def read_value(self):
|
||||
return round(100 * random.random(), 1)
|
||||
@ -90,8 +88,8 @@ class Temp(Drivable):
|
||||
|
||||
class Lower(Communicator):
|
||||
"""Communicator returning a lowercase version of the request"""
|
||||
command = {
|
||||
'communicate': Command('lowercase a string', argument=StringType(), result=StringType(), export='communicate'),
|
||||
}
|
||||
def do_communicate(self, request):
|
||||
return str(request).lower()
|
||||
|
||||
@Command(argument=StringType(), result=StringType(), export='communicate')
|
||||
def communicate(self, command):
|
||||
"""lowercase a string"""
|
||||
return str(command).lower()
|
||||
|
Reference in New Issue
Block a user