Muscle Model#

The spike trains alone are not enough to create EMG signals.

To create EMG signals, we need to create a muscle model that will distribute the motor units and fibers within the muscle volume.

Import Libraries#

from pathlib import Path

import numpy as np
import matplotlib.pyplot as plt
import joblib

from myogen import simulator
from myogen.utils.plotting.muscle import plot_mf_centers, plot_innervation_areas_2d

Define Parameters#

The muscle model is created using the Muscle object.

The Muscle object takes the following parameters:

  • recruitment_thresholds: Recruitment thresholds of the motor units

  • radius: Radius of the muscle in mm

  • fiber_density: Fiber density per mm²

  • max_innervation_area_to_total_muscle_area__ratio: Maximum innervation area to total muscle area ratio

  • grid_resolution: Spatial resolution for muscle discretization

Since the recruitment thresholds are already generated, we can load them from the previous example using joblib.

# Load recruitment thresholds
save_path = Path("./results")

recruitment_thresholds = joblib.load(save_path / "thresholds.pkl")

# Define muscle parameters for an FDI muscle
muscle_radius = 4.9  # Muscle radius in mm
mean_fiber_length = 32  # Mean fiber length in mm
fiber_length_variation = 3  # Fiber length variation (±) in mm
fiber_density = 50  # Fiber density per mm²

# Define simulation parameters
max_innervation_ratio = 1 / 4  # Maximum motor unit territory size
grid_resolution = 256  # Spatial resolution for muscle discretization

Create Muscle Model#

Note

Depending on the parameters, the simulation can take a few minutes to run.

To avoid running the simulation every time, we can save the muscle model using joblib.

# Create muscle model
muscle = simulator.Muscle(
    recruitment_thresholds=recruitment_thresholds[::4],  # For faster simulation
    radius__mm=muscle_radius,
    fiber_density__fibers_per_mm2=fiber_density,
    max_innervation_area_to_total_muscle_area__ratio=max_innervation_ratio,
    grid_resolution=grid_resolution,
    autorun=True,
)

# Save muscle model for future use
joblib.dump(muscle, save_path / "muscle_model.pkl")

# Display muscle statistics
total_fibers = sum(muscle.resulting_number_of_innervated_fibers)

print(f"\nMuscle model statistics:")
print(f"  - Total muscle fibers: {total_fibers}")
print(f"  - Mean fibers per MU: {total_fibers / len(recruitment_thresholds):.1f}")
print(f"  - Muscle cross-sectional area: {np.pi * muscle_radius**2:.1f} mm²")
Calculating out-of-circle coefficients:   0%|          | 0/25 [00:00<?, ?it/s]
Calculating out-of-circle coefficients:   4%|▍         | 1/25 [00:03<01:28,  3.67s/it]
Calculating out-of-circle coefficients:   8%|▊         | 2/25 [00:07<01:23,  3.62s/it]
Calculating out-of-circle coefficients:  12%|█▏        | 3/25 [00:09<01:01,  2.81s/it]
Calculating out-of-circle coefficients:  16%|█▌        | 4/25 [00:12<01:02,  2.97s/it]
Calculating out-of-circle coefficients:  20%|██        | 5/25 [00:13<00:49,  2.48s/it]
Calculating out-of-circle coefficients:  24%|██▍       | 6/25 [00:15<00:40,  2.15s/it]
Calculating out-of-circle coefficients:  28%|██▊       | 7/25 [00:17<00:36,  2.02s/it]
Calculating out-of-circle coefficients:  32%|███▏      | 8/25 [00:18<00:32,  1.92s/it]
Calculating out-of-circle coefficients:  36%|███▌      | 9/25 [00:20<00:26,  1.68s/it]
Calculating out-of-circle coefficients:  40%|████      | 10/25 [00:22<00:26,  1.79s/it]
Calculating out-of-circle coefficients:  44%|████▍     | 11/25 [00:24<00:25,  1.86s/it]
Calculating out-of-circle coefficients:  48%|████▊     | 12/25 [00:25<00:21,  1.63s/it]
Calculating out-of-circle coefficients:  52%|█████▏    | 13/25 [00:27<00:20,  1.69s/it]
Calculating out-of-circle coefficients:  56%|█████▌    | 14/25 [00:28<00:17,  1.56s/it]
Calculating out-of-circle coefficients:  60%|██████    | 15/25 [00:29<00:13,  1.32s/it]
Calculating out-of-circle coefficients:  64%|██████▍   | 16/25 [00:31<00:13,  1.51s/it]
Calculating out-of-circle coefficients:  68%|██████▊   | 17/25 [00:31<00:10,  1.34s/it]
Calculating out-of-circle coefficients:  72%|███████▏  | 18/25 [00:33<00:10,  1.44s/it]
Calculating out-of-circle coefficients:  76%|███████▌  | 19/25 [00:34<00:07,  1.29s/it]
Calculating out-of-circle coefficients:  80%|████████  | 20/25 [00:36<00:06,  1.38s/it]
Calculating out-of-circle coefficients:  84%|████████▍ | 21/25 [00:37<00:05,  1.26s/it]
Calculating out-of-circle coefficients:  88%|████████▊ | 22/25 [00:37<00:03,  1.11s/it]
Calculating out-of-circle coefficients:  92%|█████████▏| 23/25 [00:39<00:02,  1.20s/it]
Calculating out-of-circle coefficients:  96%|█████████▌| 24/25 [00:40<00:01,  1.07s/it]
Calculating out-of-circle coefficients: 100%|██████████| 25/25 [00:41<00:00,  1.09s/it]
Calculating out-of-circle coefficients: 100%|██████████| 25/25 [00:41<00:00,  1.65s/it]

Assigning muscle fibers to motor neurons:   0%|          | 0/3771 [00:00<?, ?it/s]
Assigning muscle fibers to motor neurons:   1%|          | 33/3771 [00:00<00:11, 324.21it/s]
Assigning muscle fibers to motor neurons:   2%|▏         | 66/3771 [00:00<00:11, 324.93it/s]
Assigning muscle fibers to motor neurons:   3%|▎         | 99/3771 [00:00<00:11, 325.64it/s]
Assigning muscle fibers to motor neurons:   4%|▎         | 132/3771 [00:00<00:11, 326.57it/s]
Assigning muscle fibers to motor neurons:   4%|▍         | 165/3771 [00:00<00:11, 326.44it/s]
Assigning muscle fibers to motor neurons:   5%|▌         | 198/3771 [00:00<00:10, 326.73it/s]
Assigning muscle fibers to motor neurons:   6%|▌         | 231/3771 [00:00<00:10, 326.65it/s]
Assigning muscle fibers to motor neurons:   7%|▋         | 264/3771 [00:00<00:10, 326.96it/s]
Assigning muscle fibers to motor neurons:   8%|▊         | 297/3771 [00:00<00:10, 326.74it/s]
Assigning muscle fibers to motor neurons:   9%|▉         | 330/3771 [00:01<00:10, 326.91it/s]
Assigning muscle fibers to motor neurons:  10%|▉         | 363/3771 [00:01<00:10, 327.51it/s]
Assigning muscle fibers to motor neurons:  11%|█         | 396/3771 [00:01<00:10, 327.94it/s]
Assigning muscle fibers to motor neurons:  11%|█▏        | 430/3771 [00:01<00:10, 328.56it/s]
Assigning muscle fibers to motor neurons:  12%|█▏        | 463/3771 [00:01<00:10, 327.85it/s]
Assigning muscle fibers to motor neurons:  13%|█▎        | 496/3771 [00:01<00:09, 328.38it/s]
Assigning muscle fibers to motor neurons:  14%|█▍        | 529/3771 [00:01<00:09, 328.43it/s]
Assigning muscle fibers to motor neurons:  15%|█▍        | 562/3771 [00:01<00:09, 327.66it/s]
Assigning muscle fibers to motor neurons:  16%|█▌        | 595/3771 [00:01<00:09, 328.07it/s]
Assigning muscle fibers to motor neurons:  17%|█▋        | 628/3771 [00:01<00:09, 328.60it/s]
Assigning muscle fibers to motor neurons:  18%|█▊        | 662/3771 [00:02<00:09, 329.09it/s]
Assigning muscle fibers to motor neurons:  18%|█▊        | 696/3771 [00:02<00:09, 330.01it/s]
Assigning muscle fibers to motor neurons:  19%|█▉        | 730/3771 [00:02<00:09, 330.30it/s]
Assigning muscle fibers to motor neurons:  20%|██        | 764/3771 [00:02<00:09, 329.52it/s]
Assigning muscle fibers to motor neurons:  21%|██        | 798/3771 [00:02<00:09, 330.15it/s]
Assigning muscle fibers to motor neurons:  22%|██▏       | 832/3771 [00:02<00:08, 330.28it/s]
Assigning muscle fibers to motor neurons:  23%|██▎       | 866/3771 [00:02<00:08, 331.31it/s]
Assigning muscle fibers to motor neurons:  24%|██▍       | 900/3771 [00:02<00:08, 332.18it/s]
Assigning muscle fibers to motor neurons:  25%|██▍       | 934/3771 [00:02<00:08, 332.27it/s]
Assigning muscle fibers to motor neurons:  26%|██▌       | 968/3771 [00:02<00:08, 332.12it/s]
Assigning muscle fibers to motor neurons:  27%|██▋       | 1002/3771 [00:03<00:08, 332.85it/s]
Assigning muscle fibers to motor neurons:  27%|██▋       | 1036/3771 [00:03<00:08, 333.64it/s]
Assigning muscle fibers to motor neurons:  28%|██▊       | 1070/3771 [00:03<00:08, 333.44it/s]
Assigning muscle fibers to motor neurons:  29%|██▉       | 1104/3771 [00:03<00:07, 333.99it/s]
Assigning muscle fibers to motor neurons:  30%|███       | 1138/3771 [00:03<00:07, 333.07it/s]
Assigning muscle fibers to motor neurons:  31%|███       | 1172/3771 [00:03<00:07, 334.28it/s]
Assigning muscle fibers to motor neurons:  32%|███▏      | 1206/3771 [00:03<00:07, 335.14it/s]
Assigning muscle fibers to motor neurons:  33%|███▎      | 1240/3771 [00:03<00:07, 334.41it/s]
Assigning muscle fibers to motor neurons:  34%|███▍      | 1274/3771 [00:03<00:07, 334.76it/s]
Assigning muscle fibers to motor neurons:  35%|███▍      | 1308/3771 [00:03<00:07, 335.14it/s]
Assigning muscle fibers to motor neurons:  36%|███▌      | 1342/3771 [00:04<00:07, 335.93it/s]
Assigning muscle fibers to motor neurons:  36%|███▋      | 1376/3771 [00:04<00:07, 335.70it/s]
Assigning muscle fibers to motor neurons:  37%|███▋      | 1410/3771 [00:04<00:07, 335.07it/s]
Assigning muscle fibers to motor neurons:  38%|███▊      | 1444/3771 [00:04<00:06, 335.42it/s]
Assigning muscle fibers to motor neurons:  39%|███▉      | 1478/3771 [00:04<00:06, 336.14it/s]
Assigning muscle fibers to motor neurons:  40%|████      | 1512/3771 [00:04<00:06, 336.61it/s]
Assigning muscle fibers to motor neurons:  41%|████      | 1547/3771 [00:04<00:06, 337.83it/s]
Assigning muscle fibers to motor neurons:  42%|████▏     | 1581/3771 [00:04<00:06, 338.38it/s]
Assigning muscle fibers to motor neurons:  43%|████▎     | 1615/3771 [00:04<00:06, 338.60it/s]
Assigning muscle fibers to motor neurons:  44%|████▍     | 1650/3771 [00:04<00:06, 339.15it/s]
Assigning muscle fibers to motor neurons:  45%|████▍     | 1684/3771 [00:05<00:06, 338.80it/s]
Assigning muscle fibers to motor neurons:  46%|████▌     | 1718/3771 [00:05<00:06, 338.73it/s]
Assigning muscle fibers to motor neurons:  46%|████▋     | 1752/3771 [00:05<00:05, 338.57it/s]
Assigning muscle fibers to motor neurons:  47%|████▋     | 1786/3771 [00:05<00:05, 337.96it/s]
Assigning muscle fibers to motor neurons:  48%|████▊     | 1821/3771 [00:05<00:05, 338.85it/s]
Assigning muscle fibers to motor neurons:  49%|████▉     | 1855/3771 [00:05<00:05, 339.11it/s]
Assigning muscle fibers to motor neurons:  50%|█████     | 1889/3771 [00:05<00:05, 339.20it/s]
Assigning muscle fibers to motor neurons:  51%|█████     | 1923/3771 [00:05<00:05, 339.35it/s]
Assigning muscle fibers to motor neurons:  52%|█████▏    | 1958/3771 [00:05<00:05, 339.92it/s]
Assigning muscle fibers to motor neurons:  53%|█████▎    | 1993/3771 [00:05<00:05, 340.77it/s]
Assigning muscle fibers to motor neurons:  54%|█████▍    | 2028/3771 [00:06<00:05, 342.01it/s]
Assigning muscle fibers to motor neurons:  55%|█████▍    | 2063/3771 [00:06<00:05, 341.56it/s]
Assigning muscle fibers to motor neurons:  56%|█████▌    | 2098/3771 [00:06<00:04, 341.64it/s]
Assigning muscle fibers to motor neurons:  57%|█████▋    | 2133/3771 [00:06<00:04, 342.04it/s]
Assigning muscle fibers to motor neurons:  57%|█████▋    | 2168/3771 [00:06<00:04, 341.84it/s]
Assigning muscle fibers to motor neurons:  58%|█████▊    | 2203/3771 [00:06<00:04, 342.48it/s]
Assigning muscle fibers to motor neurons:  59%|█████▉    | 2238/3771 [00:06<00:04, 342.68it/s]
Assigning muscle fibers to motor neurons:  60%|██████    | 2273/3771 [00:06<00:04, 343.04it/s]
Assigning muscle fibers to motor neurons:  61%|██████    | 2308/3771 [00:06<00:04, 343.81it/s]
Assigning muscle fibers to motor neurons:  62%|██████▏   | 2343/3771 [00:07<00:04, 343.60it/s]
Assigning muscle fibers to motor neurons:  63%|██████▎   | 2378/3771 [00:07<00:04, 345.02it/s]
Assigning muscle fibers to motor neurons:  64%|██████▍   | 2413/3771 [00:07<00:03, 345.38it/s]
Assigning muscle fibers to motor neurons:  65%|██████▍   | 2448/3771 [00:07<00:03, 345.63it/s]
Assigning muscle fibers to motor neurons:  66%|██████▌   | 2483/3771 [00:07<00:03, 345.96it/s]
Assigning muscle fibers to motor neurons:  67%|██████▋   | 2518/3771 [00:07<00:03, 346.28it/s]
Assigning muscle fibers to motor neurons:  68%|██████▊   | 2553/3771 [00:07<00:03, 346.76it/s]
Assigning muscle fibers to motor neurons:  69%|██████▊   | 2588/3771 [00:07<00:03, 346.35it/s]
Assigning muscle fibers to motor neurons:  70%|██████▉   | 2623/3771 [00:07<00:03, 346.53it/s]
Assigning muscle fibers to motor neurons:  70%|███████   | 2658/3771 [00:07<00:03, 345.76it/s]
Assigning muscle fibers to motor neurons:  71%|███████▏  | 2693/3771 [00:08<00:03, 346.43it/s]
Assigning muscle fibers to motor neurons:  72%|███████▏  | 2728/3771 [00:08<00:03, 346.26it/s]
Assigning muscle fibers to motor neurons:  73%|███████▎  | 2763/3771 [00:08<00:02, 346.11it/s]
Assigning muscle fibers to motor neurons:  74%|███████▍  | 2798/3771 [00:08<00:02, 345.97it/s]
Assigning muscle fibers to motor neurons:  75%|███████▌  | 2833/3771 [00:08<00:02, 345.83it/s]
Assigning muscle fibers to motor neurons:  76%|███████▌  | 2868/3771 [00:08<00:02, 345.94it/s]
Assigning muscle fibers to motor neurons:  77%|███████▋  | 2903/3771 [00:08<00:02, 345.73it/s]
Assigning muscle fibers to motor neurons:  78%|███████▊  | 2938/3771 [00:08<00:02, 345.98it/s]
Assigning muscle fibers to motor neurons:  79%|███████▉  | 2973/3771 [00:08<00:02, 346.01it/s]
Assigning muscle fibers to motor neurons:  80%|███████▉  | 3008/3771 [00:08<00:02, 345.38it/s]
Assigning muscle fibers to motor neurons:  81%|████████  | 3043/3771 [00:09<00:02, 345.39it/s]
Assigning muscle fibers to motor neurons:  82%|████████▏ | 3078/3771 [00:09<00:02, 345.22it/s]
Assigning muscle fibers to motor neurons:  83%|████████▎ | 3113/3771 [00:09<00:01, 345.01it/s]
Assigning muscle fibers to motor neurons:  83%|████████▎ | 3148/3771 [00:09<00:01, 345.01it/s]
Assigning muscle fibers to motor neurons:  84%|████████▍ | 3183/3771 [00:09<00:01, 344.84it/s]
Assigning muscle fibers to motor neurons:  85%|████████▌ | 3218/3771 [00:09<00:01, 345.31it/s]
Assigning muscle fibers to motor neurons:  86%|████████▋ | 3253/3771 [00:09<00:01, 346.60it/s]
Assigning muscle fibers to motor neurons:  87%|████████▋ | 3288/3771 [00:09<00:01, 347.35it/s]
Assigning muscle fibers to motor neurons:  88%|████████▊ | 3324/3771 [00:09<00:01, 348.47it/s]
Assigning muscle fibers to motor neurons:  89%|████████▉ | 3359/3771 [00:09<00:01, 348.72it/s]
Assigning muscle fibers to motor neurons:  90%|█████████ | 3395/3771 [00:10<00:01, 349.96it/s]
Assigning muscle fibers to motor neurons:  91%|█████████ | 3430/3771 [00:10<00:00, 349.22it/s]
Assigning muscle fibers to motor neurons:  92%|█████████▏| 3466/3771 [00:10<00:00, 349.98it/s]
Assigning muscle fibers to motor neurons:  93%|█████████▎| 3502/3771 [00:10<00:00, 350.60it/s]
Assigning muscle fibers to motor neurons:  94%|█████████▍| 3538/3771 [00:10<00:00, 350.94it/s]
Assigning muscle fibers to motor neurons:  95%|█████████▍| 3574/3771 [00:10<00:00, 351.25it/s]
Assigning muscle fibers to motor neurons:  96%|█████████▌| 3610/3771 [00:10<00:00, 351.98it/s]
Assigning muscle fibers to motor neurons:  97%|█████████▋| 3646/3771 [00:10<00:00, 351.92it/s]
Assigning muscle fibers to motor neurons:  98%|█████████▊| 3682/3771 [00:10<00:00, 352.50it/s]
Assigning muscle fibers to motor neurons:  99%|█████████▊| 3718/3771 [00:10<00:00, 353.02it/s]
Assigning muscle fibers to motor neurons: 100%|█████████▉| 3754/3771 [00:11<00:00, 352.40it/s]
Assigning muscle fibers to motor neurons: 100%|██████████| 3771/3771 [00:11<00:00, 339.59it/s]
Assignment completed. 3771 muscle fibers assigned.

Muscle model statistics:
  - Total muscle fibers: 3771
  - Mean fibers per MU: 37.7
  - Muscle cross-sectional area: 75.4 mm²

Visualize Muscle Fiber Centers#

The fiber centers are the centers of the fibers that are innervated by the motor units.

Note

The fiber centers have been precalculated from a Voronoi tessellation of the muscle volume. Then depending on the fiber density, the fiber centers are distributed within the muscle volume.

plt.figure(figsize=(6, 6))

with plt.xkcd():
    plot_mf_centers(muscle, ax=plt.gca())
plt.title("Motor Unit Fiber Centers")
plt.xlabel("X Position (mm)")
plt.ylabel("Y Position (mm)")
plt.axis("equal")

plt.tight_layout()
plt.show()
Motor Unit Fiber Centers

Visualize Motor Unit Innervation Areas#

Display the spatial organization of motor units and their innervation areas.

Note

The innervation areas are the areas where the motor units are innervated. They are calculated using the recruitment thresholds and the fiber density.

plt.figure(figsize=(6, 6))

selected_indices = np.arange(25)[::-1]
with plt.xkcd():
    plot_innervation_areas_2d(muscle, indices_to_plot=selected_indices, ax=plt.gca())
plt.title("Motor Unit Innervation Areas")
plt.xlabel("X Position (mm)")
plt.ylabel("Y Position (mm)")
plt.axis("equal")

plt.tight_layout()
plt.show()
Motor Unit Innervation Areas

Total running time of the script: (0 minutes 53.249 seconds)

Gallery generated by Sphinx-Gallery