A comprehensive, unified framework for neuroscience and psychophysics experiments that combines controller (Controller) and experiment (rig) functionality in a single, distributed architecture.
NeuRPi provides a robust, scalable platform for conducting behavioral experiments with real-time hardware control, distributed computing capabilities, and comprehensive data management. Originally developed from separate Controller and Rig branches, it now offers a unified solution for experiment control and execution.
- π Unified Codebase: Single repository combining controller and experiment functionality
- π Distributed Computing: Run components across multiple machines or locally
- β‘ Real-time Performance: High-precision timing for behavioral experiments
- π Hardware Abstraction: Unified interface for diverse hardware components
- π¦ Modern Package Management: UV-based dependency management with Python 3.13+
- π₯οΈ Flexible GUI: Optional PyQt6 interface with headless operation support
- π§ Cross-Platform: Native support for Windows and Linux
- π Comprehensive Logging: Structured logging with multiple output formats
- π ZeroMQ Backbone: High-performance, reliable inter-process communication
- π Auto-Discovery: Automatic rig detection and management
- π‘ Protocol Flexibility: Support for various experimental protocols
- π‘οΈ Error Recovery: Robust error handling and recovery mechanisms
- Python 3.13+ (Required for latest features and performance)
- UV Package Manager (Modern, fast Python package management)
# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# Linux/macOS (Bash)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Alternative: via pip
pip install uv# Clone the repository
git clone https://github.com/your-org/neurpi.git
cd neurpi
# Install all dependencies with development tools
uv sync --all-extras
# Or install minimal setup
uv sync# Initialize default configuration
uv run neurpi init-config
# Set environment variables (optional)
export NEURPI_NAME="my_rig_01"
export NEURPI_MSGPORT=5560
export NEURPI_DATADIR="/path/to/data"# With GUI (default)
uv run neurpi controller
# Console mode (no GUI)
uv run neurpi controller --no-gui
# Custom configuration
uv run neurpi controller --config custom_config.yaml# Basic rig
uv run neurpi rig --name rig_01
# With specific hardware profile
uv run neurpi rig --name rig_01 --hardware lab_setup_a
# Child rig (hierarchical setup)
uv run neurpi rig --child --parent controller_main# Automatically detects role based on configuration
uv run neurpi unified
# With specific role override
uv run neurpi unified --force-role rigPerfect for protocol development and testing:
# Controller 1: Start rig with test hardware
uv run neurpi rig --name dev_rig --hardware simulator
# Controller 2: Start controller
uv run neurpi controller --development-modeProduction environment with multiple experiment rigs:
# Experiment Room - Rig 1
uv run neurpi rig --name rig_001 --hardware lab_config_a
# Experiment Room - Rig 2
uv run neurpi rig --name rig_002 --hardware lab_config_b
# Control Room - Controller
uv run neurpi controller --lab-mode --auto-discoverHeadless operation via SSH or automated scripts:
# Start controller in console mode
uv run neurpi controller --no-gui --remote-access
# Available console commands:
neurpi> status # Show system status
neurpi> rigs # List connected rigs
neurpi> ping all # Ping all rigs
neurpi> hardware rig_001 # Check hardware status
neurpi> start rig_001 random_dot_motion subject_001 # Start experiment
neurpi> monitor rig_001 # Monitor experiment progress
neurpi> stop rig_001 # Stop experiment
neurpi> data export # Export recent data
neurpi> quit # Exit controllerEmbed NeuRPi in custom applications:
from neurpi.agents.controller import Controller
from neurpi.agents.rig import rig
from neurpi.protocols import load_protocol
# Create controller programmatically
controller = Controller(gui_enabled=False)
controller.start()
# Connect to existing rig
rig_info = controller.get_rig("rig_001")
# Load and start experiment protocol
protocol = load_protocol("random_dot_motion", "rt_training")
controller.start_experiment(
rig="rig_001",
protocol=protocol,
subject="mouse_042"
)
# Monitor progress
while controller.is_experiment_running("rig_001"):
status = controller.get_experiment_status("rig_001")
print(f"Trials completed: {status.trials_completed}")
time.sleep(1)Coordinate multiple laboratories:
# Lab A - Main Controller
uv run neurpi controller --name lab_a_control --port 5555
# Lab A - Local rigs
uv run neurpi rig --name lab_a_rig_01 --parent lab_a_control
uv run neurpi rig --name lab_a_rig_02 --parent lab_a_control
# Lab B - Sub Controller
uv run neurpi controller --name lab_b_control --child --parent lab_a_control
# Lab B - Local rigs
uv run neurpi rig --name lab_b_rig_01 --parent lab_b_controlneurpi/
βββ agents/ # Core Controller and rig agents
βββ networking/ # ZeroMQ-based communication
βββ gui/ # Optional PyQt6 interface
βββ config/ # Configuration management
βββ loggers/ # Unified logging system
βββ hardware/ # Hardware abstraction (placeholder)
βββ tasks/ # Experiment tasks (placeholder)
βββ utils/ # Utility functions
βββ data_model/ # Data structures (placeholder)
Configuration is handled through:
- Default values in code
- YAML config files (
neurpi_config.yaml) - Environment variables (
NEURPI_*)
# Initialize default config file
uv run neurpi init-config
# Set environment variables
export NEURPI_NAME=my_rig
export NEURPI_MSGPORT=5560# Development install
uv sync --dev
# Run tests
uv run pytest
# Check code
uv run black neurpi/
uv run isort neurpi/This unified version merges the previous separate NeuRPi-controller and NeuRPi-rig branches:
- Controller (controller) β
neurpi controller - rig (rig) β
neurpi rig - Both β
neurpi unified
The networking and core functionality remain compatible while simplifying deployment and maintenance.
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linting
- Submit a pull request
Happy experimenting with NeuRPi!
Problem: Rig machines cannot connect to Windows controller, connection times out.
Symptoms:
- Rig connection fails with timeout error
- Ping between machines works
- Controller shows as listening on port 12000
- Connection works when Windows Firewall is disabled
Solution:
-
Open Command Prompt as Administrator
-
Find Python executable path:
where python -
Add firewall rules:
netsh advfirewall firewall add rule name="NeuRPi Controller TCP" dir=in action=allow protocol=TCP localport=12000 profile=any netsh advfirewall firewall add rule name="NeuRPi Controller Program" dir=in action=allow program="[PYTHON_PATH]" profile=any
Replace
[PYTHON_PATH]with the full path from step 2. -
Restart controller and test connection
Alternative: Use Windows Security GUI:
- Windows Security β Firewall & network protection β Advanced settings
- Inbound Rules β New Rule β Port β TCP β Port 12000 β Allow
Controller IP Binding:
- Set
CONTROLLERIP: 0.0.0.0incontroller.yamlto listen on all interfaces - Or use specific IP address if network allows direct connections
University/Corporate Networks:
- Some networks block inter-device communication
- Contact IT support if firewall rules don't resolve the issue
- Consider using a VPN or dedicated network segment