How TVBO handles physical units across simulation components
2Specify·Dynamical systems
TVBO uses SymPy’s units system to handle physical units automatically. This enables correct unit conversions across different components of a simulation experiment.
Overview
Physical quantities appear throughout simulations:
TVBO correctly handles mixed units. The conduction speed unit doesn’t need to match the network’s distance/time units:
# Speed in m/s, distances in mm, output in msnet.conduction_speed = Parameter(name="v", value=3.0, unit="m/s")delays = net.calculate_delays()print(f"With speed in m/s:\n{np.round(delays, 2)}")
With speed in m/s:
[[ 0. 16.67 26.67]
[16.67 0. 10. ]
[26.67 10. 0. ]]
# Override output unitdelays_seconds = net.calculate_delays(output_unit="s")print(f"Delays in seconds:\n{delays_seconds}")
# Network with distances in meters and time in secondsnet_si = Network.from_matrix( W, lengths=L /1000, # Convert mm to m distance_unit="m", time_unit="s")net_si.conduction_speed = Parameter(name="v", value=3.0, unit="m/s")delays_si = net_si.calculate_delays()print(f"SI units - delays in seconds:\n{delays_si}")
SI units - delays in seconds:
[[0. 0.01666667 0.02666667]
[0.01666667 0. 0.01 ]
[0.02666667 0.01 0. ]]
1.4 Supported Units
Any unit recognized by SymPy can be used:
Category
Examples
Length
mm, m, cm, km, um (micrometer)
Time
ms, s, us (microsecond), minute, hour
Speed
m/s, mm/ms, km/hour, etc.
# Example: centimeters and microsecondsnet_micro = Network.from_matrix( W, lengths=L *10, # mm to 0.1mm scale distance_unit="cm", time_unit="us")net_micro.conduction_speed = Parameter(name="v", value=3000.0, unit="m/s")delays_us = net_micro.calculate_delays()print(f"Delays in microseconds:\n{np.round(delays_us, 2)}")
Number of edges: 2
Edge 0→1:
weight: 0.5
distance: 50.0 mm
delay: 16.67 ms
Edge 1→2:
weight: 0.8
distance: 30.0 mm
2. Integrator Units
The integrator sets its time unit with time_unit — the same spelling the network uses. One step_size, one duration, and one transient_time are all read in that unit.
Leaving it unset means undeclared, not ms: the slot stays None so that an integrator can inherit the unit declared one scope out. time_unit_of is the single reader that resolves a scope’s declaration, falling back to ms only when nothing anywhere declared one.
from tvbo.datamodel import Integratorfrom tvbo.utils.units import time_unit_of# Undeclared: the slot is None, and the resolver supplies the ms fallbackinteg_ms = Integrator(method="heun", step_size=0.1, duration=1000.0)print(f"Declared: {integ_ms.time_unit} -> resolved: {time_unit_of(integ_ms)}")# Same run written in secondsinteg_s = Integrator( method="heun", step_size=0.0001, # 0.1 ms time_unit="s", # step_size / duration / transient_time now in seconds duration=1.0, # 1 second)print(f"Explicit: {time_unit_of(integ_s)}")# `time_scale` is accepted as a synonym on inputinteg_alias = Integrator(method="heun", step_size=0.1, time_scale="us")print(f"Via time_scale synonym: {time_unit_of(integ_alias)}")
Declared: None -> resolved: ms
Explicit: s
Via time_scale synonym: us
Accepted values are s, ms, and us — the UnitEnum time units. time_scale is accepted as a synonym for time_unit on input, and dt as a synonym for step_size; a synonym is read back under the canonical name. See Integrators for methods, noise, and coupling-stage options.
Keep the integrator’s time_unit consistent with the network’s (section 1) unless you deliberately mix scales.
3. Dynamics Units (Coming Soon)
Time constants and frequencies in dynamics models will be unit-aware:
# Future API examplefrom tvbo.datamodel import Parametertau = Parameter(name="tau", value=10.0, unit="ms") # time constantomega = Parameter(name="omega", value=10.0, unit="Hz") # frequency
4. Monitor Units (Coming Soon)
Sampling periods and frequencies will support units:
# Future API examplefrom tvbo.datamodel import Monitormonitor = Monitor( name="BOLD", period=2.0, period_unit="s", # TR in seconds)
Summary
Set distance_unit and time_unit on networks to define the unit system
calculate_delays() automatically converts between units using SymPy
Set the integrator’s time_unit (s / ms / us) to choose the time unit for step_size, duration, and transient_time
Edge and model parameters can include a unit for documentation and validation
Any SymPy-recognized unit string works (no hardcoded mappings)