Working with Units#
brainmass uses brainunit for unit-safe computations, preventing common errors in scientific computing.
Why Units Matter#
Without units, it’s easy to make mistakes:
# DANGEROUS: Are these in ms or s?
tau = 10
frequency = 0.5
# What happens when you multiply them?
result = tau * frequency # Meaningless without units!
With units, errors are caught automatically:
import brainunit as u
tau = 10 * u.ms
frequency = 0.5 * u.Hz
# Units are checked automatically
result = tau * frequency # ✓ Dimensionless (ms * Hz = ms * 1/s = 0.001)
Basic Usage#
Creating Quantities#
import brainunit as u
import jax.numpy as jnp
# Scalar with units
time_const = 10.0 * u.ms
# Array with units
rates = jnp.array([1.0, 2.0, 3.0]) * u.Hz
# Common units
voltage = -65 * u.mV
current = 2.5 * u.nA
capacitance = 100 * u.pF
conductance = 10 * u.nS
time = 1.5 * u.second
Accessing Values and Units#
tau = 10.0 * u.ms
# Get magnitude (number)
magnitude = tau.magnitude # 10.0
# Get unit
unit = tau.unit # millisecond
# Convert to different unit
tau_in_seconds = tau.to(u.second) # 0.01 s
tau_in_us = tau.to(u.us) # 10000 μs
Unit Operations#
import brainunit as u
# Addition/subtraction: units must match
t1 = 10 * u.ms
t2 = 5 * u.ms
t_sum = t1 + t2 # 15 ms ✓
t3 = 1 * u.second
t_combined = t1 + t3 # 1.01 s (automatic conversion) ✓
# Multiplication/division: units combine
R = 10 * u.ohm
I = 2 * u.amp
V = R * I # 20 volt ✓
# Powers
area = (5 * u.meter) ** 2 # 25 meter²
Common Units in Neuroscience#
Time#
import brainunit as u
# Time constants
tau = 10 * u.ms # milliseconds
tau_slow = 0.5 * u.second # seconds
# Sampling intervals
dt = 0.1 * u.ms
TR = 2 * u.second # fMRI repetition time
Frequency#
# Oscillation frequencies
alpha = 10 * u.Hz # 10 Hz
theta = 5 * u.Hz
gamma = 40 * u.Hz
# Convert to angular frequency
omega = 2 * jnp.pi * alpha # rad/s
Voltage#
# Membrane potentials
V_rest = -70 * u.mV
V_thresh = -55 * u.mV
V_spike = 20 * u.mV
# EEG potentials
eeg_signal = 50 * u.uV # microvolts
Current#
# Synaptic currents
I_ext = 2.5 * u.pA # picoamperes
# Dipole moments (EEG/MEG)
dipole = 10 * u.nA * u.meter # nanoampere-meters
Rate#
# Firing rates
rate_E = 10 * u.Hz
rate_I = 15 * u.Hz
# Rates can be added
total_rate = rate_E + rate_I # 25 Hz
Using Units with brainmass#
Model Parameters#
Most brainmass models accept unit quantities:
import brainmass
import brainunit as u
model = brainmass.WilsonCowanModel(
in_size=10,
tau_E=10. * u.ms, # with units
tau_I=20. * u.ms,
# Or without units (assumes defaults)
c_EE=12.0, # unitless coupling strength
)
State Variables#
Internal states maintain units:
model = brainmass.HopfOscillator(
in_size=5,
omega=10 * u.Hz,
)
model.init_all_states()
model.update()
# States have units if specified
x = model.x.value # has units from model definition
y = model.y.value
Noise with Units#
# Noise in Hz (for firing rates)
noise = brainmass.OUProcess(
in_size=10,
sigma=0.5 * u.Hz,
tau=20 * u.ms,
)
# Noise in mV (for voltages)
noise_V = brainmass.OUProcess(
in_size=10,
sigma=5 * u.mV,
tau=10 * u.ms,
)
Forward Models#
# BOLD (dimensionless or %)
bold = brainmass.BOLDSignal(in_size=90)
# Input: neural activity (Hz or dimensionless)
# Output: BOLD % signal change
# EEG lead-field
L_eeg = load_leadfield() * (u.volt / (u.nA * u.meter))
eeg_model = brainmass.EEGLeadFieldModel(
in_size=68,
out_size=64,
L=L_eeg, # with units
)
Unit Checking and Errors#
Automatic Error Detection#
import brainunit as u
tau = 10 * u.ms
rate = 5 * u.Hz
# This will raise DimensionMismatch error:
try:
result = tau + rate # Can't add time and frequency!
except u.DimensionMismatch as e:
print(f"Error: {e}")
Common Unit Errors#
Error 1: Mixing incompatible units
# WRONG:
time = 10 * u.ms
voltage = 5 * u.mV
result = time + voltage # Error: can't add ms and mV
# CORRECT:
# Don't add incompatible quantities
Error 2: Forgetting units
# WRONG:
tau_E = 10 * u.ms
tau_I = 20 # forgot units!
ratio = tau_I / tau_E # May work but wrong semantics
# CORRECT:
tau_E = 10 * u.ms
tau_I = 20 * u.ms
ratio = tau_I / tau_E # 2.0 (dimensionless)
Error 3: Unit conversion mistakes
# WRONG:
tau_ms = 10 # assumed ms, but unclear
tau_s = tau_ms / 1000 # manual conversion, error-prone
# CORRECT:
tau = 10 * u.ms
tau_s = tau.to(u.second) # 0.01 s, automatic
Converting to Unitless#
Sometimes you need plain numbers (for plotting, external libraries):
import brainunit as u
import matplotlib.pyplot as plt
time = jnp.arange(1000) * u.ms
signal = jnp.sin(2 * jnp.pi * 10 * u.Hz * time)
# Convert to unitless for plotting
time_ms = time.to(u.ms).magnitude # array of numbers
signal_unitless = signal.magnitude
plt.plot(time_ms, signal_unitless)
plt.xlabel('Time (ms)')
plt.ylabel('Signal')
Or use brainunit’s plotting support:
# Some plotting functions may support units directly
plt.plot(time, signal) # may work with recent brainunit versions
Best Practices#
Always use units for physical quantities
# GOOD tau = 10 * u.ms frequency = 5 * u.Hz # BAD tau = 10 # unclear: ms? s? frequency = 5 # unclear: Hz? kHz?
Use consistent units within modules
# Within a module, stick to one time unit tau_E = 10 * u.ms tau_I = 20 * u.ms # not mixing with seconds dt = 0.1 * u.ms
Document units in comments when necessary
# Even with brainunit, document expected ranges tau = 10 * u.ms # typical range: 5-50 ms
Convert units explicitly when needed
omega_Hz = 10 * u.Hz omega_rad = 2 * jnp.pi * omega_Hz # rad/s # Convert time constant to frequency tau = 10 * u.ms f_cutoff = (1 / (2 * jnp.pi * tau)).to(u.Hz)
Use dimensionless quantities appropriately
# Ratios are naturally dimensionless tau_E = 10 * u.ms tau_I = 20 * u.ms ratio = tau_I / tau_E # 2.0 (dimensionless)
Troubleshooting#
Issue: Dimension mismatch error
# Error: DimensionMismatch: cannot add Hz and mV
# Solution: Check that you're not mixing incompatible quantities
Issue: Lost units after JAX operations
# Some JAX operations may strip units
x = 10 * u.ms
y = jnp.exp(x) # May lose units
# Solution: Use brainunit-aware functions or reattach units
y = jnp.exp(x.magnitude) * u.dimensionless
Issue: Slow performance with units
# Units add overhead; for tight loops, consider converting to unitless
tau_ms = tau.to(u.ms).magnitude # convert once
# ... use tau_ms in loop ...
Next Steps#
Quickstart - See units in action
Building Multi-Region Networks - Units in network simulations
brainunitdocumentation for advanced features
See Also#
Neural Mass Models - Model parameters and units
Forward Models - Forward model units