Basic Usage¶
This guide covers the fundamental concepts and workflows for using Neun Python bindings.
Core Concepts¶
Neurons¶
Neurons are the primary computational units. Each neuron model has:
- Variables - Dynamic state (e.g., membrane potential, gating variables)
- Parameters - Fixed properties (e.g., conductances, reversal potentials)
- Integrator - Numerical method for solving differential equations
Integrators¶
Integrators solve the differential equations that govern neuron dynamics:
- RK4 - 4th-order Runge-Kutta (good balance of accuracy and speed)
- RK6 - 6th-order Runge-Kutta (higher accuracy, slower)
Precision¶
Models support different numeric precisions:
- float - Single precision (32-bit)
- double - Double precision (64-bit, recommended)
Creating a Neuron¶
Basic Neuron Creation¶
import neun_py
# Create constructor arguments
neuron_args = neun_py.HHDoubleConstructorArgs()
# Create a Hodgkin-Huxley neuron with double precision and RK4 integrator
neuron = neun_py.HHDoubleRK4(neuron_args)
Setting Parameters¶
Parameters define the physical properties of the neuron:
# Set membrane capacitance
neuron.set_param(neun_py.HHDoubleParameter.cm, 1 * 7.854e-3)
# Set reversal potentials (mV)
neuron.set_param(neun_py.HHDoubleParameter.vna, 50)
neuron.set_param(neun_py.HHDoubleParameter.vk, -77)
neuron.set_param(neun_py.HHDoubleParameter.vl, -54.387)
# Set conductances (mS/cm²)
neuron.set_param(neun_py.HHDoubleParameter.gna, 120 * 7.854e-3)
neuron.set_param(neun_py.HHDoubleParameter.gk, 36 * 7.854e-3)
neuron.set_param(neun_py.HHDoubleParameter.gl, 0.3 * 7.854e-3)
Setting Initial Conditions¶
Variables define the dynamic state:
# Set membrane potential
neuron.set(neun_py.HHDoubleVariable.v, -80)
# Set gating variables
neuron.set(neun_py.HHDoubleVariable.m, 0.1)
neuron.set(neun_py.HHDoubleVariable.n, 0.7)
neuron.set(neun_py.HHDoubleVariable.h, 0.01)
Running a Simulation¶
Basic Simulation Loop¶
# Simulation parameters
step = 0.001 # Integration time step (ms)
simulation_time = 100 # Total time (ms)
# Storage for results
times = []
voltages = []
# Simulation loop
time = 0.0
while time < simulation_time:
# Add external input (optional)
neuron.add_synaptic_input(0.1)
# Step the neuron forward in time
neuron.step(step)
# Read the current voltage
voltage = neuron.get(neun_py.HHDoubleVariable.v)
# Store results
times.append(time)
voltages.append(voltage)
time += step
Adding External Inputs¶
# Add constant current
neuron.add_synaptic_input(0.1) # Current in appropriate units
# Add time-varying current
import math
time = 0.0
while time < simulation_time:
# Sinusoidal input
current = 0.1 * math.sin(2 * math.pi * time / 20)
neuron.add_synaptic_input(current)
neuron.step(step)
time += step
Reading Neuron State¶
Getting Variables¶
# Get membrane potential
v = neuron.get(neun_py.HHDoubleVariable.v)
# Get gating variables
m = neuron.get(neun_py.HHDoubleVariable.m)
n = neuron.get(neun_py.HHDoubleVariable.n)
h = neuron.get(neun_py.HHDoubleVariable.h)
print(f"Membrane potential: {v:.3f} mV")
print(f"Gating variables: m={m:.3f}, n={n:.3f}, h={h:.3f}")
Getting Parameters¶
# Get parameters
cm = neuron.get_param(neun_py.HHDoubleParameter.cm)
gna = neuron.get_param(neun_py.HHDoubleParameter.gna)
print(f"Membrane capacitance: {cm:.6f}")
print(f"Sodium conductance: {gna:.6f}")
Visualization¶
Plotting with Matplotlib¶
import matplotlib.pyplot as plt
# Plot membrane potential over time
plt.figure(figsize=(10, 4))
plt.plot(times, voltages, linewidth=1.5)
plt.xlabel('Time (ms)')
plt.ylabel('Membrane Potential (mV)')
plt.title('Hodgkin-Huxley Neuron Simulation')
plt.grid(True, alpha=0.3)
plt.savefig('neuron_simulation.pdf')
plt.close()
Multiple Variables¶
# Store multiple variables
import numpy as np
times = []
v_values = []
m_values = []
n_values = []
h_values = []
time = 0.0
while time < simulation_time:
neuron.add_synaptic_input(0.1)
neuron.step(step)
times.append(time)
v_values.append(neuron.get(neun_py.HHDoubleVariable.v))
m_values.append(neuron.get(neun_py.HHDoubleVariable.m))
n_values.append(neuron.get(neun_py.HHDoubleVariable.n))
h_values.append(neuron.get(neun_py.HHDoubleVariable.h))
time += step
# Create subplots
fig, axes = plt.subplots(2, 1, figsize=(10, 8), sharex=True)
# Plot voltage
axes[0].plot(times, v_values, 'b-', linewidth=1.5)
axes[0].set_ylabel('Voltage (mV)')
axes[0].set_title('Membrane Potential')
axes[0].grid(True, alpha=0.3)
# Plot gating variables
axes[1].plot(times, m_values, 'r-', label='m', linewidth=1.5)
axes[1].plot(times, n_values, 'g-', label='n', linewidth=1.5)
axes[1].plot(times, h_values, 'b-', label='h', linewidth=1.5)
axes[1].set_xlabel('Time (ms)')
axes[1].set_ylabel('Gating Variable')
axes[1].set_title('Gating Variables')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('hh_detailed.pdf')
plt.close()
Saving Data¶
Writing to Text Files¶
# Save data to file
with open('simulation_data.dat', 'w') as f:
f.write("# Time(ms) Voltage(mV)\n")
for t, v in zip(times, voltages):
f.write(f"{t:.6f} {v:.6f}\n")
Using NumPy Arrays¶
import numpy as np
# Convert to numpy arrays
times_array = np.array(times)
voltages_array = np.array(voltages)
# Save as NumPy binary format
np.savez('simulation.npz', times=times_array, voltages=voltages_array)
# Load later
data = np.load('simulation.npz')
times_loaded = data['times']
voltages_loaded = data['voltages']
Common Patterns¶
Initialization Helper¶
def create_hh_neuron(v_init=-80, external_current=0.1):
"""Create and initialize a Hodgkin-Huxley neuron"""
neuron_args = neun_py.HHDoubleConstructorArgs()
neuron = neun_py.HHDoubleRK4(neuron_args)
# Set parameters
neuron.set_param(neun_py.HHDoubleParameter.cm, 1 * 7.854e-3)
neuron.set_param(neun_py.HHDoubleParameter.vna, 50)
neuron.set_param(neun_py.HHDoubleParameter.vk, -77)
neuron.set_param(neun_py.HHDoubleParameter.vl, -54.387)
neuron.set_param(neun_py.HHDoubleParameter.gna, 120 * 7.854e-3)
neuron.set_param(neun_py.HHDoubleParameter.gk, 36 * 7.854e-3)
neuron.set_param(neun_py.HHDoubleParameter.gl, 0.3 * 7.854e-3)
# Set initial conditions
neuron.set(neun_py.HHDoubleVariable.v, v_init)
neuron.set(neun_py.HHDoubleVariable.m, 0.1)
neuron.set(neun_py.HHDoubleVariable.n, 0.7)
neuron.set(neun_py.HHDoubleVariable.h, 0.01)
return neuron
# Usage
neuron = create_hh_neuron(v_init=-75)
Simulation Wrapper¶
def simulate_neuron(neuron, duration, step, external_input=0.1):
"""Run a neuron simulation and return results"""
times = []
voltages = []
time = 0.0
while time < duration:
neuron.add_synaptic_input(external_input)
neuron.step(step)
times.append(time)
voltages.append(neuron.get(neun_py.HHDoubleVariable.v))
time += step
return np.array(times), np.array(voltages)
# Usage
neuron = create_hh_neuron()
times, voltages = simulate_neuron(neuron, duration=100, step=0.001)
Next Steps¶
- Learn about different neuron models
- Connect neurons with synapses
- Add your own custom models