summaryrefslogtreecommitdiff
path: root/ui/code_templates.py
blob: 2a3ff0903caef717f77341f3c996cc65036cdc6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""
ui/code_templates.py

Code templates for derived channel kinds.

BUILTIN_TEMPLATES — shown as read-only previews for built-in kinds.
  "Edit as Custom Script" copies the template into custom_script.
  Uses exec-style: assign to `result`.

SCRIPT_TEMPLATES — default starter code shown when user picks a script kind.
  expression  → single Python expression (no assignment)
  function    → auto-wrapped as def compute(x, t): ... use return
  custom_script → exec-style block, assign to `result`

Namespace available in all kinds:
  x      — list of source values in source order
  <name> — each source's channel_id as a named variable (same as x[i])
  t      — elapsed time (seconds)
  math   — Python math module
  vars   — shared SignalProcessor._script_vars dict (read/write)
  state  — per-channel persistent dict (survives between evaluations)

`vars` is the bridge from the Control Panel into Channel math: a button's
"On Action Script" (ui/control_editor.py) and every Channel script here see
the *same* `vars` dict. e.g. a "Zero" button sets
    vars['zero'] = channels.get('force_raw', 0)
and a Channel reads it back with `vars.get('zero', 0)` — see the
"custom_script" template below. Same pattern for an operator-entered
constant like specimen length: a Setpoint control's On Action Script sets
`vars['specimen_length_cm'] = value`, and a Channel divides by it.
"""

BUILTIN_TEMPLATES: dict = {

    "none": """\
result = x[0]
""",

    "scale_offset": """\
# scale/offset also settable from a Control Panel button's On Action Script,
# e.g. vars["offset"] = -x[0]  to zero the reading on press
scale = vars.get("scale", 1.0)
offset = vars.get("offset", 0.0)
result = x[0] * scale + offset
""",

    "derivative": """\
prev_v = state.get("v", x[0])
prev_t = state.get("t", t)
state["v"] = x[0]
state["t"] = t
result = (x[0] - prev_v) / (t - prev_t) if t != prev_t else 0.0
""",

    "derivative_channel": """\
prev_v = state.get("v", x[0])
prev_x = state.get("x", x[1])
state["v"] = x[0]
state["x"] = x[1]
result = (x[0] - prev_v) / (x[1] - prev_x) if x[1] != prev_x else 0.0
""",

    "second_derivative": """\
prev_v   = state.get("v", x[0])
prev_t   = state.get("t", t)
prev_vel = state.get("vel", 0.0)

cur_vel = (x[0] - prev_v) / (t - prev_t) if t != prev_t else 0.0
result  = (cur_vel - prev_vel) / (t - prev_t) if t != prev_t else 0.0

state["v"]   = x[0]
state["t"]   = t
state["vel"] = cur_vel
""",

    "second_derivative_channel": """\
prev_v   = state.get("v", x[0])
prev_x   = state.get("x", x[1])
prev_vel = state.get("vel", 0.0)

cur_vel = (x[0] - prev_v) / (x[1] - prev_x) if x[1] != prev_x else 0.0
result  = (cur_vel - prev_vel) / (x[1] - prev_x) if x[1] != prev_x else 0.0

state["v"]   = x[0]
state["x"]   = x[1]
state["vel"] = cur_vel
""",

    "rms": """\
import math as _math
buf = state.setdefault("buf", [])
buf.append(x[0])
window = 20
if len(buf) > window:
    buf.pop(0)
result = _math.sqrt(sum(v * v for v in buf) / len(buf))
""",

    "power": """\
result = x[0] * x[1]
""",

    "difference": """\
result = x[0] - x[1]
""",

    "sum": """\
result = sum(x)
""",
}


# Default starter code shown when user selects a script kind
SCRIPT_TEMPLATES: dict = {

    "expression": "x[0]",

    "function": """\
# "offset" can be set here or from a Control Panel button's On Action Script
# (vars is the same dict on both sides)
offset = vars.get("offset", 0)
return x[0] - offset
""",

    "custom_script": """\
# Wire a "Zero" button to this: On Action Script -> vars["zero"] = channels.get("<signal_id>", 0)
zero = vars.get("zero", 0)
result = x[0] - zero
""",
}