summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-04-22 14:50:13 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-04-22 14:50:13 -0600
commit99445c6fd2fd4f15df828c79600b96b80fa1cfa6 (patch)
tree22c9933fc6bb942172a1f456bef7a35ec4be1726 /core
parent445403fdc61f4e65736dc65a959f119fc096f4c0 (diff)
Added derived signal to be sources of other derived signals.
Fixed derived signal saving profile. Renamed Signals>Pipeline to Signas>Channels and adding/removing channels feature.
Diffstat (limited to 'core')
-rw-r--r--core/__pycache__/profile.cpython-312.pycbin14026 -> 14149 bytes
-rw-r--r--core/__pycache__/signal_processor.cpython-312.pycbin23674 -> 23682 bytes
-rw-r--r--core/profile.py21
-rw-r--r--core/signal_processor.py13
4 files changed, 16 insertions, 18 deletions
diff --git a/core/__pycache__/profile.cpython-312.pyc b/core/__pycache__/profile.cpython-312.pyc
index 0fee9d9..208b48b 100644
--- a/core/__pycache__/profile.cpython-312.pyc
+++ b/core/__pycache__/profile.cpython-312.pyc
Binary files differ
diff --git a/core/__pycache__/signal_processor.cpython-312.pyc b/core/__pycache__/signal_processor.cpython-312.pyc
index adcf10d..e914490 100644
--- a/core/__pycache__/signal_processor.cpython-312.pyc
+++ b/core/__pycache__/signal_processor.cpython-312.pyc
Binary files differ
diff --git a/core/profile.py b/core/profile.py
index 2a70370..ef8c55b 100644
--- a/core/profile.py
+++ b/core/profile.py
@@ -231,6 +231,16 @@ class ProfileManager:
except Exception:
pass
+ # Clear all existing devices — profile defines the complete device set
+ for dev in list(registry.all_instances()):
+ try:
+ dev.disconnect()
+ except Exception:
+ pass
+ registry.remove_instance(dev.info.device_id)
+ if engine is not None:
+ engine.remove_device(dev.info.device_id)
+
for dev_cfg in profile.devices:
dev_type = dev_cfg.get("device_type")
dev_id = dev_cfg.get("device_id")
@@ -241,17 +251,6 @@ class ProfileManager:
print(f"[Profile] Unknown device type: {dev_type}")
continue
try:
- # Replace existing device so saved config takes effect
- existing = registry.get_instance(dev_id)
- if existing is not None:
- try:
- existing.disconnect()
- except Exception:
- pass
- registry.remove_instance(dev_id)
- if engine is not None:
- engine.remove_device(dev_id)
-
kwargs = {k: v for k, v in dev_cfg.items() if k != "device_type"}
dev = factory(**kwargs)
registry.add_instance(dev)
diff --git a/core/signal_processor.py b/core/signal_processor.py
index 4161d4d..0d4ed39 100644
--- a/core/signal_processor.py
+++ b/core/signal_processor.py
@@ -10,7 +10,7 @@ Provides two capabilities:
2. DERIVED CHANNELS — virtual channels computed from one or more physical
channels. Each derived channel runs a user-defined function every time
- new data arrives. Built-ins: velocity/acceleration from displacement,
+ new data arrives. Built-ins: derivative/second_derivative from displacement,
power from voltage+current, RMS, etc. Custom: arbitrary Python snippet.
Architecture
@@ -195,8 +195,8 @@ class DerivedChannel:
A virtual channel computed from one or more physical channels.
kind options:
- "velocity" — derivative of a displacement source
- "acceleration" — second derivative of a displacement source
+ "derivative" — derivative of a source (dy/dt)
+ "second_derivative" — second derivative of a source (d²y/dt²)
"power" — voltage_source * current_source
"rms" — rolling RMS of a source (window samples)
"expression" — arbitrary Python expression string
@@ -418,7 +418,7 @@ class SignalProcessor(QObject):
return None
return dc._fn(inputs, t)
- elif dc.kind == "velocity":
+ elif dc.kind == "derivative":
# derivative of source[0]
src = dc.sources[0] if dc.sources else None
if src is None: return None
@@ -428,12 +428,11 @@ class SignalProcessor(QObject):
if prev_t is None or t == prev_t: return 0.0
return (inputs[0] - prev_v) / (t - prev_t)
- elif dc.kind == "acceleration":
- # second derivative — derivative of velocity
+ elif dc.kind == "second_derivative":
+ # second derivative — derivative of derivative
src = dc.sources[0] if dc.sources else None
if src is None: return None
state = dc.params.setdefault("_state", {})
- # First get velocity
prev_t = state.get("t"); prev_v = state.get("v")
cur_vel = 0.0
if prev_t is not None and t != prev_t: