summaryrefslogtreecommitdiff
path: root/ui/code_templates.py
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-06-09 22:14:20 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-06-09 22:14:20 -0600
commit7aec470acd69e9c1810b40aa5eea9b96b9eb73ad (patch)
tree9146091077ec64ed1437621ebf2725edf987801f /ui/code_templates.py
parentb138e72d6f81cf58f27c6c1e4ce65cfebbb58624 (diff)
Scripting: named signal vars, shared vars dict, control scripts, code templates
- Named variables in expressions: source channel IDs injected as Python identifiers alongside x[] (e.g. write `A0 * 2` instead of `x[0] * 2`) - Shared `vars` dict on SignalProcessor accessible from all expressions, functions, and control scripts; persisted in .labdaq profiles - Per-derived-channel `state` dict for persistent computation state in custom scripts - Control widgets gain optional on_action_script (Python snippet with value, vars, channels, math in scope); syntax-checked in editor dialog - Built-in derived kinds (derivative, rms, power, etc.) now show their Python implementation as read-only code previews; "Edit as Custom Script" converts to custom_script kind with template pre-filled Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'ui/code_templates.py')
-rw-r--r--ui/code_templates.py70
1 files changed, 70 insertions, 0 deletions
diff --git a/ui/code_templates.py b/ui/code_templates.py
new file mode 100644
index 0000000..0863e62
--- /dev/null
+++ b/ui/code_templates.py
@@ -0,0 +1,70 @@
+"""
+ui/code_templates.py
+
+Python code templates for built-in derived channel kinds.
+Shown as read-only previews in the UI; clicking "Edit as Custom Script"
+converts the channel to custom_script kind with the template pre-filled.
+
+Templates use the enhanced expression namespace:
+ x — list of source values in order
+ <name> — each source's channel_id as a named variable
+ t — elapsed time (seconds)
+ math — Python math module
+ vars — shared SignalProcessor._script_vars dict (read/write)
+ state — per-channel persistent dict (survives between evaluations)
+ result — assign the computed value here (expression-style exec)
+"""
+
+BUILTIN_TEMPLATES: dict = {
+
+ "derivative": """\
+# dy/dt — backward finite difference
+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
+""",
+
+ "second_derivative": """\
+# d²y/dt² — two-pass finite difference
+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
+""",
+
+ "rms": """\
+# Rolling RMS over a sliding window
+import math as _math
+buf = state.setdefault("buf", [])
+buf.append(x[0])
+window = 20 # adjust window size (samples) here
+if len(buf) > window:
+ buf.pop(0)
+result = _math.sqrt(sum(v * v for v in buf) / len(buf))
+""",
+
+ "power": """\
+# Electrical power P = V × I
+# source 0 = voltage, source 1 = current
+result = x[0] * x[1]
+""",
+
+ "difference": """\
+# Difference A − B
+# source 0 = A, source 1 = B
+result = x[0] - x[1]
+""",
+
+ "sum": """\
+# Sum of all sources
+result = sum(x)
+""",
+}