Note
Go to the end to download the full example code.
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 unitsradius
: Radius of the muscle in mmfiber_density
: Fiber density per mm²max_innervation_area_to_total_muscle_area__ratio
: Maximum innervation area to total muscle area ratiogrid_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()

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()

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