Simulator¶
Recruitment¶
RecruitmentThresholds ¶
RecruitmentThresholds(N: int, recruitment_range__ratio: float, deluca__slope: float | None = None, konstantin__max_threshold__ratio: float = 1.0, mode: Literal['fuglevand', 'deluca', 'konstantin', 'combined'] = 'konstantin')
Motor unit recruitment threshold generator using physiological models.
This class computes recruitment thresholds for motor unit pools using different established models from the literature.
Generate recruitment thresholds for a pool of motor units using different models.
This class computes the recruitment thresholds (and zero-based thresholds) for a pool of N motor units according to one of several models from the literature. The distribution of thresholds is controlled by the recruitment range (RR) and, for some models, additional parameters.
Following models are available:
- Fuglevand et al. (1993) [1]
- De Luca & Contessa (2012) [2]
- Konstantin et al. (2020) [3]
- Combined model
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
N
|
int
|
Number of motor units in the pool. |
required |
recruitment_range__ratio
|
float
|
Recruitment range (dimensionless ratio), defined as the ratio of the largest to smallest threshold \((rt(N)/rt(1))\). |
required |
deluca__slope
|
float
|
Dimensionless slope parameter for the |
None
|
konstantin__max_threshold__ratio
|
float
|
Maximum recruitment threshold (dimensionless ratio) for the |
1.0
|
mode
|
RecruitmentMode
|
Model to use for threshold generation. One of |
'konstantin'
|
Attributes:
| Name | Type | Description |
|---|---|---|
rt |
RECRUITMENT_THRESHOLDS__ARRAY
|
Recruitment thresholds for each motor unit (shape: (N,)).
Values are monotonically increasing from |
rtz |
RECRUITMENT_THRESHOLDS__ARRAY
|
Zero-based recruitment thresholds where \(rtz[0] = 0\) (shape: (N,)). Computed as \(rtz = rt - rt[0]\), convenient for simulation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a required mode-specific parameter is not provided or if an unknown mode is specified. |
References
[1] Fuglevand, A.J., Winter, D.A., Patla, A.E., 1993. Models of recruitment and rate coding organization in motor-unit pools. Journal of Neurophysiology 70, 2470-2488. https://doi.org/10.1152/jn.1993.70.6.2470
[2] De Luca, C.J., Contessa, P., 2012. Hierarchical control of motor units in voluntary contractions. Journal of Neurophysiology 107, 178-195. https://doi.org/10.1152/jn.00961.2010
[3] Konstantin, A., Yu, T., Le Carpentier, E., Aoustin, Y., Farina, D., 2020. Simulation of Motor Unit Action Potential Recordings From Intramuscular Multichannel Scanning Electrodes. IEEE Transactions on Biomedical Engineering 67, 2005-2014. https://doi.org/10.1109/TBME.2019.2953680
Notes
fuglevand : Fuglevand et al. (1993) [1] exponential model
where \(i = 1, 2, \ldots, N\)
deluca : De Luca & Contessa (2012) [2] model with slope correction
where \(b\) = deluca__slope, \(i = 1, 2, \ldots, N\)
konstantin : Konstantin et al. (2020) [3] model allowing explicit maximum threshold control
where \(RT_{max}\) = konstantin__max_threshold__ratio, \(i = 1, 2, \ldots, N\)
combined : A corrected De Luca model that uses the slope parameter for shape control but properly respects the RR constraint and maximum threshold like the Konstantin model
where \(b\) = deluca__slope, \(RT_{max}\) = konstantin__max_threshold__ratio, \(i = 1, 2, \ldots, N\)
Examples:
>>> # Generate thresholds using Fuglevand model
>>> thresholds = RecruitmentThresholds(
... N=100, recruitment_range__ratio=50.0, mode='fuglevand'
... )
>>> rt, rtz = thresholds # Tuple unpacking works
>>> # Or access directly
>>> rt = thresholds.rt
>>> rtz = thresholds.rtz
>>>
>>> # Generate thresholds using Konstantin model with explicit max threshold
>>> thresholds = RecruitmentThresholds(
... N=100, recruitment_range__ratio=50.0, konstantin__max_threshold__ratio=1.0, mode='konstantin'
... )
>>> rt, rtz = thresholds
Source code in myogen/simulator/core/physiological_distribution.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | |
Neuron populations¶
AlphaMN__Pool ¶
AlphaMN__Pool(n: int | None = None, recruitment_thresholds__array: RECRUITMENT_THRESHOLDS__ARRAY | None = None, config_file: Union[str, Path, None] = None, model: str | None = None, mode: str | None = None, axon_velocities: tuple[float, float] | None = None, axon_length: float | None = None, gamma: float | None = None, cell_index: Optional[int] = None, lambda_factor: float | None = None, initial_voltage__mV: Union[float, list[float], None] = None, spike_threshold__mV: float | None = None, soma_length_range: tuple[float, float, float] | None = None, soma_diameter_range: tuple[float, float, float] | None = None, soma_capacitance_range: tuple[float, float, float] | None = None, soma_passive_conductance_range: tuple[float, float, float] | None = None, soma_passive_reversal_range: tuple[float, float, float] | None = None, soma_na3rp_conductance_range: tuple[float, float, float] | None = None, soma_naps_conductance_range: tuple[float, float, float] | None = None, soma_kdrrl_conductance_range: tuple[float, float, float] | None = None, soma_mahp_ca_conductance_range: tuple[float, float, float] | None = None, soma_mahp_k_conductance_range: tuple[float, float, float] | None = None, soma_mahp_tau_range: tuple[float, float, float] | None = None, soma_gh_conductance_range: tuple[float, float, float] | None = None, dendrite_length_range: tuple[float, float, float] | None = None, dendrite_diameter_range: tuple[float, float, float] | None = None, dendrite_passive_conductance_range: tuple[float, float, float] | None = None, dendrite_passive_reversal_range: tuple[float, float, float] | None = None, dendrite_resistance_range: tuple[float, float, float] | None = None, dendrite_capacitance_range: tuple[float, float, float] | None = None, dendrite_gh_conductance_range: tuple[float, float, float] | None = None, dendrite_ca_conductance_ranges: tuple[tuple[float, float, float], ...] | None = None, dendrite_ca_theta_m_range: tuple[float, float, float] | None = None, dendrite_ca_theta_h_range: tuple[float, float, float] | None = None)
Bases: _Pool
Container for a population of alpha motor neurons.
Manages a collection of AlphaMN (alpha motor neuron) cells with different biophysical models: ModALS or Powers2017. These cells form the final common pathway for motor control.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of alpha motor neurons to create. |
None
|
recruitment_thresholds__array
|
RECRUITMENT_THRESHOLDS__ARRAY
|
Array of recruitment thresholds for each motor neuron, by default None. |
None
|
config_file
|
str or Path
|
Path to YAML configuration file containing model parameters. If provided, parameters from this file will be used as defaults, which can be overridden by explicitly passed parameters. Can be a filename (searches in myogen/config/), relative path, or absolute path. By default uses "alpha_mn_default.yaml". |
None
|
model
|
str
|
Motor neuron model type ("NERLab" or "Powers2017"), by default "NERLab".
When |
None
|
mode
|
str
|
Simulation mode ("active" or "passive"), by default "active". |
None
|
axon_velocities
|
tuple[float, float]
|
Min and max axon conduction velocities (m/s), by default (50, 65). |
None
|
axon_length
|
float
|
Length of the axon (mm), by default 0.6. |
None
|
gamma
|
float
|
Neuromodulation level (a.u.), by default 0.2. |
None
|
cell_index
|
Optional[int]
|
Specific cell index to create (creates only one cell), by default None. |
None
|
lambda_factor
|
float
|
Lambda factor for Powers2017 model persistent sodium scaling, by default 1.0. |
None
|
initial_voltage__mV
|
float or list[float]
|
Initial membrane voltage (mV), by default -67. |
None
|
spike_threshold__mV
|
float
|
Spike detection threshold for recording motor neuron spikes, by default 50.0. Motor neurons have large action potentials (80-100 mV) requiring higher thresholds. |
None
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
soma_length_range |
tuple[float, float, float]
|
Soma length [min, max, curve] (um). Only used when |
soma_diameter_range |
tuple[float, float, float]
|
Soma diameter [min, max, curve] (um). |
soma_capacitance_range |
tuple[float, float, float]
|
Soma capacitance [min, max, curve] (uF/cm²). |
soma_passive_conductance_range |
tuple[float, float, float]
|
Soma passive conductance [min, max, curve] (S/cm²). |
soma_passive_reversal_range |
tuple[float, float, float]
|
Soma passive reversal potential [min, max, curve] (mV). |
soma_na3rp_conductance_range |
tuple[float, float, float]
|
Soma Na3RP conductance [min, max, curve] (S/cm²). |
soma_naps_conductance_range |
tuple[float, float, float]
|
Soma NaPS conductance [min, max, curve] (S/cm²). |
soma_kdrrl_conductance_range |
tuple[float, float, float]
|
Soma KDRRL conductance [min, max, curve] (S/cm²). |
soma_mahp_ca_conductance_range |
tuple[float, float, float]
|
Soma mAHP calcium conductance [min, max, curve] (S/cm²). |
soma_mahp_k_conductance_range |
tuple[float, float, float]
|
Soma mAHP potassium conductance [min, max, curve] (S/cm²). |
soma_mahp_tau_range |
tuple[float, float, float]
|
Soma mAHP time constant [min, max, curve] (ms). |
soma_gh_conductance_range |
tuple[float, float, float]
|
Soma h-current conductance [min, max, curve] (S/cm²). |
dendrite_length_range |
tuple[float, float, float]
|
Dendrite length [min, max, curve] (um). |
dendrite_diameter_range |
tuple[float, float, float]
|
Dendrite diameter [min, max, curve] (um). |
dendrite_passive_conductance_range |
tuple[float, float, float]
|
Dendrite passive conductance [min, max, curve] (S/cm²). |
dendrite_passive_reversal_range |
tuple[float, float, float]
|
Dendrite passive reversal potential [min, max, curve] (mV). |
dendrite_resistance_range |
tuple[float, float, float]
|
Dendrite axial resistance [min, max, curve] (Ω·cm). |
dendrite_capacitance_range |
tuple[float, float, float]
|
Dendrite capacitance [min, max, curve] (uF/cm²). |
dendrite_gh_conductance_range |
tuple[float, float, float]
|
Dendrite h-current conductance [min, max, curve] (S/cm²). |
dendrite_ca_conductance_ranges |
tuple[tuple[float, float, float], ...]
|
L-type Ca conductance ranges for each dendrite (4 tuples). |
dendrite_ca_theta_m_range |
tuple[float, float, float]
|
Ca channel activation threshold [min, max, curve] (mV). |
dendrite_ca_theta_h_range |
tuple[float, float, float]
|
Ca channel inactivation threshold [min, max, curve] (mV). |
Source code in myogen/simulator/neuron/populations/motor_neurons.py
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | |
DescendingDrive__Pool ¶
DescendingDrive__Pool(n: int, timestep__ms: Quantity__ms | None = None, process_type: str = 'poisson', shape: float = 3.0)
Bases: _Pool
Container for a population of descending drive neurons.
Manages a collection of DD cells that generate spike trains using either Poisson or Gamma point processes for cortical input to spinal circuits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of descending drive neurons to create. |
required |
timestep__ms
|
Quantity__ms
|
Time step for simulation as a Quantity with units of milliseconds (required). |
None
|
process_type
|
str
|
Type of point process: "poisson" or "gamma", by default "poisson". - "poisson": discrete-time Poisson process, irregular firing (CV=1.0, exact as dt->0) - "gamma": More regular firing with CV controlled by shape parameter |
'poisson'
|
shape
|
float
|
Shape parameter for Gamma process (only used when process_type="gamma"), by default 3.0. Controls spike regularity: - shape=1: Poisson-like (CV=1.0) - shape=2-5: Typical cortical neuron regularity (CV=0.45-0.71) - Higher values: More regular firing (CV=1/sqrt(shape)) |
3.0
|
Source code in myogen/simulator/neuron/populations/descending_drive.py
DescendingDrive_Gamma__Pool is a backward-compatibility alias. New code should
prefer DescendingDrive__Pool(process_type="gamma", shape=...).
DescendingDrive_Gamma__Pool ¶
DescendingDrive_Gamma__Pool(n: int, timestep__ms: Quantity__ms, shape: float = 3.0)
Bases: _Pool
Container for a population of descending drive neurons using Gamma process.
Manages a collection of DD_Gamma cells that generate Gamma-distributed spike trains for more regular cortical input to spinal circuits, typical of cortical neuron firing patterns.
Note: This class is kept for backward compatibility. Consider using DescendingDrive__Pool with process_type='gamma' instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of descending drive neurons to create. |
required |
timestep__ms
|
Quantity__ms
|
Time step for simulation as a Quantity with units of milliseconds. |
required |
shape
|
float
|
Shape parameter controlling spike regularity, by default 3.0. - shape=1: Poisson-like (irregular) firing - shape=2-5: Typical cortical neuron regularity - Higher values: More regular, clock-like firing |
3.0
|
Source code in myogen/simulator/neuron/populations/descending_drive.py
AffIa__Pool ¶
AffIa__Pool(n: int, timestep__ms: Quantity__ms, recruitment_thresholds: tuple[float, float] = (0, 40), axon_velocities__m_per_s: tuple[Quantity__m_per_s, Quantity__m_per_s] = (61 * m / s, 75 * m / s), axon_length__m: Quantity__m = 0.6 * m, shape: int = 145, init_order: int = 0)
Bases: _Pool
Container for a population of afferent Ia neurons.
Manages a collection of AffIa (type Ia afferent) cells that provide proprioceptive feedback from muscle spindles to spinal circuits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of type Ia afferent neurons to create. |
required |
recruitment_thresholds
|
tuple[float, float]
|
Min and max recruitment thresholds (Hz). |
(0, 40)
|
axon_velocities__m_per_s
|
tuple[Quantity__m_per_s, Quantity__m_per_s]
|
Min and max axon conduction velocities (m/s). |
(61 * m / s, 75 * m / s)
|
axon_length__m
|
Quantity__m
|
Length of the axon (m). |
0.6 * m
|
shape
|
int
|
Gamma shape parameter controlling ISI regularity: CV = 1/sqrt(shape). Larger values give more regular firing. Does not set the firing rate. |
145
|
timestep__ms
|
Quantity__ms
|
Time step for simulation (ms). |
required |
init_order
|
int
|
Initial order parameter for afferent initialization. |
0
|
Source code in myogen/simulator/neuron/populations/afferents.py
AffII__Pool ¶
AffII__Pool(n: int, timestep__ms: Quantity__ms, recruitment_thresholds: tuple[float, float] = (0, 40), axon_velocities__m_per_s: tuple[Quantity__m_per_s, Quantity__m_per_s] = (30 * m / s, 50 * m / s), axon_length__m: Quantity__m = 0.6 * m, shape: int = 772, init_order: int = 0)
Bases: _Pool
Container for a population of afferent II neurons.
Manages a collection of AffII (type II afferent) cells that provide secondary proprioceptive feedback from muscle spindles to spinal circuits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of type II afferent neurons to create. |
required |
recruitment_thresholds
|
tuple[float, float]
|
Min and max recruitment thresholds (Hz). |
(0, 40)
|
axon_velocities__m_per_s
|
tuple[Quantity__m_per_s, Quantity__m_per_s]
|
Min and max axon conduction velocities (m/s). |
(30 * m / s, 50 * m / s)
|
axon_length__m
|
Quantity__m
|
Length of the axon (m). |
0.6 * m
|
shape
|
int
|
Gamma shape parameter controlling ISI regularity: CV = 1/sqrt(shape). Larger values give more regular firing. Does not set the firing rate. |
772
|
timestep__ms
|
Quantity__ms
|
Time step for simulation (ms). |
required |
init_order
|
int
|
Initial order parameter for afferent initialization. |
0
|
Source code in myogen/simulator/neuron/populations/afferents.py
AffIb__Pool ¶
AffIb__Pool(n: int, timestep__ms: Quantity__ms, recruitment_thresholds: tuple[float, float] = (0, 40), axon_velocities__m_per_s: tuple[Quantity__m_per_s, Quantity__m_per_s] = (64 * m / s, 72 * m / s), axon_length__mm: Quantity__mm = 0.6 * mm, shape: int = 145, init_order: int = 0)
Bases: _Pool
Container for a population of afferent Ib neurons.
Manages a collection of AffIb (type Ib afferent) cells that provide primary proprioceptive feedback from Golgi tendon organs to spinal circuits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of type Ib afferent neurons to create. |
required |
recruitment_thresholds
|
tuple[float, float]
|
Min and max recruitment thresholds (Hz). |
(0, 40)
|
axon_velocities__m_per_s
|
tuple[Quantity__m_per_s, Quantity__m_per_s]
|
Min and max axon conduction velocities (m/s). |
(64 * m / s, 72 * m / s)
|
axon_length__mm
|
Quantity__mm
|
Length of the axon (mm). |
0.6 * mm
|
shape
|
int
|
Gamma shape parameter controlling ISI regularity: CV = 1/sqrt(shape). Larger values give more regular firing. Does not set the firing rate. |
145
|
timestep__ms
|
Quantity__ms
|
Time step for simulation (ms). |
required |
init_order
|
int
|
Initial order parameter for afferent initialization. |
0
|
Source code in myogen/simulator/neuron/populations/afferents.py
GII__Pool ¶
GII__Pool(n: int, soma_length_range__um: tuple[float, float] = _get_interneuron_diameter_range__um(), soma_diameter_range: tuple[float, float] = _get_interneuron_diameter_range__um(), passive_conductance_range: tuple[float, float] = (3e-05, 7e-05), na3rp_conductance_range: tuple[float, float] = (0.003, 0.01), kdrrl_conductance_range: tuple[float, float] = (0.015, 0.015), mahp_ca_conductance_range: tuple[float, float] = (3e-06, 3e-06), mahp_k_conductance_range: tuple[float, float] = (0.0005, 0.0005), mahp_tau_range: tuple[float, float] = (60, 70), gh_conductance_range: tuple[float, float] = (2.5e-05, 2.5e-05), axon_velocities: tuple[float, float] = (10, 10), axon_length: float = 0.05, cell_index: Optional[int] = None, initial_voltage__mV: Union[float, list[float]] = -70.0)
Bases: _Pool
Container for a population of group II interneurons.
Manages a collection of INgII (group II interneuron) cells that provide inhibitory feedback in spinal circuits, processing type II afferent input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of group II interneurons to create. |
required |
soma_length_range__um
|
tuple[float, float]
|
Min and max soma length (um). By default, it is set to the estimated range for interneurons from Bui et al. 2003 [1]. |
_get_interneuron_diameter_range__um()
|
soma_diameter_range
|
tuple[float, float]
|
Min and max soma diameter (um). By default, it is set to the estimated range for interneurons from Bui et al. 2003 [1]. |
_get_interneuron_diameter_range__um()
|
passive_conductance_range
|
tuple[float, float]
|
Min and max passive membrane conductance (S/cm²). |
(3e-05, 7e-05)
|
na3rp_conductance_range
|
tuple[float, float]
|
Min and max Na3RP sodium channel conductance (S/cm²). |
(0.003, 0.01)
|
kdrrl_conductance_range
|
tuple[float, float]
|
Min and max KDRRL potassium channel conductance (S/cm²). |
(0.015, 0.015)
|
mahp_ca_conductance_range
|
tuple[float, float]
|
Min and max mAHP calcium conductance (S/cm²). |
(3e-06, 3e-06)
|
mahp_k_conductance_range
|
tuple[float, float]
|
Min and max mAHP potassium conductance (S/cm²). |
(0.0005, 0.0005)
|
mahp_tau_range
|
tuple[float, float]
|
Min and max mAHP time constant (ms). |
(60, 70)
|
gh_conductance_range
|
tuple[float, float]
|
Min and max h-current conductance (S/cm²). |
(2.5e-05, 2.5e-05)
|
axon_velocities
|
tuple[float, float]
|
Min and max axon conduction velocities (m/s). |
(10, 10)
|
axon_length
|
float
|
Length of the axon (mm). |
0.05
|
cell_index
|
int
|
Specific cell index to create (creates only one cell), by default None. |
None
|
References
[1] Bui, T.V., Cushing, S., Dewey, D., Fyffe, R.E., Rose, P.K., 2003. Comparison of the Morphological and Electrotonic Properties of Renshaw Cells, Ia Inhibitory Interneurons, and Motoneurons in the Cat. Journal of Neurophysiology 90, 2900–2918. https://doi.org/10.1152/jn.00533.2003
Source code in myogen/simulator/neuron/populations/interneurons.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
GIb__Pool ¶
GIb__Pool(n: int, soma_length_range: tuple[float, float] = _get_interneuron_diameter_range__um(), soma_diameter_range: tuple[float, float] = _get_interneuron_diameter_range__um(), passive_conductance_range: tuple[float, float] = (3e-05, 8e-05), na3rp_conductance_range: tuple[float, float] = (0.01, 0.03), kdrrl_conductance_range: tuple[float, float] = (0.035, 0.028), mahp_ca_conductance_range: tuple[float, float] = (1e-06, 6e-06), mahp_k_conductance_range: tuple[float, float] = (0.0003, 0.00045), mahp_tau_range: tuple[float, float] = (120, 90), gh_conductance_range: tuple[float, float] = (2.5e-05, 2.5e-05), axon_velocities: tuple[float, float] = (10, 10), axon_length: float = 0.05, cell_index: int | None = None, initial_voltage__mV: float | list[float] = -70.0)
Bases: _Pool
Container for a population of group Ib interneurons.
Manages a collection of INgIb (group Ib interneuron) cells that provide inhibitory feedback in spinal circuits, processing type Ib afferent input from Golgi tendon organs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of group Ib interneurons to create. |
required |
soma_length_range
|
tuple[float, float]
|
Min and max soma length (um). |
_get_interneuron_diameter_range__um()
|
soma_diameter_range
|
tuple[float, float]
|
Min and max soma diameter (um). |
_get_interneuron_diameter_range__um()
|
passive_conductance_range
|
tuple[float, float]
|
Min and max passive membrane conductance (S/cm²). |
(3e-05, 8e-05)
|
na3rp_conductance_range
|
tuple[float, float]
|
Min and max Na3RP sodium channel conductance (S/cm²). |
(0.01, 0.03)
|
kdrrl_conductance_range
|
tuple[float, float]
|
Min and max KDRRL potassium channel conductance (S/cm²). |
(0.035, 0.028)
|
mahp_ca_conductance_range
|
tuple[float, float]
|
Min and max mAHP calcium conductance (S/cm²). |
(1e-06, 6e-06)
|
mahp_k_conductance_range
|
tuple[float, float]
|
Min and max mAHP potassium conductance (S/cm²). |
(0.0003, 0.00045)
|
mahp_tau_range
|
tuple[float, float]
|
Min and max mAHP time constant (ms). |
(120, 90)
|
gh_conductance_range
|
tuple[float, float]
|
Min and max h-current conductance (S/cm²). |
(2.5e-05, 2.5e-05)
|
axon_velocities
|
tuple[float, float]
|
Min and max axon conduction velocities (m/s). |
(10, 10)
|
axon_length
|
float
|
Length of the axon (mm). |
0.05
|
cell_index
|
Optional[int]
|
Specific cell index to create (creates only one cell), by default None. |
None
|
Source code in myogen/simulator/neuron/populations/interneurons.py
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | |
Network & runner¶
Network ¶
Modern neural network builder with intuitive connection API.
Provides a clean, discoverable interface for creating neural network connections while maintaining compatibility with existing NEURON-based infrastructure.
Initialize network with neural populations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
populations
|
dict[str, Union[list, Any]]
|
Dictionary mapping population names to Pool objects or lists of neuron objects. Pool objects will have .neurons extracted, lists used directly. Example: {"alpha_mn": alphaMN_pool, "ia": ia_pool} |
required |
spike_recording
|
dict
|
Dictionary containing 'idvec' and 'spkvec' for spike recording. Example: {"idvec": {"aMN": h.Vector()}, "spkvec": {"aMN": h.Vector()}} |
None
|
Source code in myogen/simulator/neuron/network.py
setup_spike_recording ¶
Set up spike recording NetCons for all neurons in all populations.
This creates additional NetCons specifically for recording spikes from neurons that might not have outgoing connections but still need spike recording for analysis.
Source code in myogen/simulator/neuron/network.py
connect ¶
connect(source: str, target: str, probability: float = 1.0, weight__uS: Quantity__uS = DEFAULT_SYNAPTIC_WEIGHT, delay__ms: Quantity__ms = DEFAULT_SYNAPTIC_DELAY, threshold__mV: Quantity__mV = DEFAULT_SPIKE_THRESHOLD, deterministic: bool = False, inhibitory: bool = False) -> list
Connect two neural populations with specified parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str
|
Name of source population (must exist in populations dict). |
required |
target
|
str
|
Name of target population (must exist in populations dict). |
required |
probability
|
float
|
Connection probability between 0.0 and 1.0, by default 1.0. Each source-target neuron pair connects with this probability (if deterministic=False). If deterministic=True, each source connects to exactly int(probability × n_targets) targets. |
1.0
|
weight__uS
|
float
|
Synaptic weight in microsiemens, by default 0.6. |
DEFAULT_SYNAPTIC_WEIGHT
|
delay__ms
|
float
|
Synaptic delay in milliseconds, by default 1.0. |
DEFAULT_SYNAPTIC_DELAY
|
threshold__mV
|
float
|
Spike threshold in millivolts, by default -10.0. |
DEFAULT_SPIKE_THRESHOLD
|
deterministic
|
bool
|
If True, each source neuron connects to exactly int(probability × n_targets) randomly selected target neurons. If False, uses probabilistic sampling. Default False. |
False
|
inhibitory
|
bool
|
If True, connect to inhibitory synapses on target neurons (reversal < -40 mV). If False, connect to excitatory synapses (reversal >= -40 mV). Default False. Use inhibitory=True for connections from inhibitory interneurons (e.g., gII→aMN, gIb→aMN). |
False
|
Returns:
| Type | Description |
|---|---|
list[NetCon]
|
List of created NEURON NetCon objects for this connection group. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If source or target populations don't exist, or probability out of range. |
Source code in myogen/simulator/neuron/network.py
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 | |
connect_to_muscle ¶
connect_to_muscle(source: str, muscle, activation_callback: Callable, weight__uS: Quantity__uS = DEFAULT_SYNAPTIC_WEIGHT, delay__ms: Quantity__ms = DEFAULT_SYNAPTIC_DELAY, threshold__mV: Quantity__mV = DEFAULT_SPIKE_THRESHOLD) -> list
Connect a neural population to a muscle with activation callback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str
|
Name of motor neuron population. |
required |
muscle
|
object
|
Muscle object for force generation. |
required |
activation_callback
|
Callable
|
Function called when motor neurons fire. Expected signature: callback(neuron_id, muscle, delay_time) |
required |
weight__uS
|
float
|
Synaptic weight in microsiemens, by default 1.0. |
DEFAULT_SYNAPTIC_WEIGHT
|
threshold__mV
|
float
|
Spike threshold in millivolts, by default -10.0. |
DEFAULT_SPIKE_THRESHOLD
|
Returns:
| Type | Description |
|---|---|
list[NetCon]
|
List of motor neuron to muscle NetCon objects. |
Source code in myogen/simulator/neuron/network.py
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 | |
connect_from_external ¶
connect_from_external(source: str, target: str, weight__uS: Quantity__uS = DEFAULT_SYNAPTIC_WEIGHT, delay__ms: Quantity__ms = DEFAULT_SYNAPTIC_DELAY, threshold__mV: Quantity__mV = DEFAULT_SPIKE_THRESHOLD) -> list
Connect external input source to a neural population.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str
|
Name/label for external input source (e.g., "spindle", "cortical_drive"). |
required |
target
|
str
|
Name of target neural population. |
required |
weight__uS
|
Quantity__uS
|
Synaptic weight in microsiemens, by default 0.8. |
DEFAULT_SYNAPTIC_WEIGHT
|
delay__ms
|
float
|
Synaptic delay in milliseconds, by default 1.0. |
DEFAULT_SYNAPTIC_DELAY
|
threshold__mV
|
float
|
Spike threshold in millivolts, by default -10.0. |
DEFAULT_SPIKE_THRESHOLD
|
Returns:
| Type | Description |
|---|---|
list[NetCon]
|
List of external to neural NetCon objects. |
Source code in myogen/simulator/neuron/network.py
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 | |
connect_one_to_one ¶
connect_one_to_one(source: str, target: str, probability: float = 1.0, weight__uS: Quantity__uS = DEFAULT_SYNAPTIC_WEIGHT, delay__ms: Quantity__ms = DEFAULT_SYNAPTIC_DELAY, threshold__mV: Quantity__mV = DEFAULT_SPIKE_THRESHOLD, inhibitory: bool = False) -> list
Connect two neural populations with one-to-one mapping.
Creates individual connections between source[i] and target[i] for each neuron pair at matching indices with specified probability. This is particularly useful for modeling independent noise sources (e.g., independent Poisson drives) where each target neuron should receive input from exactly one source neuron.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str
|
Name of source population (must exist in populations dict). |
required |
target
|
str
|
Name of target population (must exist in populations dict). |
required |
probability
|
float
|
Probability that each source[i] -> target[i] connection is made, by default 1.0. Must be between 0.0 and 1.0. |
1.0
|
weight__uS
|
Quantity__uS
|
Synaptic weight in microsiemens, by default 0.6. |
DEFAULT_SYNAPTIC_WEIGHT
|
delay__ms
|
Quantity__ms
|
Synaptic delay in milliseconds, by default 1.0. |
DEFAULT_SYNAPTIC_DELAY
|
threshold__mV
|
Quantity__mV
|
Spike threshold in millivolts, by default -10.0. |
DEFAULT_SPIKE_THRESHOLD
|
inhibitory
|
bool
|
If True, connect to inhibitory synapses on target neurons (reversal < -40 mV). If False, connect to excitatory synapses (reversal >= -40 mV). Default False. |
False
|
Returns:
| Type | Description |
|---|---|
list[NetCon]
|
List of created NEURON NetCon objects for connections that were made. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If source or target populations don't exist, have different sizes, or probability is not in [0.0, 1.0]. |
Examples:
>>> # Create independent noise for each motor neuron
>>> noise_pool = DescendingDrive__Pool(n=10, timestep__ms=0.05)
>>> mn_pool = AlphaMN__Pool(n=10)
>>> network = Network({"noise": noise_pool, "mn": mn_pool})
>>> network.connect_one_to_one("noise", "mn", weight__uS=0.5)
Source code in myogen/simulator/neuron/network.py
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 | |
get_connections ¶
get_netcons ¶
Get NEURON NetCon objects with optional filtering by source and target.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str
|
Filter by source population/input name. If None, returns NetCons from all sources. |
None
|
target
|
str
|
Filter by target population name. If None, returns NetCons to all targets. |
None
|
Returns:
| Type | Description |
|---|---|
list[NetCon]
|
List of matching NetCon objects. |
Source code in myogen/simulator/neuron/network.py
print_network ¶
Print a summary of network structure.
Source code in myogen/simulator/neuron/network.py
SimulationRunner ¶
SimulationRunner(network: Network, models: dict[str, Any], step_callback: Callable[[Any], Any], model_outputs: Optional[dict[str, Union[list[str], None]]] = None, temperature__celsius: float = 36.0)
Manages NEURON simulation execution with automated setup, initialization, and result collection for neuromuscular simulations.
Provides a clean interface for running complex neuromuscular simulations while maintaining full user control over populations, connections, and step-by-step simulation logic. Automatically handles NEURON environment setup, voltage initialization, and structured result collection.
Separates simulation control from plotting and analysis concerns.
Initialize SimulationRunner with network, models, and step callback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
Configured Network instance with populations and connections. |
required |
models
|
Dict[str, Any]
|
Physiological models (e.g., {"hill": hill_model, "spin": spindle_model}). |
required |
step_callback
|
Callable
|
User-defined function called at each simulation timestep. |
required |
model_outputs
|
Optional[Dict[str, Union[List[str], None]]]
|
Explicit model output attributes to collect. None uses smart defaults. Format: {"model_name": ["attr1", "attr2"]} or {"model_name": None} for defaults, by default None. |
None
|
temperature__celsius
|
float
|
NEURON simulation temperature, by default 36.0. |
36.0
|
Source code in myogen/simulator/neuron/simulation_runner.py
run ¶
run(duration__ms: Quantity__ms, timestep__ms: Quantity__ms, membrane_recording: Optional[dict[str, list[int]]] = None, verbose: bool = True) -> Block
Execute NEURON simulation with automated setup and result collection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
duration__ms
|
Quantity__ms
|
Total simulation duration in milliseconds. |
required |
timestep__ms
|
Quantity__ms
|
Integration timestep in milliseconds. |
required |
membrane_recording
|
Optional[Dict[str, List[int]]]
|
Populations and cell indices for membrane potential recording. Format: {"population_name": [cell_id1, cell_id2, ...]}, by default None. |
None
|
verbose
|
bool
|
If True, display progress bar and status messages. Set to False to disable. |
True
|
Returns:
| Type | Description |
|---|---|
Block
|
Structured simulation results containing: - spikes: Spike timing and ID data for all populations - membrane: Membrane potential traces (if requested) - models: Output data from all physiological models - simulation: Time vector and simulation metadata |
Raises:
| Type | Description |
|---|---|
ValueError
|
If model output attributes don't exist on model instances. |
RuntimeError
|
If NEURON simulation fails to complete. |
Source code in myogen/simulator/neuron/simulation_runner.py
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | |
get_model_outputs ¶
Get the list of output attributes that will be collected for a model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_name
|
str
|
Name of the model as specified in the models dictionary. |
required |
Returns:
| Type | Description |
|---|---|
List[str]
|
List of attribute names that will be collected from this model. |
Source code in myogen/simulator/neuron/simulation_runner.py
set_model_outputs ¶
Override the output attributes for a specific model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_name
|
str
|
Name of the model as specified in the models dictionary. |
required |
output_attrs
|
List[str]
|
List of attribute names to collect from this model. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If model_name is not found in the models dictionary. |
Source code in myogen/simulator/neuron/simulation_runner.py
Muscle & force¶
Muscle ¶
Muscle(recruitment_thresholds: RECRUITMENT_THRESHOLDS__ARRAY, radius__mm: Quantity__mm = 6.91 * mm, length__mm: Quantity__mm = 30.0 * mm, fiber_density__fibers_per_mm2: Quantity__per_mm2 = 350 * mm ** -2, max_innervation_area_to_total_muscle_area__ratio: float = 1 / 4, mean_conduction_velocity__m_per_s: Quantity__m_per_s = 4.2 * m / s, mean_fiber_length__mm: Quantity__mm = 31.7 * mm, var_fiber_length__mm: Quantity__mm = 2.8 * mm, radius_bone__mm: Quantity__mm = 0 * mm, fat_thickness__mm: Quantity__mm = 0.3 * mm, skin_thickness__mm: Quantity__mm = 1.29 * mm, muscle_conductivity_radial__S_per_m: Quantity__S_per_m = 0.09 * S / m, muscle_conductivity_longitudinal__S_per_m: Quantity__S_per_m = 0.4 * S / m, fat_conductivity__S_per_m: Quantity__S_per_m = 0.0407 * S / m, skin_conductivity__S_per_m: Quantity__S_per_m = 0.000488 * S / m, grid_resolution: int = 256, autorun: bool = False)
A muscle model based on the cylindrical description of the volume conductor by Farina et al. 2004 [1] and the motor unit distribution by Konstantin et al. 2020 [2].
All default values are set to simulate the First Dorsal Interosseous (FDI) muscle. Values are pulled from the literature.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
recruitment_thresholds
|
RECRUITMENT_THRESHOLDS__ARRAY
|
Array of recruitment thresholds for each motor unit (see |
required |
radius__mm
|
float
|
Radius of the muscle cross-section in millimeters. Default is set to 6.91 mm as determined by Jacobson et al. 1992 [3]. |
6.91
|
length__mm
|
float
|
Length of the muscle in millimeters. Default is 30.0 mm, a nominal value chosen to match the order of magnitude of the FDI muscle; adjust to match the muscle under study. |
30.0
|
fiber_density__fibers_per_mm2
|
float
|
Density of muscle fibers per square millimeter. Default is set to 350 fibers/mm² as determined by Bettelho et al. 2019 [7]. |
350
|
max_innervation_area_to_total_muscle_area__ratio
|
float
|
Ratio defining the maximum territory size relative to total muscle area. Default is 0.25 as a pragmatic upper bound for the FDI, with no single published source; revisit for larger muscles. A value of 0.25 means the largest motor unit can innervate up to 25% of the total muscle cross-sectional area. Must be in range (0, 1]. |
0.25
|
mean_conduction_velocity__m_per_s
|
float
|
Mean conduction velocity in m/s. Default is set to 4.2 m/s as determined by Nishizono et al. 1990 [4]. Experimental range determined by Nishizono et al. 1990 [4] is between 3.2 and 5.0 m/s. |
4.2
|
mean_fiber_length__mm
|
float
|
Mean fiber length in mm. Default is set to 31.7 mm as determined by Jacobson et al. 1992 [3] (Table 1). |
31.7
|
var_fiber_length__mm
|
float
|
Fiber length variance in mm. Default is set to 2.8 mm as determined by Jacobson et al. 1992 [3] (Table 1). |
2.8
|
radius_bone__mm
|
float
|
Bone radius in mm. Default is set to 1 mm. |
1
|
fat_thickness__mm
|
float
|
Fat thickness in mm. Default is set to 0.3 mm as determined by Störchle et al. 2018 [5]. |
0.3
|
skin_thickness__mm
|
float
|
Skin thickness in mm. Default is set to the male skin thickness average of 1.29 mm as determined by Brodar 1960 [6]. |
1.29
|
muscle_conductivity_radial__S_per_m
|
float
|
Muscle conductivity in radial direction. Default is set to 0.09 S/m as determined by Botelho et al. 2019 [7] (Table 1). |
0.09
|
muscle_conductivity_longitudinal__S_per_m
|
float
|
Muscle conductivity in longitudinal direction. Default is set to 0.4 S/m as determined by Botelho et al. 2019 [7] (Table 1). |
0.4
|
fat_conductivity__S_per_m
|
float
|
Fat conductivity. Default is set to 4.07E-2 S/m as determined by Botelho et al. 2019 [7] (Table 1). |
4.07E-2
|
skin_conductivity__S_per_m
|
float
|
Skin conductivity. Default is set to 4.88E-4 S/m as determined by Botelho et al. 2019 [7] (Table 1). |
4.88E-4
|
grid_resolution
|
int
|
Resolution of the computational grid used for innervation the muscle. Higher values provide more accurate spatial distribution but increase computational cost. Default is set to 256. |
256
|
autorun
|
bool
|
If True, automatically executes the complete muscle simulation pipeline: innervation distribution, muscle fiber generation, and fiber-to-motor unit assignment. If False, these steps must be called manually. |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
innervation_center_positions__mm |
ndarray
|
Motor unit innervation center positions [x, y] in mm. Available after distribute_innervation_centers(). |
muscle_fiber_centers__mm |
ndarray
|
Muscle fiber center positions [x, y] in mm. Available after generate_muscle_fiber_centers(). |
muscle_fiber_diameters__mm |
ndarray
|
Muscle fiber diameters in mm. Available after _generate_fiber_properties(). |
muscle_fiber_conduction_velocities__mm_per_s |
ndarray
|
Muscle fiber conduction velocities in mm/s. Available after _generate_fiber_properties(). |
assignment |
ndarray
|
Motor unit assignment for each muscle fiber. Available after assign_mfs2mns(). |
number_of_muscle_fibers |
int
|
Total number of muscle fibers. Available after generate_muscle_fiber_centers(). |
muscle_border__mm |
ndarray
|
Muscle boundary points for visualization. Available after generate_muscle_fiber_centers(). |
resulting_number_of_innervated_fibers |
ndarray
|
Actual number of fibers per motor unit. Available after assign_mfs2mns(). |
resulting_innervation_areas__mm2 |
ndarray
|
Actual innervation areas per motor unit in mm². Available after assign_mfs2mns(). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If max_innervation_area_to_total_muscle_area__ratio is not in (0, 1]. |
References
[1] Farina, D., Mesin, L., Martina, S., Merletti, R., 2004. A surface EMG generation model with multilayer cylindrical description of the volume conductor. IEEE Transactions on Biomedical Engineering 51, 415–426. https://doi.org/10.1109/TBME.2003.820998
[2] Konstantin, A., Yu, T., Le Carpentier, E., Aoustin, Y., Farina, D., 2020. Simulation of Motor Unit Action Potential Recordings From Intramuscular Multichannel Scanning Electrodes. IEEE Transactions on Biomedical Engineering 67, 2005–2014. https://doi.org/10.1109/TBME.2019.2953680
[3] Jacobson, M.D., Raab, R., Fazeli, B.M., Abrams, R.A., Botte, M.J., Lieber, R.L., 1992. Architectural design of the human intrinsic hand muscles. The Journal of Hand Surgery 17, 804–809. https://doi.org/10.1016/0363-5023(92)90446-V
[4] Nishizono, H., Fujimoto, T., Ohtake, H., Miyashita, M., 1990. Muscle fiber conduction velocity and contractile properties estimated from surface electrode arrays. Electroencephalography and Clinical Neurophysiology 75, 75–81. https://doi.org/10.1016/0013-4694(90)90154-C
[5] Störchle, P., Müller, W., Sengeis, M., Lackner, S., Holasek, S., Fürhapter-Rieger, A., 2018. Measurement of mean subcutaneous fat thickness: eight standardised ultrasound sites compared to 216 randomly selected sites. Sci Rep 8, 16268. https://doi.org/10.1038/s41598-018-34213-0
[6] Brodar, V., 1960. Observations on skin thickness and subcutaneous tissue in man. Zeitschrift für Morphologie und Anthropologie 50, 386–395.
[7] Botelho, D.P., Curran, K., Lowery, M.M., 2019. Anatomically accurate model of EMG during index finger flexion and abduction derived from diffusion tensor imaging. PLOS Computational Biology 15, e1007267. https://doi.org/10.1371/journal.pcbi.1007267
Source code in myogen/simulator/core/muscle/muscle.py
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | |
resulting_number_of_innervated_fibers
property
¶
resulting_number_of_innervated_fibers: ndarray
Calculate the actual number of muscle fibers assigned to each motor unit.
This property returns the final fiber counts after the assignment process, which may differ slightly from the desired counts due to the stochastic assignment algorithm and discrete fiber distribution.
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of length n_motor_units where each element represents the actual number of muscle fibers assigned to the corresponding motor unit. The sum of all elements equals the total number of muscle fibers. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If muscle fiber assignment has not been completed yet. |
Examples:
>>> actual_counts = muscle.resulting_number_of_innervated_fibers
>>> desired_counts = muscle.desired_number_of_innervated_fibers
>>> print(f"Motor unit 0: desired {desired_counts[0]}, actual {actual_counts[0]}")
Notes
This property can be used to assess how well the assignment algorithm achieved the target fiber distribution. Large deviations may indicate the need to adjust assignment parameters or increase grid resolution.
resulting_innervation_areas__mm2
property
¶
resulting_innervation_areas__mm2: Quantity__mm2
Calculate the actual innervation areas for each motor unit based on assigned fibers.
The innervation area is computed as the area of a circle that encompasses all muscle fibers assigned to a motor unit, centered on the motor unit's innervation center. This provides a measure of the spatial extent of each motor unit territory.
Returns:
| Type | Description |
|---|---|
Quantity__mm2
|
Array of length n_motor_units containing the innervation area (in mm²) for each motor unit. Areas are calculated as π × r², where r is the maximum distance from the innervation center to any assigned fiber. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If innervation_center_positions is None or assignment has not been completed. |
Examples:
>>> actual_areas = muscle.resulting_innervation_areas__mm2
>>> desired_areas = muscle.desired_innervation_areas__mm2
>>> for i, (actual, desired) in enumerate(zip(actual_areas, desired_areas)):
... print(f"MU {i}: desired {desired:.2f} mm², actual {actual:.2f} mm²")
Notes
The resulting areas may differ from desired areas due to the discrete nature of fiber assignment and the constraint of the circular muscle boundary. Motor units near the muscle periphery may have smaller actual areas than desired due to boundary effects.
innervation_center_positions__mm
property
¶
innervation_center_positions__mm: Quantity__mm
Motor unit innervation center positions [x, y] in mm.
Returns:
| Type | Description |
|---|---|
Quantity__mm
|
Array of shape (n_motor_units, 2) containing [x, y] coordinates in mm. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If innervation centers have not been computed yet. |
muscle_fiber_centers__mm
property
¶
muscle_fiber_centers__mm: Quantity__mm
Muscle fiber center positions [x, y] in mm.
Returns:
| Type | Description |
|---|---|
Quantity__mm
|
Array of shape (n_fibers, 2) containing [x, y] coordinates in mm. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If muscle fiber centers have not been computed yet. |
muscle_fiber_diameters__mm
property
¶
muscle_fiber_diameters__mm: Quantity__mm
Muscle fiber diameters in mm.
Returns:
| Type | Description |
|---|---|
Quantity__mm
|
Array of muscle fiber diameters in mm. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If fiber properties have not been computed yet. |
muscle_fiber_conduction_velocities__mm_per_s
property
¶
muscle_fiber_conduction_velocities__mm_per_s: Quantity__mm_per_s
Muscle fiber conduction velocities in mm/s.
Returns:
| Type | Description |
|---|---|
Quantity__mm_per_s
|
Array of muscle fiber conduction velocities in mm/s. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If fiber properties have not been computed yet. |
assignment
property
¶
assignment: ndarray
Motor unit assignment for each muscle fiber.
Returns:
| Type | Description |
|---|---|
ndarray
|
Array where each element indicates the motor unit index (0 to n_motor_units-1) assigned to that fiber. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If muscle fiber assignment has not been completed yet. |
number_of_muscle_fibers
property
¶
number_of_muscle_fibers: int
Total number of muscle fibers.
Returns:
| Type | Description |
|---|---|
int
|
Total number of muscle fibers. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If muscle fiber centers have not been computed yet. |
muscle_border__mm
property
¶
muscle_border__mm: Quantity__mm
Muscle boundary points for visualization.
Returns:
| Type | Description |
|---|---|
Quantity__mm
|
Array of boundary points for the circular muscle cross-section in mm. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If muscle fiber centers have not been computed yet. |
recruitment_thresholds
property
¶
recruitment_thresholds: RECRUITMENT_THRESHOLDS__ARRAY
Motor unit recruitment thresholds.
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of recruitment thresholds for each motor unit. |
distribute_innervation_centers ¶
Distribute innervation center positions using the fast marching method.
This method implements an optimal packing algorithm to distribute motor unit innervation centers within the circular muscle cross-section. The algorithm uses the Fast Marching Method to ensure that each new innervation center is placed at the location that maximizes the minimum distance to all previously placed centers.
Results are stored in the innervation_center_positions property after execution.
Notes
This method must be called before generate_muscle_fiber_centers() and assign_mfs2mns(). The resulting distribution approximates the optimal packing problem for circles, leading to realistic motor unit territory arrangements.
Source code in myogen/simulator/core/muscle/muscle.py
generate_muscle_fiber_centers ¶
generate_muscle_fiber_centers(verbose: bool = True) -> None
Generate muscle fiber center positions using a pre-computed Voronoi distribution.
This method creates the spatial distribution of muscle fiber centers within the circular muscle cross-section. The distribution is based on a Voronoi tessellation pattern that mimics the natural packing of muscle fibers observed in histological studies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
verbose
|
bool
|
If True, display status messages. Set to False to disable. |
True
|
Notes
Results are stored in the following properties after execution:
mf_centers: Array of shape (n_fibers, 2) with fiber positions [x, y] in mmnumber_of_muscle_fibers: Total number of muscle fibersmuscle_border: Array of border points for visualization
This method should be called after distribute_innervation_centers() and before assign_mfs2mns(). The Voronoi-based distribution provides more realistic fiber spacing compared to regular grids or purely random distributions.
The reference dataset ('voronoi_pi1e5.csv') contains 100,000 pre-computed Voronoi cell centers optimized for circular domains, ensuring efficient and consistent fiber distributions across simulations.
Source code in myogen/simulator/core/muscle/muscle.py
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | |
assign_mfs2mns ¶
assign_mfs2mns(n_neighbours: int = 3, conf: float = 0.999, n_jobs: int = -2, verbose: bool = True) -> None
Assign muscle fibers to motor neurons using biologically realistic principles.
This method implements an assignment algorithm that balances multiple biological constraints:
- Proximity: Fibers closer to innervation centers are more likely to be assigned
- Territory size: Each motor unit has a target number of fibers based on its size
- Self-avoidance: Neighboring fibers avoid belonging to the same motor unit
- Gaussian territories: Fiber territories follow roughly Gaussian distributions
The assignment uses a probabilistic approach where each fiber is assigned based on the posterior probability computed from prior probabilities (target fiber numbers) and likelihoods (spatial clustering with Gaussian territories).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_neighbours
|
int
|
Number of neighboring fibers to consider for self-avoiding phenomena. Higher values increase intermingling between motor units but may slow computation. Typical range: 2-5. |
3
|
conf
|
float
|
Confidence interval that defines the relationship between innervation area and Gaussian distribution variance. Higher values create tighter, more compact territories. Should be between 0.9 and 0.999. |
0.999
|
n_jobs
|
int
|
Number of parallel workers for out-of-circle coefficient computation.
|
-2
|
verbose
|
bool
|
If True, display progress bars and status messages. Set to False to disable. |
True
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If innervation_center_positions is None. Call distribute_innervation_centers() first, or if muscle fiber centers are not available. |
Notes
Results are stored in the assignment property after execution.
The algorithm compensates for out-of-muscle effects by calculating how much of each motor unit's Gaussian distribution falls outside the circular muscle boundary and adjusting the in-muscle probabilities accordingly.
The self-avoidance mechanism promotes realistic intermingling by reducing the probability of assigning a fiber to a motor unit if its neighbors are already assigned to that unit.
Source code in myogen/simulator/core/muscle/muscle.py
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 | |
resulting_fiber_assignment ¶
resulting_fiber_assignment(mu: int) -> Quantity__mm
Get the muscle fiber positions assigned to a specific motor unit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mu
|
int
|
Motor unit index (0-based). Must be less than the total number of motor units. |
required |
Returns:
| Type | Description |
|---|---|
Quantity__mm
|
Array of shape (n_assigned_fibers, 2) containing the [x, y] coordinates (in mm) of all muscle fibers assigned to the specified motor unit. If no fibers are assigned to the motor unit, returns an empty array. |
Raises:
| Type | Description |
|---|---|
IndexError
|
If mu is outside the valid range [0, n_motor_units-1]. |
ValueError
|
If the muscle fiber assignment has not been completed yet. |
Examples:
>>> fiber_positions = muscle.resulting_fiber_assignment(0)
>>> print(f"Motor unit 0 has {len(fiber_positions)} fibers")
>>> print(f"First fiber position: x={fiber_positions[0,0]:.2f}, y={fiber_positions[0,1]:.2f}")
Notes
This method should only be called after assign_mfs2mns() has been executed. The returned coordinates are in the muscle's coordinate system with the origin at the muscle center.
Source code in myogen/simulator/core/muscle/muscle.py
HillModel ¶
HillModel(simulation_time__ms: Quantity__ms, time_step__ms: Quantity__ms, muscle_parameters: dict[str, Any], n_motor_units_type1: int, n_motor_units_type2: int, initial_joint_angle__deg: float, initial_muscle_length__L0: float = -1.0, muscle_role: Literal['flexor', 'extensor'] = 'flexor')
API wrapper for the Hill muscle model.
This class provides an intuitive interface for creating Hill muscle models with user-friendly parameter names that are internally mapped to the correct format expected by the underlying Hill implementation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
simulation_time__ms
|
float
|
Total simulation time in milliseconds |
required |
time_step__ms
|
float
|
Integration time step in milliseconds |
required |
muscle_parameters
|
dict[str, Any]
|
Dictionary containing Hill muscle model parameters |
required |
n_motor_units_type1
|
int
|
Number of type I motor units |
required |
n_motor_units_type2
|
int
|
Number of type II motor units |
required |
initial_joint_angle__deg
|
float
|
Initial joint angle in degrees |
required |
initial_muscle_length__L0
|
float
|
Initial muscle length normalized to L0. If -1, automatically calculated from joint angle. Must be between 0.7 and 1.3 if specified. |
-1.0
|
muscle_role
|
str
|
Muscle role for antagonist pairs ("flexor" or "extensor"), by default "flexor". Used for joint dynamics calculations and result organization. |
'flexor'
|
Source code in myogen/simulator/neuron/muscle.py
muscle_acceleration
property
¶
muscle_acceleration: ndarray
Get muscle acceleration time series (L0/s^2).
signed_muscle_torque
property
¶
signed_muscle_torque: ndarray
Get muscle torque with correct sign for joint dynamics (F0*m).
type2_activation
property
¶
type2_activation: ndarray
Get Type II motor unit activation time series.
motor_unit_forces
property
¶
motor_unit_forces: ndarray
Get individual motor unit forces matrix (N_units x time_points).
add_spike ¶
Add a spike event for a specific motor unit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
motor_unit_id
|
int
|
ID of the motor unit (0-based index) |
required |
delay__ms
|
float
|
Spike delay in milliseconds, by default 0.0 |
0.0
|
Source code in myogen/simulator/neuron/muscle.py
integrate ¶
Integrate the muscle model for one time step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
joint_angle__deg
|
float
|
Current joint angle in degrees |
required |
Returns:
| Type | Description |
|---|---|
tuple[float, float, float]
|
Muscle length (normalized to L0), velocity (L0/s), acceleration (L0/s^2) |
Source code in myogen/simulator/neuron/muscle.py
create_default_muscle_parameters
staticmethod
¶
Create default muscle parameter dictionary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
muscle_type
|
str
|
Type of muscle model ("FDI", "Sol"), by default "FDI" |
'FDI'
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary of muscle parameters |
Raises:
| Type | Description |
|---|---|
ValueError
|
If muscle_type is not recognized |
Source code in myogen/simulator/neuron/muscle.py
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | |
ForceModel ¶
ForceModel(recruitment_thresholds: RECRUITMENT_THRESHOLDS__ARRAY, recording_frequency__Hz: Quantity__Hz, longest_duration_rise_time__ms: Quantity__ms = 90.0 * ms, contraction_time_range_factor: float = 3.0)
Force model based on Fuglevand et al. (1993) [1].
This class implements the Fuglevand force generation model for motor unit pools, computing individual motor unit twitch responses and their nonlinear gain modulation based on discharge rates. The model generates realistic force outputs from spike trains using physiologically-based parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
recruitment_thresholds
|
RECRUITMENT_THRESHOLDS__ARRAY
|
Recruitment thresholds for each motor unit. Array of values typically ranging from 0 to 1 where larger motor units have higher thresholds. |
required |
recording_frequency__Hz
|
Quantity__Hz
|
Recording frequency in Hz. Determines temporal resolution of force calculations. Typical values: 100-1000 Hz. |
required |
longest_duration_rise_time__ms
|
Quantity__ms
|
Longest duration of the rise time in milliseconds. This parameter (T_L in _[1]) determines the contraction time of the slowest motor unit. Typical range: 50-150 ms. |
90.0 * pq.ms
|
contraction_time_range_factor
|
float
|
Contraction time range factor (RT in _[1]). Determines the spread of contraction times across motor units. Generally between 2 and 5. Higher values create larger differences between fast and slow motor units. |
3.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
peak_twitch_forces__unitless |
ndarray
|
Peak twitch forces for each motor unit (unitless). Available after initialization. Computed according to Fuglevand equation 13. |
contraction_times__samples |
ndarray
|
Contraction times for each motor unit in samples. Available after initialization. Computed according to Fuglevand equation 14. |
twitch_mat |
ndarray
|
Complete twitch matrix for all motor units. Available after initialization. Shape: (max_twitch_length, n_motor_units). |
twitch_list |
list[ndarray]
|
List of individual twitch responses for each motor unit. Available after initialization. Each element contains the twitch response for one motor unit. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If recruitment_thresholds is empty or contains invalid values. If recording_frequency__Hz is not positive. If longest_duration_rise_time__ms is not positive. If contraction_time_range_factor is not greater than 1. |
References
[1] Fuglevand, A. J., Winter, D. A., & Patla, A. E. (1993). Models of recruitment and rate coding in motor-unit pools. Journal of Neurophysiology, 70(2), 782-797.
Examples:
>>> import numpy as np
>>> from myogen.simulator.core.force import ForceModel
>>> thresholds = np.linspace(0.1, 1.0, 10)
>>> force_model = ForceModel(
... recruitment_thresholds=thresholds,
... recording_frequency__Hz=2000.0
... )
Source code in myogen/simulator/core/force/force_model.py
peak_twitch_forces__unitless
property
¶
peak_twitch_forces__unitless: ndarray
Peak twitch forces for each motor unit (unitless).
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of peak twitch forces according to Fuglevand model equation 13. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If twitch parameters have not been computed yet. |
contraction_times__samples
property
¶
contraction_times__samples: ndarray
Contraction times for each motor unit in samples.
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of contraction times according to Fuglevand model equation 14. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If twitch parameters have not been computed yet. |
twitch_mat
property
¶
twitch_mat: ndarray
Complete twitch matrix for all motor units.
Returns:
| Type | Description |
|---|---|
ndarray
|
Matrix of shape (max_twitch_length, n_motor_units) containing the twitch responses for each motor unit. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If twitches have not been initialized yet. |
twitch_list
property
¶
List of individual twitch responses for each motor unit.
Returns:
| Type | Description |
|---|---|
list[ndarray]
|
List where each element is the twitch response array for one motor unit. Each array may have different lengths based on the motor unit's contraction time. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If twitches have not been initialized yet. |
generate_force ¶
generate_force(spike_train__Block: SPIKE_TRAIN__Block, verbose: bool = True) -> FORCE__AnalogSignal
Generate force output from motor unit spike trains using the Fuglevand model.
This method simulates muscle force by converting spike trains into force output through individual motor unit twitches with nonlinear gain modulation based on discharge rate. Each motor unit contributes to the total force according to its twitch properties and firing pattern. The output is resampled to match the recording_frequency__Hz parameter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spike_train__Block
|
SPIKE_TRAIN__Block
|
Spike train block containing spike train data for multiple motor neuron pools. |
required |
verbose
|
bool
|
If True, display progress bars during force generation. Set to False to disable. |
True
|
Returns:
| Type | Description |
|---|---|
FORCE__AnalogSignal
|
Force output neo.AnalogSignal representing muscle force over time. Each channel corresponds to one motor neuron pool's force response. Sampling rate matches the recording_frequency__Hz parameter. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If spike train matrix dimensions don't match the number of motor units. If twitch parameters have not been computed. |
Notes
The force generation follows these steps: 1. Convert spike trains to inter-pulse intervals (IPIs) 2. Calculate nonlinear gain based on discharge rates 3. Sum weighted twitch responses for each spike 4. Apply gain modulation to final force output 5. Resample output to match recording_frequency__Hz
Source code in myogen/simulator/core/force/force_model.py
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | |
ForceModelVectorized ¶
ForceModelVectorized(recruitment_thresholds: RECRUITMENT_THRESHOLDS__ARRAY, recording_frequency__Hz: Quantity__Hz, longest_duration_rise_time__ms: Quantity__ms = 90.0 * ms, contraction_time_range_factor: float = 3.0)
Vectorized force model based on Fuglevand et al. (1993) [1].
This is an optimized version of ForceModel that uses numpy
vectorization for significantly better performance, especially for long
simulations. It shares the IPI/gain/twitch pipeline with the reference
implementation via force_utils so the output is guaranteed to match
the reference model bit-for-bit (modulo per-spike accumulation order).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
recruitment_thresholds
|
RECRUITMENT_THRESHOLDS__ARRAY
|
Recruitment thresholds for each motor unit. |
required |
recording_frequency__Hz
|
Quantity__Hz
|
Recording frequency in Hz. Determines temporal resolution of force calculations. Typical values: 100-1000 Hz. |
required |
longest_duration_rise_time__ms
|
Quantity__ms
|
Longest duration of the rise time in milliseconds. |
90.0 * pq.ms
|
contraction_time_range_factor
|
float
|
Contraction time range factor. Determines the spread of contraction times across motor units. Generally between 2 and 5. |
3.0
|
References
[1] Fuglevand, A. J., Winter, D. A., & Patla, A. E. (1993). Models of recruitment and rate coding in motor-unit pools. Journal of Neurophysiology, 70(2), 782-797.
Source code in myogen/simulator/core/force/force_model_vectorized.py
generate_force ¶
generate_force(spike_train__Block: SPIKE_TRAIN__Block, verbose: bool = True) -> FORCE__AnalogSignal
Generate force output from motor unit spike trains.
The body mirrors ForceModel.generate_force so that the two
implementations cannot drift apart silently. Only the per-spike
accumulation differs (vectorized vs. per-spike loop).
Source code in myogen/simulator/core/force/force_model_vectorized.py
EMG¶
SurfaceEMG ¶
SurfaceEMG(muscle_model: Muscle, electrode_arrays: list[SurfaceElectrodeArray], sampling_frequency__Hz: Quantity__Hz = 2048.0 * Hz, sampling_points_in_t_and_z_domains: int = 256, sampling_points_in_theta_domain: int = 32, MUs_to_simulate: list[int] | None = None, internal_sampling_frequency__Hz: Quantity__Hz | None = None, iap_kernel_length__mm: float | None = None, use_unified: bool = False)
Surface Electromyography (sEMG) Simulation.
This class provides a simulation framework for generating surface electromyography signals from the muscle. It implements the multi-layered cylindrical volume conductor model from Farina et al. 2004 [1].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
muscle_model
|
Muscle
|
Pre-computed muscle model (see |
required |
electrode_arrays
|
list[SurfaceElectrodeArray]
|
List of electrode arrays to use for simulation (see |
required |
sampling_frequency__Hz
|
float
|
Sampling frequency in Hz. Default is set to 2048 Hz as used by the Quattrocento (OT Bioelettronica, Turin, Italy) system. |
2048.0
|
sampling_points_in_t_and_z_domains
|
int
|
Spatial and temporal discretization resolution for numerical integration. Controls the accuracy of the volume conductor calculations but significantly impacts computational cost (scales quadratically). Higher values provide better numerical accuracy at the expense of simulation time. Default is set to 256 samples. |
256
|
sampling_points_in_theta_domain
|
int
|
Angular discretization for cylindrical coordinate system in degrees. Higher values provide better spatial resolution but cause numerical overflow in Bessel functions. Default is set to 32 points to avoid numerical instability. WARNING: Values >64 cause extreme Bessel function overflow leading to incorrect results. This is suitable for most EMG studies. |
32
|
MUs_to_simulate
|
list[int]
|
Indices of motor units to simulate. If None, all motor units are simulated. Default is None. For computational efficiency, consider simulating subsets for initial analysis. Indices correspond to the recruitment order (0 is recruited first). |
None
|
internal_sampling_frequency__Hz
|
Quantity__Hz
|
Internal sampling frequency for MUAP computation before downsampling. If None, defaults to 10 kHz. Higher values provide better temporal resolution but increase computation time. Default is 10 kHz. |
None
|
iap_kernel_length__mm
|
float
|
Physical spatial extent for intracellular action potential (IAP) kernel evaluation in mm. If None (default), uses individual fiber lengths from muscle model, ensuring MUAP duration is physiologically accurate and independent of sampling resolution. Recommended: Leave as None to use fiber-specific lengths for most realistic MUAPs. Alternatively, set to a fixed value (e.g., 80-100 mm) to use the same kernel extent for all fibers, which can simplify analysis but may be less physiologically accurate for muscles with variable fiber lengths. This parameter controls the spatial extent over which the IAP waveform is computed, directly affecting MUAP duration: duration ≈ iap_kernel_length__mm / (2 * v) ms. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
muaps__Block |
SURFACE_MUAP__Block
|
Motor Unit Action Potential (MUAP) templates for each electrode array as a neo.Block. Available after simulate_muaps(). |
surface_emg__Block |
SURFACE_EMG__Block
|
Surface EMG signals for each electrode array as a neo.Block. Available after simulate_surface_emg(). |
noisy_surface_emg__Block |
SURFACE_EMG__Block
|
Noisy surface EMG signals for each electrode array as a neo.Block. Available after add_noise(). |
spike_train__Block |
SPIKE_TRAIN__Block
|
Spike train block used for EMG generation signals. Available after simulate_surface_emg(). |
References
[1] Farina, D., Mesin, L., Martina, S., Merletti, R., 2004. A surface EMG generation model with multilayer cylindrical description of the volume conductor. IEEE Transactions on Biomedical Engineering 51, 415–426. https://doi.org/10.1109/TBME.2003.820998
Source code in myogen/simulator/core/emg/surface/surface_emg.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
muaps__Block
property
¶
muaps__Block: SURFACE_MUAP__Block
Motor Unit Action Potential (MUAP) templates for each electrode array.
Returns:
| Type | Description |
|---|---|
list[SURFACE_MUAP_SHAPE__TENSOR]
|
List of MUAP templates for each electrode array. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If MUAP templates have not been computed yet. |
surface_emg__Block
property
¶
surface_emg__Block: SURFACE_EMG__Block
Surface EMG signals for each electrode array stored in a neo.Block.
Returns:
| Type | Description |
|---|---|
SURFACE_EMG__Block
|
Surface EMG signals for each electrode array stored in a neo.Block. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If surface EMG has not been computed yet. |
noisy_surface_emg__Block
property
¶
noisy_surface_emg__Block: SURFACE_EMG__Block
Noisy surface EMG signals for each electrode array.
Returns:
| Type | Description |
|---|---|
SURFACE_EMG__Block
|
Noisy surface EMG signals for each electrode array. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If noisy surface EMG has not been computed yet. |
spike_train__Block
property
¶
spike_train__Block: SPIKE_TRAIN__Block
Spike train block used for EMG generation.
Returns:
| Type | Description |
|---|---|
SPIKE_TRAIN__Block
|
The spike train block used in the simulation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If spike train block has not been set yet. |
simulate_muaps ¶
simulate_muaps(n_jobs: int = -2, verbose: bool = True, use_gpu: Optional[bool] = None) -> SURFACE_MUAP__Block
Simulate MUAPs for all electrode arrays using the provided muscle model.
This method generates Motor Unit Action Potential (MUAP) templates that represent the electrical signature of each motor unit as recorded by the surface electrodes. The simulation uses the multi-layered cylindrical volume conductor model with parallel processing for improved performance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_jobs
|
int
|
Number of parallel workers for motor unit processing. Default is -2. - n_jobs=-1: Use all CPU cores - n_jobs=-2: Use all cores except one (recommended, keeps system responsive) - n_jobs=-3: Use all cores except two - n_jobs=1: No parallelization - n_jobs=N: Use exactly N cores |
-2
|
verbose
|
bool
|
If True, display progress bars. Set to False to disable. |
True
|
use_gpu
|
bool or None
|
GPU acceleration control for the per-fiber volume-conductor solve
(mirrors
Note: CuPy only supports NVIDIA GPUs (CUDA). AMD/ROCm is not supported. For typical surface-EMG problem sizes, CPU is often faster than GPU due to host↔device transfer overhead. |
None
|
Returns:
| Type | Description |
|---|---|
SURFACE_MUAP__Block
|
neo.Block of generated MUAP templates for each electrode array.
Results are stored in the |
Notes
This method must be called before simulate_surface_emg(). The generated MUAP templates are used as basis functions for EMG signal synthesis.
The motor units are processed in parallel using joblib, with each motor unit's fibers processed sequentially to maintain optimization efficiency.
Source code in myogen/simulator/core/emg/surface/surface_emg.py
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 | |
simulate_surface_emg ¶
simulate_surface_emg(spike_train__Block: SPIKE_TRAIN__Block, verbose: bool = True) -> SURFACE_EMG__Block
Generate surface EMG signals for all electrode arrays using the provided spike train block.
This method convolves the pre-computed MUAP templates with the spike trains to synthesize realistic surface EMG signals. The process includes temporal resampling to match the spike train timestep and supports both CPU and GPU acceleration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spike_train__Block
|
SPIKE_TRAIN__Block
|
Block containing spike trains organized as segments (pools) with spiketrains. |
required |
verbose
|
bool
|
If True, display progress bars. Set to False to disable. |
True
|
Returns:
| Type | Description |
|---|---|
SURFACE_EMG__Block
|
Surface EMG signals for each electrode array stored in a neo.Block.
Results are stored in the |
Raises:
| Type | Description |
|---|---|
ValueError
|
If MUAP templates have not been generated. Call simulate_muaps() first. |
Source code in myogen/simulator/core/emg/surface/surface_emg.py
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 | |
add_noise ¶
add_noise(snr__dB: float, noise_type: str = 'gaussian') -> SURFACE_EMG__Block
Add noise to all electrode arrays.
This method adds realistic noise to the simulated surface EMG signals based on a specified signal-to-noise ratio. The noise is calculated and applied independently for each electrode channel to ensure that channels with different signal amplitudes maintain the specified SNR.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
snr__dB
|
float
|
Signal-to-noise ratio in dB. Higher values result in cleaner signals. Typical physiological EMG has SNR ranging from 10-40 dB. The SNR is applied independently to each electrode channel. |
required |
noise_type
|
str
|
Type of noise to add. Currently supports "gaussian" for white noise. |
"gaussian"
|
Returns:
| Type | Description |
|---|---|
SURFACE_EMG__Block
|
Noisy EMG signals for each electrode array as a neo.Block.
Results are stored in the |
Raises:
| Type | Description |
|---|---|
ValueError
|
If surface EMG has not been simulated. Call simulate_surface_emg() first. |
Notes
The noise is computed per-channel (per electrode) to maintain the specified SNR independently across all channels. This ensures that electrodes with different signal amplitudes receive appropriately scaled noise.
Source code in myogen/simulator/core/emg/surface/surface_emg.py
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 | |
IntramuscularEMG ¶
IntramuscularEMG(muscle_model: Muscle, electrode_array: IntramuscularElectrodeArray, sampling_frequency__Hz: Quantity__Hz = 10240.0 * Hz, spatial_resolution__mm: Quantity__mm = 0.01 * mm, endplate_center__percent: float = 50, nmj_jitter__s: Quantity__s = 3.5e-05 * s, branch_cvs__m_per_s: tuple[Quantity__m_per_s, Quantity__m_per_s] = (5.0 * m / s, 2.0 * m / s), MUs_to_simulate: list[int] | None = None)
Intramuscular Electromyography (iEMG) Simulation.
This class provides a comprehensive simulation framework for generating intramuscular EMG signals detected by needle electrodes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
muscle_model
|
Muscle
|
Pre-computed muscle model (see |
required |
electrode_array
|
IntramuscularElectrodeArray
|
Intramuscular electrode array configuration to use for simulation (see |
required |
sampling_frequency__Hz
|
Quantity__Hz
|
Sampling frequency in Hz for EMG simulation. Default is set to 10240 Hz as used by the Quattrocento (OT Bioelettronica, Turin, Italy) system. |
10240.0 * pq.Hz
|
spatial_resolution__mm
|
Quantity__mm
|
Spatial resolution for fiber action potential calculation in mm. Default is set to 0.01 mm. |
0.01 * pq.mm
|
endplate_center__percent
|
float
|
Percentage of muscle length where the endplate is located. By default, the endplate is located at the center of the muscle (50% of the muscle length). |
50
|
nmj_jitter__s
|
Quantity__s
|
Standard deviation of neuromuscular junction jitter in seconds. Default is set to 35e-6 s as determined by Konstantin et al. 2020 [1]. |
35e-6 * pq.s
|
branch_cvs__m_per_s
|
tuple[Quantity__m_per_s, Quantity__m_per_s]
|
Conduction velocities for the two-layer model of the neuromuscular junction in m/s. Default is set to (5.0, 2.0) m/s as determined by Konstantin et al. 2020 [1]. Note: The two-layer model is a simplification of the actual arborization pattern, but it is a good approximation for the purposes of this simulation. Follows the implementation of Konstantin et al. 2020 [1]. |
(5.0 * pq.m / pq.s, 2.0 * pq.m / pq.s)
|
MUs_to_simulate
|
list[int]
|
Indices of motor units to simulate. If None, all motor units are simulated. Default is None. For computational efficiency, consider simulating subsets for initial analysis. Indices correspond to the recruitment order (0 is recruited first). |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
muaps__Block |
INTRAMUSCULAR_MUAP__Block
|
Intramuscular MUAP shapes for the electrode array as a neo.Block. Available after simulate_muaps(). |
intramuscular_emg__Block |
INTRAMUSCULAR_EMG__Block
|
Intramuscular EMG signals for the electrode array as a neo.Block. Available after simulate_intramuscular_emg(). |
noisy_intramuscular_emg__Block |
INTRAMUSCULAR_EMG__Block
|
Noisy intramuscular EMG signals for the electrode array as a neo.Block. Available after add_noise(). |
spike_train__Block |
SPIKE_TRAIN__Block
|
Spike train block used for EMG generation. Available after simulate_intramuscular_emg(). |
References
[1] Konstantin, A., Yu, T., Le Carpentier, E., Aoustin, Y., Farina, D., 2020. Simulation of Motor Unit Action Potential Recordings From Intramuscular Multichannel Scanning Electrodes. IEEE Transactions on Biomedical Engineering 67, 2005–2014. https://doi.org/10.1109/TBME.2019.2953680
Source code in myogen/simulator/core/emg/intramuscular/intramuscular_emg.py
muaps__Block
property
¶
muaps__Block: INTRAMUSCULAR_MUAP__Block
Intramuscular MUAP shapes for the electrode array.
Returns:
| Type | Description |
|---|---|
INTRAMUSCULAR_MUAP__Block
|
Intramuscular MUAP templates for the electrode array as a neo.Block. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If MUAP templates have not been computed yet. |
intramuscular_emg__Block
property
¶
intramuscular_emg__Block: INTRAMUSCULAR_EMG__Block
Intramuscular EMG signals for the electrode array.
Returns:
| Type | Description |
|---|---|
INTRAMUSCULAR_EMG__Block
|
Intramuscular EMG signals for the electrode array as a neo.Block. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If intramuscular EMG has not been computed yet. |
noisy_intramuscular_emg__Block
property
¶
noisy_intramuscular_emg__Block: INTRAMUSCULAR_EMG__Block
Noisy intramuscular EMG signals for the electrode array.
Returns:
| Type | Description |
|---|---|
INTRAMUSCULAR_EMG__Block
|
Noisy intramuscular EMG signals for the electrode array as a neo.Block. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If noisy intramuscular EMG has not been computed yet. |
spike_train__Block
property
¶
spike_train__Block: SPIKE_TRAIN__Block
Spike train block used for EMG generation.
Returns:
| Type | Description |
|---|---|
SPIKE_TRAIN__Block
|
The spike train block used in the simulation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If spike train block has not been set yet. |
simulate_muaps ¶
simulate_muaps(n_jobs: int = -2, verbose: bool = True) -> INTRAMUSCULAR_MUAP__Block
Simulate MUAPs for all electrode arrays using the provided muscle model.
This method generates intramuscular Motor Unit Action Potential (MUAP) templates by simulating individual motor units with realistic neuromuscular junction distributions and fiber action potential propagation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_jobs
|
int
|
Number of parallel workers for motor unit processing. Default is -2. - n_jobs=-1: Use all CPU cores - n_jobs=-2: Use all cores except one (recommended, keeps system responsive) - n_jobs=-3: Use all cores except two - n_jobs=1: No parallelization - n_jobs=N: Use exactly N cores |
-2
|
verbose
|
bool
|
If True, display progress bars. Set to False to disable. |
True
|
Returns:
| Type | Description |
|---|---|
INTRAMUSCULAR_MUAP__Block
|
Intramuscular MUAP shapes for all motor units stored in a neo.Block.
Results are stored in the |
Notes
This method must be called before simulate_intramuscular_emg(). The process includes: (1) motor unit initialization, (2) neuromuscular junction simulation, and (3) MUAP calculation with spatial filtering.
Source code in myogen/simulator/core/emg/intramuscular/intramuscular_emg.py
simulate_intramuscular_emg ¶
simulate_intramuscular_emg(spike_train__Block: SPIKE_TRAIN__Block, verbose: bool = True) -> INTRAMUSCULAR_EMG__Block
Generate intramuscular EMG signals using the provided spike train block.
This method convolves the pre-computed MUAP templates with spike trains to synthesize realistic intramuscular EMG signals. The process includes temporal resampling and supports both CPU and GPU acceleration for efficient computation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spike_train__Block
|
SPIKE_TRAIN__Block
|
Block containing spike trains organized as segments (pools) with spiketrains. |
required |
verbose
|
bool
|
If True, display progress bars. Set to False to disable. |
True
|
Returns:
| Type | Description |
|---|---|
INTRAMUSCULAR_EMG__Block
|
Intramuscular EMG signals for the electrode array stored in a neo.Block.
Results are stored in the |
Raises:
| Type | Description |
|---|---|
ValueError
|
If MUAP templates have not been generated. Call simulate_muaps() first. |
Source code in myogen/simulator/core/emg/intramuscular/intramuscular_emg.py
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | |
add_noise ¶
add_noise(snr__dB: float, noise_type: str = 'gaussian', *, spectral_slope: float = -0.5, excess_kurtosis: float = 3.0, powerline_hz: float = 50.0, powerline_amplitude: float = 0.1, powerline_harmonic_ratios: Optional[list[float]] = None, powerline_frequency_drift_hz: float = 0.3, powerline_amplitude_modulation_depth: float = 0.15, peak_hz: float = 1000.0, analog_hpf_hz: float = 10.0, baseline_drift_rms_uv: float = 0.0, baseline_drift_alpha: float = 1.75, baseline_drift_low_hz: float | None = None, baseline_drift_high_hz: float = 1.0) -> INTRAMUSCULAR_EMG__Block
Add noise to the electrode array.
Two noise models are available:
"gaussian"– white Gaussian noise (legacy default). Each electrode channel gets independent normal noise scaled to hit the requested per-channel SNR."realistic"– spectrally colored noise calibrated against real bipolar fine-wire iEMG recordings (TEP / Synergy studies). 1/f-like base, mid-band spectral emphasis from electrode–amplifier bandwidth, heavy tails from cross-talk artifacts, and additive 50/60 Hz powerline interference with harmonics. Seemyogen.utils.emg_noisefor the math.
Per-channel SNR is preserved across both modes: each electrode's noise RMS is computed from that channel's own signal RMS so electrodes with different amplitudes get appropriately scaled noise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
snr__dB
|
float
|
Signal-to-noise ratio in dB. Higher values result in cleaner signals. Typical intramuscular EMG has SNR ranging from 15–50 dB. Applied independently to each electrode channel. |
required |
noise_type
|
(gaussian, realistic)
|
Noise model to use. |
"gaussian"
|
spectral_slope
|
float
|
PSD slope in log–log space for the colored-noise base.
|
-0.5
|
excess_kurtosis
|
float
|
Target excess kurtosis ( |
3.0
|
powerline_hz
|
float
|
Powerline interference frequency. Use |
50.0
|
powerline_amplitude
|
float
|
Powerline fundamental amplitude as a fraction of noise RMS.
Set to |
0.1
|
powerline_harmonic_ratios
|
list of float
|
Per-harmonic amplitude ratios relative to the fundamental.
|
None
|
powerline_frequency_drift_hz
|
float
|
Standard deviation (Hz) of the slow random walk of the
mains instantaneous frequency. Broadens each line peak
from a delta into a ~2-5 Hz FWHM bump (typical of real
recordings). Set to 0 for a pure-tone powerline.
Ignored when |
0.3
|
powerline_amplitude_modulation_depth
|
float
|
Fractional AM depth (±15% by default) applied to each
powerline harmonic — adds narrow sidebands within ±2 Hz
of every line. Set to 0 to disable.
Ignored when |
0.15
|
peak_hz
|
float
|
Center frequency of the mid-band spectral emphasis from
electrode–amplifier bandwidth interaction.
Ignored when |
1000.0
|
baseline_drift_rms_uv
|
float
|
Target RMS (post-HPF) of a band-limited 1/f^α baseline
drift representing electrode/interface noise (Huigen 2002,
Gondran 1996). Same units as the EMG block. Set to 0 (the
default) to disable, preserving legacy behaviour.
The spectral form is paper-constrained; the amplitude
defaults are not validated for intramuscular EMG —
calibrate against real recordings via
|
0.0
|
baseline_drift_alpha
|
float
|
Drift PSD slope α (PSD ∝ 1/f^α). Midpoint of the [1.5, 2.0]
electrode-noise regime. Must be > 0.
Ignored when |
1.75
|
baseline_drift_low_hz
|
float or None
|
Lower edge of the drift band, in Hz. |
None
|
baseline_drift_high_hz
|
float
|
Upper edge of the drift band, in Hz. Default keeps the
knob scoped to sub-1 Hz baseline wander.
Ignored when |
1.0
|
Returns:
| Type | Description |
|---|---|
INTRAMUSCULAR_EMG__Block
|
Noisy intramuscular EMG signals for the electrode array as a
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If intramuscular EMG has not been simulated (call
|
Source code in myogen/simulator/core/emg/intramuscular/intramuscular_emg.py
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 | |
SurfaceElectrodeArray ¶
SurfaceElectrodeArray(num_rows: int, num_cols: int, inter_electrode_distance__mm: Quantity__mm, electrode_radius__mm: Quantity__mm, center_point__mm_deg: tuple[Quantity__mm, Quantity__deg] = (0.0 * mm, 0.0 * deg), bending_radius__mm: Quantity__mm = 0.0 * mm, rotation_angle__deg: Quantity__deg = 0.0 * deg, differentiation_mode: Literal['monopolar', 'bipolar_longitudinal', 'bipolar_transversal', 'laplacian'] = 'monopolar')
Surface electrode array for EMG recording.
Represents a grid of surface electrodes with configurable spacing, size, and differentiation modes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_rows
|
int
|
Number of rows in the electrode array |
required |
num_cols
|
int
|
Number of columns in the electrode array |
required |
inter_electrode_distance__mm
|
float
|
Inter-electrode distance in mm. |
required |
electrode_radius__mm
|
float
|
Radius of the electrodes in mm |
required |
center_point__mm_deg
|
tuple[float, float]
|
Position along z in mm and rotation around the muscle theta in degrees. |
(0.0 * mm, 0.0 * deg)
|
bending_radius__mm
|
float
|
Bending radius around which the electrode grid is bent. Usually this is equal to the radius of the muscle. |
0.0 * mm
|
rotation_angle__deg
|
float
|
Rotation angle of the electrodes in degrees. This is the angle between the electrode grid and the muscle surface. |
0.0 * deg
|
differentiation_mode
|
(monopolar, bipolar_longitudinal, bipolar_transversal, laplacian)
|
Differentiation mode. Default is monopolar. |
"monopolar"
|
Attributes:
| Name | Type | Description |
|---|---|---|
pos_z |
ndarray
|
Longitudinal electrode positions in mm, shape (num_rows, num_cols).
Available after class initialization via |
pos_theta |
ndarray
|
Angular electrode positions in radians, shape (num_rows, num_cols).
Available after class initialization via |
electrode_positions |
tuple[ndarray, ndarray]
|
Complete electrode position arrays (pos_z, pos_theta).
Available after class initialization via |
num_electrodes |
int
|
Total number of electrodes (num_rows * num_cols). |
num_channels |
int
|
Number of recording channels based on differentiation mode. |
Source code in myogen/simulator/core/emg/electrodes.py
pos_z
property
¶
pos_z: Quantity__mm
Longitudinal positions of electrodes in mm.
Returns:
| Type | Description |
|---|---|
Quantity__mm
|
Array of shape (num_rows, num_cols) containing z-coordinates of each electrode position in mm. |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If electrode grid has not been created. Run constructor first. |
pos_theta
property
¶
pos_theta: Quantity__rad
Angular positions of electrodes in radians.
Returns:
| Type | Description |
|---|---|
Quantity__rad
|
Array of shape (num_rows, num_cols) containing angular coordinates of each electrode position in radians. |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If electrode grid has not been created. Run constructor first. |
electrode_positions
property
¶
electrode_positions: tuple[Quantity__mm, Quantity__rad]
Complete electrode position arrays (z, theta) in physical coordinates.
Returns:
| Type | Description |
|---|---|
tuple[Quantity__mm, Quantity__rad]
|
Tuple containing: - pos_z: Longitudinal positions in mm, shape (num_rows, num_cols) - pos_theta: Angular positions in radians, shape (num_rows, num_cols) |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If electrode grid has not been created. Run constructor first. |
num_channels
property
¶
num_channels: int
Number of recording channels based on differentiation mode.
Returns:
| Type | Description |
|---|---|
int
|
Number of recording channels. Depends on |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If channel count has not been calculated. Run constructor first. |
get_H_sf ¶
Get the spatial filter for the electrode array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ktheta_mesh_kzktheta
|
ndarray
|
Angular spatial frequency mesh |
required |
kz_mesh_kzktheta
|
ndarray
|
Longitudinal spatial frequency mesh |
required |
Returns:
| Name | Type | Description |
|---|---|---|
H_sf |
ndarray or float
|
Spatial filter for the specified differentiation mode |
Source code in myogen/simulator/core/emg/electrodes.py
IntramuscularElectrodeArray ¶
IntramuscularElectrodeArray(num_electrodes: int, inter_electrode_distance__mm: Quantity__mm = 0.5 * mm, position__mm: tuple[Quantity__mm, Quantity__mm, Quantity__mm] = (0.0 * mm, 0.0 * mm, 0.0 * mm), orientation__rad: tuple[Quantity__rad, Quantity__rad, Quantity__rad] = (0.0 * rad, 0.0 * rad, 0.0 * rad), differentiation_mode: Literal['consecutive', 'reference'] = 'consecutive', trajectory_distance__mm: Quantity__mm = 0.0 * mm, trajectory_steps: int = 1)
Intramuscular electrode array for EMG recording.
Represents a linear array of intramuscular electrodes (needle electrodes) with configurable spacing and differentiation modes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_electrodes
|
int
|
Number of electrodes in the array |
required |
inter_electrode_distance__mm
|
float
|
Inter-electrode distance in mm |
0.5
|
position__mm
|
tuple[float, float, float]
|
Position of the electrode array center in mm (x, y, z coordinates) |
(0.0, 0.0, 0.0)
|
orientation__rad
|
tuple[float, float, float]
|
Orientation of the electrode array in radians (roll, pitch, yaw) |
(0.0, 0.0, 0.0)
|
differentiation_mode
|
Literal['consecutive', 'reference']
|
Differentiation mode for recording |
"consecutive"
|
trajectory_distance__mm
|
float
|
Distance for trajectory movement in mm |
0.0
|
trajectory_steps
|
int
|
Number of steps in the trajectory |
1
|
Attributes:
| Name | Type | Description |
|---|---|---|
electrode_positions |
ndarray
|
Current electrode positions in 3D space, shape (n_nodes * num_electrodes, 3). Available after set_linear_trajectory() execution. |
differential_matrix |
ndarray
|
Differential matrix for signal processing based on differentiation mode. Available after class initialization. |
trajectory_transforms |
ndarray
|
Transformation matrices for trajectory movement, shape (n_nodes, 6). Available after set_linear_trajectory() execution. |
initial_positions |
ndarray
|
Initial electrode positions after position/orientation setup, shape (num_electrodes, 3). Available after set_position() execution. |
num_channels |
int
|
Number of recording channels based on differentiation mode. Available after class initialization. |
num_points |
int
|
Alias for num_electrodes (compatibility). |
n_nodes |
int
|
Number of trajectory nodes. |
Source code in myogen/simulator/core/emg/electrodes.py
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | |
electrode_positions
property
¶
electrode_positions: Quantity__mm
Current electrode positions in 3D space (mm).
Returns:
| Type | Description |
|---|---|
Quantity__mm
|
Array of shape (n_nodes * num_electrodes, 3) containing x, y, z coordinates of each electrode position for all trajectory nodes, in mm. |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If trajectory has not been calculated. Run set_linear_trajectory() first. |
differential_matrix
property
¶
differential_matrix: ndarray
Differential matrix for signal processing based on differentiation mode.
Returns:
| Type | Description |
|---|---|
ndarray
|
Differential matrix for applying spatial differentiation to recorded signals. Shape depends on differentiation mode and number of trajectory nodes. |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If differential matrix has not been created. Run constructor first. |
trajectory_transforms
property
¶
trajectory_transforms: ndarray
Transformation matrices for trajectory movement.
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of shape (n_nodes, 6) containing translation and rotation parameters for each trajectory node. First 3 columns are translations (x, y, z), last 3 columns are rotations (roll, pitch, yaw). |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If trajectory has not been set. Run set_linear_trajectory() first. |
initial_positions
property
¶
initial_positions: Quantity__mm
Initial electrode positions after position/orientation setup.
Returns:
| Type | Description |
|---|---|
Quantity__mm
|
Array of shape (num_electrodes, 3) containing initial x, y, z coordinates of electrodes before trajectory movement is applied, in mm. |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If initial positions have not been set. Run set_position() first. |
num_channels
property
¶
num_channels: int
Number of recording channels based on differentiation mode.
Returns:
| Type | Description |
|---|---|
int
|
Number of differential recording channels available from this electrode array. |
Raises:
| Type | Description |
|---|---|
AttributeError
|
If channel count has not been calculated. Run constructor first. |
set_position ¶
set_position(position__mm: tuple[Quantity__mm, Quantity__mm, Quantity__mm], orientation__rad: tuple[Quantity__rad, Quantity__rad, Quantity__rad]) -> None
Set the position and orientation of the intramuscular electrode array.
This method defines the spatial placement and angular orientation of the electrode array within the muscle volume. The array is first oriented according to the specified rotations and then translated to the target position.
Coordinate System: - x-axis: radial direction (outward from muscle center) - y-axis: circumferential direction (around muscle) - z-axis: longitudinal direction (along muscle fibers)
Rotation Order: Applied as: Roll (x) → Pitch (y) → Yaw (z) using Rodrigues rotation
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
position__mm
|
tuple[float, float, float]
|
Center position of the electrode array in mm (x, y, z coordinates). This defines where the array center is placed within the muscle. |
required |
orientation__rad
|
tuple[float, float, float]
|
Orientation angles in radians (roll, pitch, yaw). - Roll: rotation around x-axis (radial tilt) - Pitch: rotation around y-axis (circumferential tilt) - Yaw: rotation around z-axis (longitudinal rotation) |
required |
Notes
Position and orientation changes affect all subsequent trajectory calculations. The electrode positions are recalculated based on the new transformation.
Examples:
>>> # Place array at muscle center with 45° yaw rotation
>>> array.set_position(
... position__mm=(0.0, 0.0, 10.0),
... orientation__rad=(0.0, 0.0, np.pi/4)
... )
See Also
set_linear_trajectory : Define trajectory movement parameters rodrigues_rot : Rodrigues rotation implementation
Source code in myogen/simulator/core/emg/electrodes.py
rodrigues_rot ¶
Apply Rodrigues rotation to vectors around an arbitrary axis.
This method implements 3D rotation of points or vectors around an arbitrary axis using the Rodrigues rotation formula. It is used internally for electrode array positioning and trajectory calculations.
Mathematical Foundation: Based on Rodrigues' rotation formula for rotating a vector v around axis k by angle theta: v_rot = vcos(θ) + (k×v)sin(θ) + k(k·v)(1-cos(θ))
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
v
|
array_like
|
Vector(s) to rotate. Can be single vector (3,) or array of vectors (N, 3). |
required |
k
|
array_like
|
Rotation axis vector (3,). Will be normalized internally. |
required |
theta
|
float
|
Rotation angle in radians. Positive angles follow right-hand rule. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Rotated vector(s) with same shape as input v. |
Notes
Uses scipy.spatial.transform.Rotation for numerical stability and efficiency. The rotation axis k is automatically normalized to unit length.
Examples:
>>> # Rotate point 90° around z-axis
>>> point = np.array([1.0, 0.0, 0.0])
>>> rotated = array.rodrigues_rot(point, [0, 0, 1], np.pi/2)
>>> # Result: approximately [0, 1, 0]
Source code in myogen/simulator/core/emg/electrodes.py
set_linear_trajectory ¶
set_linear_trajectory(distance__mm: Quantity__mm, n_nodes: int | None = None) -> None
Configure linear trajectory movement for the electrode array.
This method sets up a linear movement path for the electrode array, simulating needle insertion or withdrawal. The trajectory is discretized into nodes for temporal interpolation during EMG simulation.
Trajectory Properties: - Direction: Along the array's longitudinal axis (z-direction in local coordinates) - Movement: Linear progression from start to end position - Discretization: Evenly spaced nodes for smooth interpolation - Default step size: 0.5mm if n_nodes not specified
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distance__mm
|
float
|
Total trajectory distance in mm. Positive values move in the positive z-direction of the array's local coordinate system. |
required |
n_nodes
|
int
|
Number of discrete trajectory nodes. If None, automatically calculated as max(ceil(distance/0.5), 1) for 0.5mm steps. |
None
|
Notes
The trajectory is applied after position and orientation transformations. All trajectory transforms are calculated in the array's oriented coordinate system.
Examples:
>>> # Set up 10mm insertion with default step size (~0.5mm)
>>> array.set_linear_trajectory(distance__mm=10.0)
>>> # Set up 5mm trajectory with specific number of nodes
>>> array.set_linear_trajectory(distance__mm=5.0, n_nodes=20)
See Also
calc_observation_points : Calculate electrode positions along trajectory traj_mixing_mat : Generate mixing matrices for trajectory interpolation
Source code in myogen/simulator/core/emg/electrodes.py
traj_mixing_fun ¶
traj_mixing_fun(t, n_nodes, node) -> float
Compute mixing weight for a specific trajectory node at given time.
This function calculates the interpolation weight for a trajectory node based on the current time/position along the trajectory. Uses triangular weighting where nodes closer to the current time get higher weights.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t
|
float
|
Current normalized time or position in trajectory (0.0 to 1.0). |
required |
n_nodes
|
int
|
Total number of nodes in the trajectory. |
required |
node
|
int or array_like
|
Node index(es) for which to calculate mixing weights. Can be scalar or array of node indices. |
required |
Returns:
| Type | Description |
|---|---|
float or ndarray
|
Mixing weight(s) for the specified node(s) at time t. Returns 0 for distant nodes, max weight 1 for closest node. |
Source code in myogen/simulator/core/emg/electrodes.py
traj_mixing_mat ¶
traj_mixing_mat(t, n_nodes, n_channels) -> ndarray
Generate mixing matrix for trajectory interpolation during EMG simulation.
This method creates a diagonal mixing matrix that weights the contribution of different trajectory nodes during temporal interpolation. The matrix enables smooth transitions between electrode positions as the array moves along its trajectory during needle insertion or withdrawal.
Interpolation Strategy: - Linear interpolation between adjacent trajectory nodes - Weights based on distance from current time/position to node positions - Diagonal matrix structure for efficient computation - Smooth transitions avoid discontinuities in EMG signals
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t
|
float
|
Current normalized time or position in trajectory (0.0 to 1.0). 0.0 corresponds to trajectory start, 1.0 to trajectory end. |
required |
n_nodes
|
int
|
Total number of trajectory nodes for interpolation. |
required |
n_channels
|
int
|
Number of recording channels in the electrode array. Depends on differentiation mode and electrode count. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Diagonal mixing matrix with shape (n_nodes * n_channels, n_nodes * n_channels). Diagonal elements contain repeated mixing weights for each trajectory node, with each node's weight repeated n_channels times. |
Notes
The mixing matrix enables temporal interpolation of EMG signals recorded at different trajectory positions. Higher weights are given to nodes closer to the current time/position parameter.
Examples:
>>> # Get mixing weights for mid-trajectory position
>>> mix_mat = array.traj_mixing_mat(t=0.5, n_nodes=10, n_channels=4)
>>> # Matrix will weight middle nodes more heavily
See Also
traj_mixing_fun : Individual node mixing function set_linear_trajectory : Configure trajectory parameters
Source code in myogen/simulator/core/emg/electrodes.py
Proprioception¶
SpindleModel ¶
SpindleModel(simulation_time__ms: Quantity__ms, time_step__ms: Quantity__ms, spindle_parameters: dict[str, Any])
API wrapper for the muscle spindle model.
This class provides an intuitive interface for creating muscle spindle models with user-friendly parameter names that are internally mapped to the correct format expected by the underlying Spindle implementation.
The muscle spindle is a proprioceptive sensory organ that detects changes in muscle length and velocity, providing feedback for motor control.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
simulation_time__ms
|
Quantity__ms
|
Total simulation time in milliseconds |
required |
time_step__ms
|
Quantity__ms
|
Integration time step in milliseconds |
required |
spindle_parameters
|
dict[str, Any]
|
Dictionary containing spindle model parameters |
required |
Source code in myogen/simulator/neuron/proprioception/spindle.py
primary_afferent_firing__Hz
property
¶
primary_afferent_firing__Hz: ndarray
Get primary afferent (Ia) firing rate time series in Hz.
secondary_afferent_firing__Hz
property
¶
secondary_afferent_firing__Hz: ndarray
Get secondary afferent (II) firing rate time series in Hz.
intrafusal_tensions
property
¶
intrafusal_tensions: ndarray
Get intrafusal fiber tensions matrix (3 × time_points) [Bag1, Bag2, Chain].
integrate ¶
integrate(muscle_length__L0: float, muscle_velocity__L0_per_s: float, muscle_acceleration__L0_per_s2: float, gamma_dynamic_drive__Hz: float, gamma_static_drive__Hz: float) -> tuple[float, float]
Integrate the spindle model for one time step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
muscle_length__L0
|
float
|
Current muscle length normalized to L0 |
required |
muscle_velocity__L0_per_s
|
float
|
Current muscle velocity in L0/s |
required |
muscle_acceleration__L0_per_s2
|
float
|
Current muscle acceleration in L0/s² |
required |
gamma_dynamic_drive__Hz
|
float
|
Gamma dynamic motor neuron drive frequency in Hz |
required |
gamma_static_drive__Hz
|
float
|
Gamma static motor neuron drive frequency in Hz |
required |
Returns:
| Type | Description |
|---|---|
tuple[float, float]
|
Primary afferent (Ia) and secondary afferent (II) firing rates in Hz |
Source code in myogen/simulator/neuron/proprioception/spindle.py
create_default_spindle_parameters
staticmethod
¶
create_default_spindle_parameters(species: str = 'human', deafferent_ia: bool = False, deafferent_ii: bool = False) -> dict[str, Any]
Create default spindle parameter dictionary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
species
|
str
|
Species type ("human" or "cat"), by default "human" |
'human'
|
deafferent_ia
|
bool
|
Whether to simulate Ia afferent deafferentation, by default False |
False
|
deafferent_ii
|
bool
|
Whether to simulate II afferent deafferentation, by default False |
False
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary of spindle parameters with detailed explanations |
Raises:
| Type | Description |
|---|---|
ValueError
|
If species is not recognized |
Source code in myogen/simulator/neuron/proprioception/spindle.py
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | |
GolgiTendonOrganModel ¶
GolgiTendonOrganModel(simulation_time__ms: Quantity__ms, time_step__ms: Quantity__ms, gto_parameters: dict[str, Any])
API wrapper for the Golgi Tendon Organ (GTO) model.
This class provides an intuitive interface for creating GTO models with user-friendly parameter names that are internally mapped to the correct format expected by the underlying GTO implementation.
The Golgi Tendon Organ is a proprioceptive sensory organ located at the muscle-tendon junction that detects muscle force/tension and provides feedback for motor control and protection against excessive forces.
The model is based on Lin & Crago (2002) and implements a logarithmic force-to-firing relationship with digital filtering for realistic afferent discharge patterns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
simulation_time__ms
|
Quantity__ms
|
Total simulation time in milliseconds |
required |
time_step__ms
|
Quantity__ms
|
Integration time step in milliseconds |
required |
gto_parameters
|
dict[str, Any]
|
Dictionary containing GTO model parameters |
required |
Source code in myogen/simulator/neuron/proprioception/golgi.py
ib_afferent_firing__Hz
property
¶
ib_afferent_firing__Hz: ndarray
Get Ib afferent firing rate time series in Hz.
integrate ¶
create_default_gto_parameters
staticmethod
¶
Create default Golgi Tendon Organ parameter dictionary.
The GTO model uses a logarithmic force-to-firing relationship: firing_rate = G1 * log(force/G2 + 1)
This is followed by digital filtering to create realistic temporal dynamics in the afferent discharge pattern.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary of GTO parameters with detailed explanations |
Notes
Model based on: - Lin & Crago (2002): Mathematical model framework - Aniss et al. (1990b): Human GTO physiological data - Elias PhD thesis (pg 83): Implementation details
The logarithmic relationship captures the GTO's ability to encode force over a wide dynamic range, from threshold detection of small forces to saturation at high forces, providing force feedback for motor control and protective reflexes.
Source code in myogen/simulator/neuron/proprioception/golgi.py
create_gto_parameters_for_muscle
staticmethod
¶
Create GTO parameters optimized for specific muscle types.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
muscle_type
|
str
|
Type of muscle ("FDI", "Sol", "generic"), by default "FDI" |
'FDI'
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary of muscle-specific GTO parameters |
Notes
Different muscles have different force production capabilities and thus require different GTO sensitivity parameters:
- FDI (First Dorsal Interosseous): Small hand muscle, low forces
- Sol (Soleus): Large calf muscle, high forces
- Generic: General-purpose parameters
Source code in myogen/simulator/neuron/proprioception/golgi.py
JointDynamics ¶
JointDynamics(inertia__kg_m2: float, damping__Nm_s_per_rad: float, stiffness__Nm_per_rad: float = 0.0, initial_angle__deg: float = 0.0, initial_velocity__deg_per_s: float = 0.0)
Joint dynamics integrator for closed-loop neuromechanical control.
This class implements second-order joint dynamics using the equation: I⋅α = τ - B⋅ω - K⋅θ where α = angular acceleration, τ = torque, ω = angular velocity, θ = joint angle, I = inertia, B = damping, K = stiffness.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inertia__kg_m2
|
float
|
Joint rotational inertia in kg⋅m². |
required |
damping__Nm_s_per_rad
|
float
|
Joint viscous damping coefficient in N⋅m⋅s/rad. Controls velocity-dependent resistance. |
required |
stiffness__Nm_per_rad
|
float
|
Joint elastic stiffness in N⋅m/rad. Set to 0 for passive joints, >0 for spring-loaded joints. |
0.0
|
initial_angle__deg
|
float
|
Initial joint angle in degrees. |
0.0
|
initial_velocity__deg_per_s
|
float
|
Initial angular velocity in degrees per second. |
0.0
|
Attributes:
| Name | Type | Description |
|---|---|---|
angle__rad |
float
|
Current joint angle in radians. |
velocity__rad_per_s |
float
|
Current angular velocity in rad/s. |
angle__deg |
float
|
Current joint angle in degrees (computed property). |
Notes
JointDynamics uses plain float parameters (not quantities.Quantity) for the
inertial/damping coefficients because no canonical Quantity__kg_m2,
Quantity__Nm_s_per_rad, or Quantity__deg_per_s type aliases exist in
myogen.utils.types. Values are interpreted as:
inertia__kg_m2— rotational inertia in kg·m²damping__Nm_s_per_rad— viscous damping in N·m·s/radinitial_angle__deg— starting joint angle in degreesinitial_velocity__deg_per_s— starting angular velocity in degrees/second
Source code in myogen/simulator/neuron/joint_dynamics.py
integrate ¶
Integrate joint dynamics for one time step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
torque__Nm
|
float
|
Applied muscle torque in N⋅m. |
required |
dt__s
|
float
|
Integration time step in seconds. |
required |
Returns:
| Type | Description |
|---|---|
tuple[float, float]
|
Updated (angle__deg, velocity__deg_per_s). |
Source code in myogen/simulator/neuron/joint_dynamics.py
reset ¶
get_state ¶
get_state() -> dict
Get current joint state.
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary containing current angle, velocity, and parameters. |
Source code in myogen/simulator/neuron/joint_dynamics.py
Geometry & biomechanics¶
MuscleGeometry
dataclass
¶
MuscleGeometry(origin_coords: tuple[float, float], insertion_coords: tuple[float, float], optimal_length__cm: float, max_length_change__cm: float)
Geometric parameters for a muscle crossing a joint.
JointGeometry
dataclass
¶
JointGeometry(center_coords: tuple[float, float], radius__cm: float, range_of_motion__degrees: tuple[float, float])
Geometric parameters for a joint.
JointBiomechanics ¶
JointBiomechanics(joint_type: Literal['hinge', 'ball_socket'], joint_geometry: JointGeometry, muscle_geometries: list[MuscleGeometry], moment_arm_data__cm: Optional[MOMENT_ARM__MATRIX] = None, use_simplified_model: bool = True)
Joint biomechanics with muscle moment arms and length calculations.
This class computes the relationship between joint angles and muscle lengths, moment arms, and resulting joint torques. It supports both simple geometric models and more complex biomechanical relationships.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
joint_type
|
(hinge, ball_socket)
|
Type of joint for biomechanical calculations. "hinge" = single degree of freedom (e.g., elbow, knee) "ball_socket" = multi-degree of freedom (e.g., shoulder, hip) |
"hinge"
|
joint_geometry
|
JointGeometry
|
Geometric parameters of the joint. |
required |
muscle_geometries
|
list[MuscleGeometry]
|
List of muscle geometry parameters for muscles crossing this joint. |
required |
moment_arm_data__cm
|
MOMENT_ARM__MATRIX
|
Pre-computed moment arm data as function of joint angle. If None, computed from geometry. Shape: (n_angles, n_muscles). |
None
|
use_simplified_model
|
bool
|
Whether to use simplified geometric model or detailed biomechanics. |
True
|
Attributes:
| Name | Type | Description |
|---|---|---|
n_muscles |
int
|
Number of muscles crossing this joint. |
joint_angles__deg |
ndarray
|
Array of joint angles for moment arm calculations. |
moment_arms__cm |
ndarray
|
Moment arms for each muscle at each joint angle. |
Source code in myogen/simulator/core/force/biomechanics.py
compute_muscle_length ¶
Compute muscle length from joint angle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
joint_angle__deg
|
float
|
Joint angle in degrees. |
required |
muscle_index
|
int
|
Index of the muscle (0 to n_muscles-1). |
required |
Returns:
| Type | Description |
|---|---|
float
|
Muscle length in cm. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If muscle_index is out of range. |
Source code in myogen/simulator/core/force/biomechanics.py
get_moment_arm ¶
Get moment arm for a muscle at a specific joint angle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
joint_angle__deg
|
float
|
Joint angle in degrees. |
required |
muscle_index
|
int
|
Index of the muscle. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Moment arm in cm. |
Source code in myogen/simulator/core/force/biomechanics.py
compute_joint_torque ¶
Compute net joint torque from muscle forces.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
muscle_forces__N
|
float or ndarray
|
Forces from each muscle in Newtons. If float, assumes single muscle. If array, must have length equal to n_muscles. |
required |
joint_angle__deg
|
float
|
Current joint angle in degrees. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Net joint torque in N⋅cm. |
Notes
Positive torque indicates rotation in the positive joint angle direction.
Source code in myogen/simulator/core/force/biomechanics.py
get_muscle_length_trajectory ¶
get_muscle_length_trajectory(joint_angle_trajectory__degrees: JOINT_ANGLE__ARRAY, muscle_index: int) -> ndarray
Compute muscle length trajectory from joint angle trajectory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
joint_angle_trajectory__degrees
|
JOINT_ANGLE__ARRAY
|
Array of joint angles over time. |
required |
muscle_index
|
int
|
Index of the muscle. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Muscle length trajectory in cm. |
Source code in myogen/simulator/core/force/biomechanics.py
get_biomechanical_summary ¶
get_biomechanical_summary() -> dict
Get summary of biomechanical parameters.
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary containing key biomechanical parameters. |
Source code in myogen/simulator/core/force/biomechanics.py
Grid / Neo utilities¶
create_grid_signal ¶
create_grid_signal(signal: ndarray, grid_shape: tuple[int, int], sampling_rate: Quantity, units: Quantity | str = mV, t_start: Quantity = 0 * s, electrode_positions: list[tuple[float, float]] | None = None, ied: float | None = None, **kwargs) -> AnalogSignal
Create an AnalogSignal with grid metadata annotations for electrode arrays.
This function creates a standard Neo AnalogSignal with grid structure stored in annotations, making it NWB-compatible while preserving spatial information.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
ndarray
|
Signal data with shape (time, rows, cols) or (time, n_electrodes). If 3D, will be flattened to (time, n_electrodes) for storage. |
required |
grid_shape
|
tuple[int, int]
|
Shape of the electrode grid as (rows, cols). |
required |
sampling_rate
|
Quantity
|
Sampling rate of the signal. |
required |
units
|
Quantity or str
|
Units of the signal. |
pq.mV
|
t_start
|
Quantity
|
Start time of the signal. |
0*pq.s
|
electrode_positions
|
list[tuple[float, float]]
|
Physical (x, y) positions of each electrode in mm. If None, positions are computed from grid_shape and ied. |
None
|
ied
|
float
|
Inter-electrode distance in mm. Used to compute electrode_positions if not provided directly. |
None
|
**kwargs
|
Additional arguments passed to AnalogSignal constructor or stored as annotations. |
{}
|
Returns:
| Type | Description |
|---|---|
AnalogSignal
|
Neo AnalogSignal with grid metadata in annotations: - 'grid_shape': (rows, cols) tuple - 'electrode_positions': list of (x, y) tuples in mm - 'ied': inter-electrode distance in mm (if provided) |
Examples:
>>> import numpy as np
>>> import quantities as pq
>>> from myogen.utils.neo import create_grid_signal, signal_to_grid
>>>
>>> # Create grid data (time, rows, cols)
>>> data = np.random.rand(1000, 8, 8)
>>> signal = create_grid_signal(
... data,
... grid_shape=(8, 8),
... sampling_rate=2048 * pq.Hz,
... ied=8.0, # 8mm inter-electrode distance
... )
>>>
>>> # Access as grid
>>> grid = signal_to_grid(signal) # shape: (1000, 8, 8)
>>>
>>> # Access single electrode
>>> row, col = 2, 3
>>> electrode_idx = row * 8 + col
>>> single = signal[:, electrode_idx]
Source code in myogen/utils/neo.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
signal_to_grid ¶
Convert a grid-annotated AnalogSignal back to 3D grid format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
AnalogSignal
|
AnalogSignal with 'grid_shape' annotation. |
required |
time_slice
|
slice
|
Time slice to extract. If None, returns all time points. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Data in grid format with shape (time, rows, cols). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the signal doesn't have grid_shape annotation. |
Examples:
>>> grid = signal_to_grid(signal)
>>> grid.shape # (time, rows, cols)
(1000, 8, 8)
>>>
>>> # Get single time point
>>> frame = signal_to_grid(signal, time_slice=slice(100, 101))
>>> frame.shape
(1, 8, 8)
Source code in myogen/utils/neo.py
get_electrode ¶
Extract a single electrode's signal from a grid-annotated AnalogSignal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
AnalogSignal
|
AnalogSignal with 'grid_shape' annotation. |
required |
row
|
int
|
Row index of the electrode. |
required |
col
|
int
|
Column index of the electrode. |
required |
Returns:
| Type | Description |
|---|---|
AnalogSignal
|
Single-channel AnalogSignal for the specified electrode. |
Examples:
Source code in myogen/utils/neo.py
get_row ¶
get_row(signal: AnalogSignal, row: int) -> AnalogSignal
Extract all electrodes from a specific row.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
AnalogSignal
|
AnalogSignal with 'grid_shape' annotation. |
required |
row
|
int
|
Row index to extract. |
required |
Returns:
| Type | Description |
|---|---|
AnalogSignal
|
Multi-channel AnalogSignal for all electrodes in the row. |
Examples:
Source code in myogen/utils/neo.py
get_column ¶
get_column(signal: AnalogSignal, col: int) -> AnalogSignal
Extract all electrodes from a specific column.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
AnalogSignal
|
AnalogSignal with 'grid_shape' annotation. |
required |
col
|
int
|
Column index to extract. |
required |
Returns:
| Type | Description |
|---|---|
AnalogSignal
|
Multi-channel AnalogSignal for all electrodes in the column. |
Examples:
Source code in myogen/utils/neo.py
The deprecated GridAnalogSignal compatibility class is intentionally excluded.