Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

neuroloop

A composable framework for building, simulating, and formally bounding closed-loop neuromodulation pipelines.

sense → decode → decide → stimulate — as a typed dataflow graph, with compile-time latency budgets and runtime-enforced safety envelopes.


Why this exists

Closed-loop neuromodulation (responsive DBS, closed-loop seizure abortion, adaptive tremor suppression) is held back by software, not silicon. The control loop has to:

  • run deterministically within a hard deadline (sense-to-stim latency of tens of milliseconds),
  • never emit a stimulation command that exceeds tissue-safety limits (charge density, amplitude, charge-per-phase), and
  • be auditable — every decision traceable, every bound provable before the device is ever near a patient.

Today that logic is hand-rolled per device, per lab, with safety checks scattered through firmware and latency budgets verified by hope. neuroloop makes the pipeline a first-class, typed, analyzable object: you compose stages, and the framework statically rejects graphs that can't meet their deadline or could violate a safety envelope — before you ever run them.

Think of it as "LangChain for closed-loop neural control" — composable stages over a messy substrate — except the substrate is a real-time control loop and the guarantees are latency and safety, not prompts.

What it is (and isn't)

  • ✅ A framework: typed SignalStageGraph composition.
  • ✅ A static analyzer: end-to-end latency budgeting + safety-envelope feasibility, checked at graph-build time.
  • ✅ A deterministic simulator: a time-triggered scheduler that runs the graph against a numerical model of neural tissue, so you can validate a closed loop with zero hardware.
  • Honest about its scope (see below).

Honesty boundary. neuroloop's runtime is a deterministic simulation of a time-triggered control loop running in CPython — it models and bounds timing, it is not a hard real-time operating system. The WCET (worst-case execution time) numbers a stage declares are contracts you assert and the analyzer reasons about, not measured on certified hardware. The value here is the abstractions, the static analysis, and the closed-loop simulation — the layer where most closed-loop neuro bugs actually live — not a flight-qualified scheduler. Porting the same typed graph onto an RTOS HAL is explicitly future work.

The core idea

A pipeline is a list of stages, each declaring its I/O signal types and a worst-case execution time:

from neuroloop import Graph, SignalType
from neuroloop.stages import BandPower, ProportionalController, Stimulator
from neuroloop.safety import SafetyEnvelope

lfp = SignalType("lfp", channels=1, fs=1000.0, units="uV")

env = SafetyEnvelope(
    max_amplitude_mA=3.0,
    electrode_area_cm2=0.06,      # typical DBS contact
    pulse_width_us=60.0,
    max_charge_density_uC_cm2=30.0,   # Shannon-safe limit
)

graph = (
    Graph(input_type=lfp, deadline_ms=50.0)
    .then(BandPower(band_hz=(4, 6), wcet_us=200))      # tremor-band power
    .then(ProportionalController(gain=1.2, wcet_us=50))
    .then(Stimulator(envelope=env, wcet_us=80))
)

graph.check()   # raises if latency budget blown OR envelope infeasible

graph.check() is the point of the whole thing. It:

  1. verifies every stage's output type matches the next stage's input type,
  2. sums declared WCETs and proves the loop fits inside deadline_ms,
  3. proves the stimulator stage cannot emit a command outside the safety envelope.

If any of those fail, you get an error at build time, with the offending stage named.

Worked example: closed-loop tremor suppression

examples/dbs_tremor.py runs a full closed loop against a numerical tremor model:

  • a neural plant generating a ~5 Hz tremor oscillation in simulated LFP,
  • the graph above sensing tremor-band power and driving a proportional stimulator,
  • the stimulation feeding back to suppress the tremor in the plant.

It prints the static latency/safety report and plots tremor power before vs. after the loop engages.

pip install -e .
python -m neuroloop.examples.dbs_tremor      # writes results/dbs_tremor.png

Status

Early, actively built. See ROADMAP.md for milestones. Local research artifact — not affiliated with or derived from any employer's work.

License

MIT — see LICENSE.

About

A composable framework for building, simulating, and formally bounding closed-loop neuromodulation pipelines (sense→decode→decide→stimulate) with compile-time latency budgets and runtime-enforced stimulation-safety envelopes.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages