The brain_simulation.py module transforms the brain_ai repository from a static knowledge atlas into a living, dynamic simulation with actual spiking neurons, synaptic connections, and temporal evolution.
# Returns a string description
action_potential = ActionPotential.get_depolarization()
# Output: "Depolarization Phase: Threshold: -55 mV..."# Runs actual voltage simulation
neuron = SimulatedNeuron(0)
neuron.add_synaptic_input(10.0)
spiked = neuron.update(dt_ms=0.1)
# neuron.voltage_mv changes in real-time: -70 → -55 → +30 mVA stateful neuron that simulates membrane potential dynamics.
Key Features:
- Dynamic voltage: Changes over time based on currents
- Ion concentrations: Na+, K+, Ca2+, Cl- with Nernst potentials
- Spike mechanics: Threshold crossing, refractory period
- Realistic dynamics: Based on Hodgkin-Huxley principles
State Variables:
neuron.voltage_mv # Current membrane potential
neuron.ion_concentrations # Ion concentrations (inside/outside)
neuron.threshold_mv # Spike threshold (-55 mV)
neuron.refractory_period_ms # Absolute refractory period (2 ms)
neuron.spike_times # History of spike timesUsage:
from brain_simulation import SimulatedNeuron, NeuronType
# Create a neuron
neuron = SimulatedNeuron(
neuron_id=0,
neuron_type=NeuronType.EXCITATORY,
region="Hippocampus"
)
# Inject current and update
neuron.add_synaptic_input(15.0)
spiked = neuron.update(dt_ms=0.1)
if spiked:
print(f"Neuron spiked at {neuron.voltage_mv} mV!")Connects two neurons with adjustable synaptic weight.
Key Features:
- Spike transmission: Pre-synaptic spike → post-synaptic current
- Transmission delay: Realistic axonal conduction time
- Hebbian learning: Weight changes based on co-activity
- Synaptic plasticity: LTP and LTD
Parameters:
synapse.weight # Synaptic strength (0.0 - 10.0)
synapse.delay_ms # Transmission delay (typically 1-5 ms)
synapse.learning_rate # Plasticity rate (default 0.01)Usage:
from brain_simulation import Synapse
# Connect two neurons
pre = SimulatedNeuron(0, NeuronType.EXCITATORY)
post = SimulatedNeuron(1, NeuronType.EXCITATORY)
synapse = Synapse(pre, post, initial_weight=2.0, delay_ms=1.0)
# Transmit spike
synapse.transmit(current_time_ms=10.0, pre_spiked=True)
# Apply learning
synapse.apply_hebbian_learning(pre_spiked=True, post_spiked=True)
# → weight increases (LTP)The main simulation engine - provides the "heartbeat" of the brain.
Key Features:
- Temporal evolution: Advances simulation time step by step
- Network management: Handles collections of neurons and synapses
- Sensory input: Inject external currents
- Learning: Optional Hebbian plasticity
- Statistics: Track spikes, firing rates, etc.
Core Methods:
from brain_simulation import BrainSimulation
sim = BrainSimulation(dt_ms=0.1) # 0.1 ms time step
# Add individual neurons
neuron_id = sim.add_neuron(0, NeuronType.EXCITATORY, region="V1")
# Connect neurons
sim.connect_neurons(pre_id=0, post_id=1, weight=2.0, delay_ms=1.0)
# Or create a simple 3-layer network
sim.create_simple_network(
n_sensory=10, # Retina
n_processing=20, # V1
n_output=5 # Visual Association
)# Single time step
spike_counts = sim.simulate_step(enable_learning=True)
# Run for duration
sim.run(duration_ms=100.0, enable_learning=True, verbose=True)# Inject current into specific neuron
sim.inject_current(neuron_id=0, current=15.0)
# Stimulate entire region
sim.stimulate_region("Retina", current=25.0)# Get statistics
stats = sim.get_statistics()
print(f"Total spikes: {stats['total_spikes']}")
print(f"Average firing rate: {stats['average_firing_rate_hz']} Hz")
# Get voltage trace
voltage_trace = sim.get_neuron_voltage_trace(neuron_id=0)
# Get spike times
spike_times = sim.get_spike_times(neuron_id=0)The simulation uses real ion concentrations and the Nernst equation:
E_ion = (RT/zF) * ln([ion]_out / [ion]_in)
Typical values:
- E_Na ≈ +66 mV (drives depolarization)
- E_K ≈ -98 mV (drives repolarization)
- E_Ca ≈ +132 mV (important for plasticity)
- E_Cl ≈ -89 mV (inhibition)
from brain_simulation import IonConcentrations
ions = IonConcentrations()
e_na = ions.calculate_nernst_potential('na')
e_k = ions.calculate_nernst_potential('k')
print(f"Sodium equilibrium: {e_na:.2f} mV")
print(f"Potassium equilibrium: {e_k:.2f} mV")The neuron model captures the essential phases:
- Resting State: V_m = -70 mV
- Depolarization: Voltage rises above threshold (-55 mV)
- Spike: Rapid rise to +30 mV
- Repolarization: Return to resting
- Refractory Period: Temporary inability to spike (2 ms)
"Cells that fire together, wire together"
if pre_spiked and post_spiked:
# Long-Term Potentiation (LTP)
weight += learning_rate * (weight_max - weight)
elif pre_spiked and not post_spiked:
# Long-Term Depression (LTD)
weight -= learning_rate * 0.005 * weightimport numpy as np
from brain_simulation import BrainSimulation
# Set random seed for reproducibility
np.random.seed(42)
# Create simulation
sim = BrainSimulation(dt_ms=0.1)
# Build Retina → V1 → Visual Association network
sim.create_simple_network(n_sensory=10, n_processing=20, n_output=5)
# Simulate visual input (flashing pattern)
duration_ms = 150.0
steps = int(duration_ms / sim.dt_ms)
for step in range(steps):
time_ms = step * sim.dt_ms
epoch = int(time_ms / 10.0)
# Flash on/off every 10 ms
if epoch % 2 == 0:
sim.stimulate_region("Retina", current=25.0)
# Run one step
sim.simulate_step(enable_learning=True)
# Check results
stats = sim.get_statistics()
print(f"Total spikes: {stats['total_spikes']}")
print(f"Average firing rate: {stats['average_firing_rate_hz']:.2f} Hz")
# Spike counts by region
for region in ['Retina', 'V1', 'Visual_Association']:
spike_count = sum(
len(sim.neurons[nid].spike_times)
for nid in sim.neuron_groups[region]
)
avg_rate = spike_count / len(sim.neuron_groups[region]) / (duration_ms / 1000.0)
print(f"{region}: {spike_count} spikes ({avg_rate:.1f} Hz avg)")Expected Output:
Total spikes: 636
Average firing rate: 121.14 Hz
Retina: 470 spikes (313.3 Hz avg)
V1: 151 spikes (50.3 Hz avg)
Visual_Association: 15 spikes (20.0 Hz avg)
This demonstrates signal propagation through the network!
The simulation_demo.py script includes 5 comprehensive demonstrations:
python simulation_demo.pyDemos included:
- Single Neuron: Action potential generation
- Nernst Potentials: Ion equilibrium calculations
- Synaptic Transmission: Pre → Post spike propagation
- Hebbian Learning: Synaptic weight modification
- Network Simulation: Multi-layer signal propagation
- Scale: Hundreds to thousands of neurons
- Speed: Real-time for small networks
- Precision: 0.1 ms time steps
For networks with millions of neurons (approaching brain-scale), you would need:
- GPU Acceleration: Use PyTorch or TensorFlow
# Future implementation
import torch
voltages = torch.tensor(voltages, device='cuda')- Vectorization: Batch operations instead of loops
# Instead of: for neuron in neurons: neuron.update()
# Use: voltages += (currents / capacitance) * dt- Sparse Connectivity: Use sparse matrices for synapses
from scipy.sparse import csr_matrix
connectivity = csr_matrix((weights, (pre_ids, post_ids)))- Specialized Libraries:
- Brian2: High-level Python SNN simulator
- NEST: Large-scale brain simulations
- Nengo: Neural engineering framework
Both systems coexist for different purposes:
| Feature | Static Atlas | Dynamic Simulation |
|---|---|---|
| Purpose | Knowledge reference | Actual computation |
| Neurons | Text descriptions | Stateful objects |
| Connectivity | Listed pathways | Functional connections |
| Time | No temporal aspect | Time steps forward |
| Learning | Describes LTP/LTD | Implements LTP/LTD |
| Output | Strings, LaTeX | Spike trains, voltages |
| Use case | Education, reference | Research, AI modeling |
To move toward "sentient" behavior:
- Larger Scale: Millions of neurons with GPU acceleration
- Realistic Morphology: Multi-compartment neuron models
- Multiple Neurotransmitters: Dopamine, serotonin dynamics
- Detailed Connectome: Real brain connectivity data
- STDP: Spike-timing-dependent plasticity
- Homeostasis: Activity-dependent regulation
- Neuromodulation: Global state changes (arousal, attention)
- Sensory Integration: Multi-modal inputs
- Motor Output: Actuator control
- Cognitive Loops: Attention, memory, decision-making
- Hodgkin & Huxley (1952): Action potential mechanism
- Hebb (1949): "Cells that fire together, wire together"
- Nernst (1888): Ion equilibrium potentials
- Gerstner & Kistler (2002): Spiking Neuron Models
- Dayan & Abbott (2001): Theoretical Neuroscience
- Izhikevich (2007): Dynamical Systems in Neuroscience
- Brian2: https://brian2.readthedocs.io/
- NEST: https://nest-simulator.org/
- Nengo: https://www.nengo.ai/
This implementation synthesizes knowledge from computational neuroscience, systems biology, and neural engineering research for educational and research purposes.