### Clone and Setup MyoGen Project Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/index.md Instructions to clone the MyoGen repository from GitHub, navigate into the project directory, synchronize dependencies, and run the setup script. ```bash git clone https://github.com/NsquaredLab/MyoGen.git cd MyoGen uv sync uv run poe setup_myogen ``` -------------------------------- ### Install MyoGen from Source Source: https://github.com/nsquaredlab/myogen/blob/main/README.md Steps to clone the MyoGen repository, navigate into the directory, synchronize dependencies, and set up the project using `uv` and `poe`. ```bash git clone https://github.com/NsquaredLab/MyoGen.git cd MyoGen uv sync uv run poe setup_myogen ``` -------------------------------- ### Install MyoGen using pip Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/index.md Provides an alternative method for installing the MyoGen package using pip, the standard Python package installer. This is an alternative to using uv. ```bash pip install myogen ``` -------------------------------- ### Install MyoGen and Compile NEURON Mechanisms Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/README.md This snippet outlines the installation process for MyoGen using uv for dependency management. It includes cloning the repository, synchronizing packages, activating a virtual environment, and compiling NEURON mechanisms, which are essential for the toolkit's functionality. ```bash # Clone and install git clone https://github.com/NsquaredLab/MyoGen.git cd MyoGen uv sync # Activate environment source .venv/bin/activate # Linux/macOS .venv\Scripts\activate # Windows # Compile NEURON mechanisms (required) uv run poe setup_myogen ``` -------------------------------- ### Verify MyoGen Installation with Python Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/index.md Verifies the MyoGen installation by running a simple Python command using uv. This command imports the 'simulator' module from 'myogen' and prints a success message if the import is successful. ```bash # Create a test script uv run python -c "from myogen import simulator; print('MyoGen installed successfully!')" ``` -------------------------------- ### Install uv Package Manager on Windows Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/index.md Installs the uv Python package manager on Windows using PowerShell. This is a prerequisite for managing project dependencies with uv. ```powershell powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" ``` -------------------------------- ### Optional GPU Acceleration Installation Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/README.md This bash command demonstrates how to install CuPy for GPU acceleration of convolutions within MyoGen. This optional step can significantly speed up computations, typically offering a 5-10x performance improvement for relevant operations. ```bash uv pip install cupy-cuda12x # 5-10× speedup ``` -------------------------------- ### Complete MyoGen Simulation Example (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst A comprehensive example demonstrating the typical data flow in MyoGen: loading spike trains and surface EMG data, extracting specific neuron spike times and EMG signals from a central electrode, and plotting both signals. ```python import joblib import numpy as np import matplotlib.pyplot as plt from myogen.utils.types import SPIKE_TRAIN__Block, SURFACE_EMG__Block # 1. Load data spike_trains = joblib.load("spike_trains.pkl") surface_emg = joblib.load("surface_emg.pkl") # 2. Extract spike times motor_pool = spike_trains.segments[0] neuron_5 = motor_pool.spiketrains[5] spike_times = neuron_5.magnitude # 3. Extract EMG from center electrode emg_signal = surface_emg.groups[0].segments[0].analogsignals[0] center_row = emg_signal.shape[1] // 2 center_col = emg_signal.shape[2] // 2 electrode_emg = emg_signal[:, center_row, center_col] # 4. Plot fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True) # Spike raster ax1.scatter(spike_times, [0]*len(spike_times), s=10, c='black') ax1.set_ylabel('Neuron 5') ax1.set_ylim(-0.5, 0.5) # EMG signal time = emg_signal.times.magnitude ax2.plot(time, electrode_emg.magnitude) ax2.set_xlabel('Time (s)') ax2.set_ylabel(f'EMG ({electrode_emg.units})') plt.tight_layout() plt.show() ``` -------------------------------- ### Extracting Time Windows from Spike Trains and Analog Signals (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst Provides code examples for extracting specific time windows from both spike train and analog signal objects. For analog signals, it demonstrates calculating start and end indices based on sampling rate. ```python # For spike trains windowed_train = spiketrain.time_slice(t_start, t_stop) # For analog signals start_idx = int(t_start * emg_signal.sampling_rate.magnitude) end_idx = int(t_stop * emg_signal.sampling_rate.magnitude) windowed_signal = emg_signal[start_idx:end_idx] ``` -------------------------------- ### Setup Spinal Network Simulation Components Source: https://context7.com/nsquaredlab/myogen/llms.txt Initializes components for simulating complete spinal reflex circuits. This includes setting up motor neurons, various afferent populations (Ia, II, Ib), interneurons, muscle spindles, Golgi tendon organs, and joint dynamics. It requires loading NMODL mechanisms and recruitment thresholds. ```python from myogen import load_nmodl_mechanisms from myogen.simulator.neuron import Network from myogen.simulator.neuron.populations import ( AlphaMN__Pool, DescendingDrive__Pool, AffIa__Pool, AffII__Pool, AffIb__Pool, GII__Pool, GIb__Pool, ) from myogen.simulator.neuron.muscle import HillModel from myogen.simulator.neuron.proprioception import SpindleModel, GolgiTendonOrganModel from myogen.simulator.neuron.joint_dynamics import JointDynamics from myogen.simulator.neuron.simulation_runner import SimulationRunner import quantities as pq import numpy as np import joblib load_nmodl_mechanisms() thresholds = joblib.load("thresholds.pkl") # Simulation parameters dt = 0.005 * pq.ms tstop = 5000 # ms ``` -------------------------------- ### Install uv Package Manager on Linux/macOS Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/index.md Installs the uv Python package manager on Linux and macOS using a curl command. uv is a fast Python package manager used for project dependency management. ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` -------------------------------- ### MyoGen Package Structure Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/index.md Representation of the MyoGen package directory structure, illustrating the organization of source code, simulator components, utilities, examples, and documentation. ```text MyoGen/ ├── myogen/ # Main package source code │ ├── simulator/ # Core simulation functionality │ │ ├── core/ # Core simulation components │ │ │ ├── emg/ # EMG signal generation │ │ │ ├── muscle/ # Muscle modeling │ │ │ └── spike_train/ # Motor neuron simulation │ │ └── ... │ ├── utils/ # Utility functions and tools │ │ ├── plotting/ # Visualization utilities │ │ ├── currents.py # Current generation │ │ └── nmodl.py # NMODL file handling │ └── ... ├── examples/ # Example scripts and tutorials ├── docs/ # Documentation source ├── pyproject.toml # Project metadata and dependencies └── uv.lock # Pinned versions of dependencies ``` -------------------------------- ### Correct Unit Scaling: Rescale Signal (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst This code example shows how to address issues with incorrect units (e.g., mV vs. µV) in electrophysiological data. It involves printing the current units and then using the .rescale() method from the quantities library to convert the signal to a desired unit. ```python print(signal.units) # e.g., mV or µV signal.rescale(pq.mV) # Convert to desired unit ``` -------------------------------- ### Access Intramuscular EMG Segments and Signals (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst Illustrates how to access motor pool segments and analog signals from an intramuscular EMG block. It includes methods to get the magnitude of the EMG signal and extract data for a specific electrode. ```python # Access intramuscular EMG motor_pool = im_emg__Block.segments[pool_idx] emg_signal = motor_pool.analogsignals[0] # Extract data emg_array = emg_signal.magnitude # Shape: (time, electrodes) electrode_emg = emg_signal[:, electrode_idx] ``` -------------------------------- ### Accessing Metadata from Neo Signals Source: https://github.com/nsquaredlab/myogen/blob/main/docs/neo_blocks.md Provides examples of how to access common metadata attributes associated with Neo AnalogSignal and SpikeTrain objects, such as sampling rate, units, and shape. ```python # Metadata signal.sampling_rate # e.g., 2048 Hz signal.t_start / t_stop # Start/stop time signal.units # e.g., mV, µV signal.shape # Array dimensions ``` -------------------------------- ### Iterating Through All Spike Trains Source: https://github.com/nsquaredlab/myogen/blob/main/docs/neo_blocks.md Provides an example of how to iterate through all segments and spike trains within a MyoGen Block object. ```python # All spike trains for segment in block.segments: for st in segment.spiketrains: print(f"{st.name}: {len(st)} spikes") ``` -------------------------------- ### Calculate Mean Firing Rate from SPIKE_TRAIN__Block (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst Provides an example of calculating the mean firing rate for each spiketrain within a motor pool using the elephant library. It iterates through spiketrains, calculates their rates if they contain spikes, and then computes the average firing rate across the pool. ```python import elephant.statistics import numpy as np motor_pool = spike_train__Block.segments[0] firing_rates = [] for spiketrain in motor_pool.spiketrains: if len(spiketrain) > 0: rate = elephant.statistics.mean_firing_rate(spiketrain) firing_rates.append(rate.magnitude) print(f"Mean firing rate: {np.mean(firing_rates):.2f} Hz") ``` -------------------------------- ### Create and Initialize MyoGen Project Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/index.md Demonstrates the steps to create a new project directory, navigate into it, initialize a Python project using uv, and add the 'myogen' package to the project's dependencies. ```bash # Create a new folder for your project mkdir my_emg_project cd my_emg_project # Initialize a Python project uv init # Add MyoGen to your project uv add myogen ``` -------------------------------- ### Serve Documentation Locally (Bash) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/README.md Scripts to serve the built documentation locally using Python's http.server. This is recommended for features that rely on AJAX, such as hover tooltips. ```bash cd docs ./serve_docs.sh ``` ```bash cd docs/build/html python -m http.server 8000 ``` -------------------------------- ### Build Documentation (Bash) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/README.md Command to build the Sphinx documentation into HTML format. The output will be located in the 'build/html/' directory. ```bash # From the docs directory make html ``` -------------------------------- ### Initialize and Simulate Surface EMG with Myogen Source: https://context7.com/nsquaredlab/myogen/llms.txt Demonstrates initializing a SurfaceEMG simulator, computing MUAPs, converting to a grid format, generating full EMG from spike trains, adding noise, and extracting single electrode traces. It uses libraries like quantities, joblib, and numpy. ```python from myogen import simulator import quantities as pq import joblib import numpy as np # Assume 'muscle' and 'electrode_array' are pre-defined objects # Example placeholders: class MockMuscle: pass class MockElectrodeArray: pass muscle = MockMuscle() electrode_array = MockElectrodeArray() # Initialize surface EMG simulator surface_emg = simulator.SurfaceEMG( muscle_model=muscle, electrode_arrays=[electrode_array], sampling_frequency__Hz=2048.0 * pq.Hz, MUs_to_simulate=[0, 1, 2, 3, 4], # Simulate first 5 MUs (or None for all) ) # Compute MUAPs (parallel processing with n_jobs) # Mocking the output of simulate_muaps for demonstration class MockAnalogSignal: def __init__(self, shape): self.shape = shape self.magnitude = np.zeros(shape) class MockSegment: def __init__(self): self.analogsignals = [MockAnalogSignal((100, 3, 3))] class MockGroup: def __init__(self): self.segments = [MockSegment()] class MockBlock: def __init__(self): self.groups = [MockGroup()] # Mock the function to return a mock block def mock_simulate_muaps(*args, **kwargs): return MockBlock() surface_emg.simulate_muaps = mock_simulate_muaps muaps = surface_emg.simulate_muaps(n_jobs=-2) # -2 = all CPUs except one # Access MUAP data (Neo Block format) muap_signal = muaps.groups[0].segments[0].analogsignals[0] # Mock signal_to_grid function def mock_signal_to_grid(signal): # Simulate conversion to (time, rows, cols) return np.random.rand(signal.shape[0], 3, 3) signal_to_grid = mock_signal_to_grid muap_3d = signal_to_grid(muap_signal) # Convert to (time, rows, cols) print(f"MUAP shape: {muap_3d.shape}") print(f"Peak amplitude: {np.max(np.abs(muap_3d)):.4f} mV") # Generate full EMG from spike trains # Mocking joblib.load for demonstration spike_train_block = joblib.load("spike_trains.pkl") # From spike simulation # Mock the simulate_surface_emg function def mock_simulate_surface_emg(*args, **kwargs): return MockBlock() # Assuming it returns a Neo Block similar to muaps surface_emg.simulate_surface_emg = mock_simulate_surface_emg emg_signals = surface_emg.simulate_surface_emg(spike_train__Block=spike_train_block) # Add realistic noise # Mock the add_noise function def mock_add_noise(*args, **kwargs): return MockBlock() # Assuming it returns a Neo Block with noise added surface_emg.add_noise = mock_add_noise noisy_emg = surface_emg.add_noise(snr__dB=20.0) # 20 dB SNR # Extract single electrode trace emg_grid = signal_to_grid(noisy_emg.groups[0].segments[0].analogsignals[0]) electrode_trace = emg_grid[:, 2, 2] # Center electrode ``` -------------------------------- ### Converting Signal Units (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst Demonstrates how to convert signal units using the 'quantities' library. It shows checking the current units and then rescaling the signal to different units, such as microvolts (uV). ```python import quantities as pq # Check current units print(signal.units) # e.g., mV # Convert to different units signal_uV = signal.rescale(pq.uV) ``` -------------------------------- ### Generate Motor Unit Action Potentials (MUAPs) in Python Source: https://github.com/nsquaredlab/myogen/blob/main/README.md Python code demonstrating how to generate recruitment thresholds, create a muscle model, set up a surface electrode array, and simulate MUAPs using the MyoGen simulator. It requires the `myogen` and `quantities` libraries. ```python from myogen import simulator import quantities as pq # 1. Generate recruitment thresholds (100 motor units) thresholds, _ = simulator.RecruitmentThresholds( N=100, recruitment_range__ratio=50, mode="fuglevand" ) # 2. Create muscle model with fiber distribution muscle = simulator.Muscle( recruitment_thresholds=thresholds, radius_bone__mm=1.0 * pq.mm, fiber_density__fibers_per_mm2=400 * pq.mm**-2, fat_thickness__mm=10 * pq.mm, autorun=True ) # 3. Set up surface electrode array electrode_array = simulator.SurfaceElectrodeArray( num_rows=5, num_cols=5, inter_electrode_distances__mm=5 * pq.mm, electrode_radius__mm=5 * pq.mm, bending_radius__mm=muscle.radius__mm + muscle.skin_thickness__mm + muscle.fat_thickness__mm, ) # 4. Create surface EMG simulator surface_emg = simulator.SurfaceEMG( muscle_model=muscle, electrode_arrays=[electrode_array], sampling_frequency__Hz=2048.0, MUs_to_simulate=[0, 1, 2, 3, 4] # First 5 motor units ) # 5. Simulate MUAPs (parallel processing) muaps = surface_emg.simulate_muaps(n_jobs=-2) ``` -------------------------------- ### Load and Access MyoGen Simulation Data (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst Demonstrates how to load simulation data from .pkl files and access specific data points for spike trains and surface EMG signals. It shows how to extract numerical data and select data from specific electrodes or time points. ```python import joblib # Load spike trains spike_trains = joblib.load("spike_trains.pkl") spiketrain = spike_trains.segments[0].spiketrains[0] spike_times = spiketrain.magnitude # NumPy array # Load surface EMG surface_emg = joblib.load("surface_emg.pkl") emg_signal = surface_emg.groups[0].segments[0].analogsignals[0] electrode_data = emg_signal[:, row, col] # Time series at electrode # Load intramuscular EMG im_emg = joblib.load("intramuscular_emg.pkl") emg_signal = im_emg.segments[0].analogsignals[0] electrode_data = emg_signal[:, electrode_idx] # Time series ``` -------------------------------- ### Inject Current and Simulate Motor Pool Spike Trains Source: https://context7.com/nsquaredlab/myogen/llms.txt Injects a specified current into motor neuron populations and simulates their spike trains. This function handles the underlying NEURON setup and returns spike trains in the Neo Block format. It requires the motor pool definition and spike detection thresholds. ```python import quantities as pq import joblib from myogen.utils.simulation import inject_currents_and_simulate_spike_trains # Assuming 'motor_pool' and 'input_current' are defined elsewhere # motor_pool = ... # input_current = ... spike_trains = inject_currents_and_simulate_spike_trains( populations=[motor_pool], input_current__AnalogSignal=input_current, spike_detection_thresholds__mV=50 * pq.mV, ) # Access spike times (Neo Block format) for i, st in enumerate(spike_trains.segments[0].spiketrains[:5]): if len(st) > 0: print(f"MU {i}: {len(st)} spikes, first at {st[0]:.3f}") # Save for EMG simulation joblib.dump(spike_trains, "spike_trains.pkl") ``` -------------------------------- ### Simulate Spike Trains with Descending Drive Source: https://context7.com/nsquaredlab/myogen/llms.txt Simulates more realistic spike trains using descending drive populations that model cortical input. It sets up a network with motor neurons and descending drive pools, connects them synaptically, and prepares for simulation by defining an input drive pattern. This requires NEURON setup and synaptic connection parameters. ```python from myogen.simulator.neuron import Network from myogen.simulator.neuron.populations import AlphaMN__Pool, DescendingDrive__Pool from myogen.utils.nmodl import load_nmodl_mechanisms from neo import AnalogSignal import quantities as pq import numpy as np from neuron import h import joblib load_nmodl_mechanisms() # Load recruitment thresholds thresholds = joblib.load("thresholds.pkl") # Create populations timestep = 0.1 * pq.ms motor_pool = AlphaMN__Pool(recruitment_thresholds__array=thresholds) dd_pool = DescendingDrive__Pool(n=100, poisson_batch_size=5, timestep__ms=timestep) # Create neural network with synaptic connections network = Network({"DD": dd_pool, "aMN": motor_pool}) network.connect(source="DD", target="aMN", probability=0.5, weight__uS=0.15 * pq.uS) network.connect_from_external(source="cortical_input", target="DD", weight__uS=1.0 * pq.uS) # Create trapezoidal drive pattern (firing rate in pps) simulation_time = 10000 # ms time = np.arange(0, simulation_time, timestep.magnitude) drive = np.zeros_like(time) drive[(time >= 1000) & (time < 8000)] = np.linspace(0, 60, sum((time >= 1000) & (time < 8000))) drive_signal = AnalogSignal(signal=drive, sampling_period=timestep.rescale(pq.s)) # Setup and run simulation with NEURON dd_netcons = network.get_netcons("cortical_input", "DD") # ... (simulation loop drives DD neurons and records spikes) ``` -------------------------------- ### Clean Documentation Build (Bash) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/README.md Command to clean the generated documentation build files. This is useful before rebuilding to ensure a fresh build. ```bash make clean ``` -------------------------------- ### Add GPU Acceleration Dependency (Optional) Source: https://github.com/nsquaredlab/myogen/blob/main/README.md Command to add `cupy-cuda12x` for optional GPU acceleration, which can significantly speed up convolution operations. ```bash uv add cupy-cuda12x ``` -------------------------------- ### Saving and Loading Neo Blocks using Joblib (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst Shows how to save and load Neo data blocks using the 'joblib' library. This is useful for persisting simulation results or intermediate data for later use. ```python import joblib # Save blocks joblib.dump(spike_train__Block, "spike_trains.pkl") joblib.dump(surface_emg__Block, "surface_emg.pkl") # Load blocks spike_trains = joblib.load("spike_trains.pkl") surface_emg = joblib.load("surface_emg.pkl") ``` -------------------------------- ### Add GPU Acceleration Package Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/index.md Command to add the 'cupy-cuda12x' package, which enables GPU acceleration for significantly faster convolutions. This requires an NVIDIA GPU. ```bash uv add cupy-cuda12x ``` -------------------------------- ### Access SPIKE_TRAIN__Block Structure and Data (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst Shows how to navigate the structure of a SPIKE_TRAIN__Block to access individual motor pools and spiketrains. It demonstrates extracting spike times, counting spikes, and retrieving the duration and sampling rate of a spiketrain. ```python # Access spike trains motor_pool = spike_train__Block.segments[pool_idx] spiketrain = motor_pool.spiketrains[neuron_idx] # Extract data spike_times__s = spiketrain.magnitude # NumPy array n_spikes = len(spiketrain) duration = spiketrain.t_stop sampling_rate = spiketrain.sampling_rate ``` -------------------------------- ### NEURON Integration Utilities Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/api/utils_api.rst Utilities for injecting currents into NEURON populations and simulating spike trains. ```APIDOC ## NEURON Current Injection and Simulation ### Description Functions to facilitate the injection of currents into NEURON simulation populations and to simulate spike trains based on these injections. ### Functions - `inject_currents_into_populations` - `inject_currents_and_simulate_spike_trains` ``` -------------------------------- ### Create Neural Populations and Network Connections in MyoGen (Python) Source: https://context7.com/nsquaredlab/myogen/llms.txt This snippet demonstrates the creation of various neural populations (AlphaMN, DescendingDrive, Afferent, Interneuron) and muscle/joint models. It then constructs a network by connecting these populations with specified probabilities and weights, including inhibitory connections. ```python from myogen.models import AlphaMN__Pool, DescendingDrive__Pool, AffIa__Pool, AffII__Pool, AffIb__Pool, GII__Pool, GIb__Pool from myogen.models.muscle import SpindleModel, GolgiTendonOrganModel, HillModel, JointDynamics from myogen.network import Network from myogen.runner import SimulationRunner import quantities as pq # Simulation parameters (assuming dt and tstop are defined elsewhere) dt = 0.1 # Example timestep in ms tstop = 1000 # Example simulation time in ms # Create neural populations aMN = AlphaMN__Pool(recruitment_thresholds__array=thresholds) DD = DescendingDrive__Pool(n=400, poisson_batch_size=5, timestep__ms=dt) Ia = AffIa__Pool(n=73, timestep__ms=dt) II = AffII__Pool(n=80, timestep__ms=dt) Ib = AffIb__Pool(n=58, timestep__ms=dt) gII = GII__Pool(n=120) gIb = GIb__Pool(n=145) # Create proprioceptive and muscle models spindle = SpindleModel( simulation_time__ms=tstop * pq.ms, time_step__ms=dt, spindle_parameters=SpindleModel.create_default_spindle_parameters() ) gto = GolgiTendonOrganModel( simulation_time__ms=tstop * pq.ms, time_step__ms=dt, gto_parameters=GolgiTendonOrganModel.create_default_gto_parameters() ) muscle = HillModel( simulation_time__ms=tstop * pq.ms, time_step__ms=dt, muscle_parameters=HillModel.create_default_muscle_parameters(), n_motor_units_type1=102, n_motor_units_type2=18, ) joint = JointDynamics(inertia__kg_m2=0.001, damping__Nm_s_per_rad=0.002) # Create network and connect populations network = Network({ "DD": DD, "aMN": aMN, "Ia": Ia, "II": II, "Ib": Ib, "gII": gII, "gIb": gIb }) network.connect("DD", "aMN", probability=0.3, weight__uS=0.05 * pq.uS) network.connect("Ia", "aMN", probability=0.8, weight__uS=0.05 * pq.uS) # Stretch reflex network.connect("II", "gII", probability=0.3, weight__uS=0.025 * pq.uS) network.connect("gII", "aMN", probability=0.3, weight__uS=0.05 * pq.uS, inhibitory=True) network.connect("Ib", "gIb", probability=0.3, weight__uS=0.025 * pq.uS) network.connect("gIb", "aMN", probability=0.3, weight__uS=0.05 * pq.uS, inhibitory=True) # Run simulation with SimulationRunner def my_callback(t, dt, network, models): # Define your callback function here if needed pass models = {"hill_muscle": muscle, "spin": spindle, "gto": gto, "joint": joint} runner = SimulationRunner(network=network, models=models, step_callback=my_callback) results = runner.run(duration__ms=tstop * pq.ms, timestep__ms=dt) ``` -------------------------------- ### Load Simulation Data with Joblib Source: https://github.com/nsquaredlab/myogen/blob/main/docs/neo_blocks.md Demonstrates how to load simulation results saved using joblib. This is the primary method for accessing stored MyoGen data. ```python import joblib # Load data = joblib.load("results.pkl") ``` -------------------------------- ### Access MyoGen Simulation Results with Neo Block (Python) Source: https://context7.com/nsquaredlab/myogen/llms.txt This snippet shows how to load simulation results stored in Neo Block objects using joblib. It demonstrates accessing spike trains and analog signals (EMG) from different parts of the Neo Block structure, including common data extraction and manipulation techniques. ```python import joblib import numpy as np from myogen.utils.neo import signal_to_grid from elephant.statistics import mean_firing_rate # SPIKE TRAINS: segments[pool].spiketrains[neuron] spike_block = joblib.load("spike_trains.pkl") for i, st in enumerate(spike_block.segments[0].spiketrains): if len(st) > 0: print(f"MU {i}: {len(st)} spikes, rate={len(st)/st.t_stop.magnitude:.1f} Hz") # SURFACE EMG/MUAP: groups[array].segments[pool/mu].analogsignals[0] emg_block = joblib.load("surface_emg.pkl") signal = emg_block.groups[0].segments[0].analogsignals[0] emg_grid = signal_to_grid(signal) # Convert to 3D (time, rows, cols) time = signal.times.magnitude electrode_trace = emg_grid[:, 2, 2] # Center electrode # INTRAMUSCULAR EMG: segments[pool].analogsignals[0] iemg_block = joblib.load("intramuscular_emg.pkl") iemg_signal = iemg_block.segments[0].analogsignals[0] channel_0 = iemg_signal[:, 0].magnitude # Common operations print(f"Sampling rate: {signal.sampling_rate}") print(f"Units: {signal.units}") print(f"Duration: {signal.t_start} to {signal.t_stop}") # Time slicing for spike trains windowed = spike_block.segments[0].spiketrains[0].time_slice(1.0, 3.0) rate = mean_firing_rate(windowed) ``` -------------------------------- ### Current Generation Utilities Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/api/utils_api.rst Functions for creating different types of electrical currents for simulations. ```APIDOC ## Current Generation Functions ### Description Provides functions to generate various current waveforms like ramp, step, sinusoidal, sawtooth, and trapezoidal currents. ### Functions - `create_ramp_current` - `create_step_current` - `create_sinusoidal_current` - `create_sawtooth_current` - `create_trapezoid_current` ``` -------------------------------- ### Generate Motor Unit Recruitment Thresholds Source: https://context7.com/nsquaredlab/myogen/llms.txt Generates motor unit recruitment thresholds using different physiologically-based models (Fuglevand, De Luca, Konstantin, or Combined). This determines the minimum activation level for each motor unit, following the size principle. Requires the 'myogen' library. ```python from myogen import simulator # Fuglevand model - classic exponential distribution thresholds_fuglevand, _ = simulator.RecruitmentThresholds( N=100, # Number of motor units recruitment_range__ratio=50, # Max threshold / min threshold ratio mode="fuglevand" ) # De Luca model - with slope control for distribution shape thresholds_deluca, _ = simulator.RecruitmentThresholds( N=100, recruitment_range__ratio=50, deluca__slope=5, # Controls curvature (0.001-50) mode="deluca" ) # Combined model - De Luca shape with Konstantin scaling thresholds_combined, _ = simulator.RecruitmentThresholds( N=100, recruitment_range__ratio=50, deluca__slope=5, konstantin__max_threshold__ratio=1.0, mode="combined" ) # Thresholds are normalized 0-1, representing % of max voluntary contraction print(f"First MU threshold: {thresholds_combined[0]:.3f}") # ~0.02 (2% MVC) print(f"Last MU threshold: {thresholds_combined[-1]:.3f}") # ~1.0 (100% MVC) ``` -------------------------------- ### Configure Surface Electrode Array Source: https://context7.com/nsquaredlab/myogen/llms.txt Configures a high-density surface electrode array for EMG recording, supporting monopolar and differential modes with customizable grid dimensions. Requires 'myogen' and 'quantities' libraries. ```python from myogen import simulator import quantities as pq # Create a 5x5 monopolar electrode array electrode_array = simulator.SurfaceElectrodeArray( num_rows=5, num_cols=5, inter_electrode_distances__mm=5 * pq.mm, # 5mm spacing electrode_radius__mm=5 * pq.mm, # Electrode contact radius differentiation_mode="monopolar", # or "single_diff", "double_diff" bending_radius__mm=25 * pq.mm, # Array curvature (for skin surface) ) # Access electrode positions print(f"Electrode positions shape: {electrode_array.electrode_positions__mm.shape}") print(f"Number of electrodes: {electrode_array.num_rows * electrode_array.num_cols}") ``` -------------------------------- ### Export MyoGen Simulation Results to NWB Format (Python) Source: https://context7.com/nsquaredlab/myogen/llms.txt This snippet demonstrates how to export MyoGen simulation results, loaded from a Neo Block file, into the Neurodata Without Borders (NWB) format. It includes necessary metadata for sharing and compatibility with neurophysiology tools. ```python from myogen.utils.nwb import export_to_nwb import joblib # Load simulation results (Neo Block) results = joblib.load("spinal_network_results.pkl") # Export to NWB format nwb_filepath = export_to_nwb( results, output_path="simulation_results.nwb", session_description="MyoGen spinal network simulation", experimenter="Researcher Name", institution="University", lab="Neuromuscular Lab", experiment_description="Motor neuron pool simulation with 100 MUs", keywords=["MyoGen", "EMG", "motor neuron", "simulation"], subject_id="simulated_001", species="Homo sapiens", subject_description="Simulated human motor neuron pool", ) print(f"Exported to: {nwb_filepath}") # Validate with: nwbinspector simulation_results.nwb ``` -------------------------------- ### Slicing Neo SpikeTrain by Time Source: https://github.com/nsquaredlab/myogen/blob/main/docs/neo_blocks.md Demonstrates how to extract a specific time window from a Neo SpikeTrain object. ```python # Slice time window windowed = spiketrain.time_slice(t_start, t_stop) ``` -------------------------------- ### Continuous Saver Utilities Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/api/utils_api.rst Utilities for managing and converting continuous simulation data. ```APIDOC ## Continuous Data Management ### Description Provides tools for saving continuous simulation data and converting data chunks into the Neo format. ### Classes - `ContinuousSaver`: Manages the saving of continuous simulation data. ### Functions - `convert_chunks_to_neo`: Converts simulation data chunks into the Neo data structure. ``` -------------------------------- ### Plotting and Visualization Utilities Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/api/utils_api.rst Functions for generating various plots related to simulation results. ```APIDOC ## Plotting and Visualization Functions ### Description Provides a suite of functions to visualize simulation outputs, including spike rasters, membrane potentials, muscle dynamics, and joint angles. ### Functions - `plot_raster_spikes` - `plot_membrane_potentials` - `plot_muscle_dynamics` - `plot_antagonist_muscle_comparison` - `plot_spindle_dynamics` - `plot_gto_dynamics` ``` -------------------------------- ### Simulate Intramuscular EMG with Myogen Source: https://context7.com/nsquaredlab/myogen/llms.txt This Python code simulates intramuscular EMG using needle electrodes. It involves loading a muscle model, creating an intramuscular electrode array, initializing the simulator, computing MUAPs, and generating EMG signals from spike trains. Libraries used include myogen, quantities, joblib, and numpy. ```python from myogen import simulator import quantities as pq import joblib import numpy as np # Load muscle model # Mocking joblib.load for demonstration muscle = joblib.load("muscle_model.pkl") # Create intramuscular electrode array (needle) electrode = simulator.IntramuscularElectrodeArray( num_electrodes=4, inter_electrode_distance__mm=2.0 * pq.mm, differentiation_mode="consecutive", # Differential recording position__mm=(0.0 * pq.mm, 0.0 * pq.mm, 15.0 * pq.mm), # Insertion position ) # Initialize intramuscular EMG simulator iemg_sim = simulator.IntramuscularEMG( muscle_model=muscle, electrode_array=electrode, MUs_to_simulate=[0, 25, 50, 90], # Selected motor units ) # Compute MUAPs # Mocking the output of simulate_muaps for demonstration class MockAnalogSignal: def __init__(self, shape): self.shape = shape self.magnitude = np.zeros(shape) class MockSegment: def __init__(self): self.analogsignals = [MockAnalogSignal((100, 1))] class MockIEMGBlock: def __init__(self): self.segments = [MockSegment() for _ in range(4)] # For the selected MUs # Mock the function to return a mock block def mock_simulate_muaps(*args, **kwargs): return MockIEMGBlock() iemg_sim.simulate_muaps = mock_simulate_muaps muaps = iemg_sim.simulate_muaps(n_jobs=2) # Access MUAP amplitude for mu_idx in [0, 25, 50, 90]: signal = muaps.segments[mu_idx].analogsignals[0] print(f"MU {mu_idx}: Peak-to-peak = {np.ptp(signal.magnitude[:, 0])*1000:.1f} µV") # Generate full EMG from spike trains spike_trains = joblib.load("spike_trains.pkl") # Mock the simulate_intramuscular_emg function def mock_simulate_intramuscular_emg(*args, **kwargs): return MockIEMGBlock() # Assuming it returns a block similar to muaps iemg_sim.simulate_intramuscular_emg = mock_simulate_intramuscular_emg emg_signals = iemg_sim.simulate_intramuscular_emg(spike_train__Block=spike_trains) # Add noise and access data # Mock the add_noise function def mock_add_noise(*args, **kwargs): return MockIEMGBlock() # Assuming it returns a block with noise added iemg_sim.add_noise = mock_add_noise noisy_emg = iemg_sim.add_noise(snr__dB=20) iemg_trace = noisy_emg.segments[0].analogsignals[0][:, 0].magnitude ``` -------------------------------- ### Access Intramuscular MUAP Segments and Signals (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst Demonstrates how to access segments and analog signals from an intramuscular MUAP block. It shows how to retrieve the magnitude of the MUAP signal and extract data for a specific electrode. ```python # Access intramuscular MUAPs muap_segment = im_muaps__Block.segments[muap_idx] muap_signal = muap_segment.analogsignals[0] # Extract data muap_array = muap_signal.magnitude # Shape: (time, electrodes) electrode_muap = muap_signal[:, electrode_idx] ``` -------------------------------- ### NWB Export Utilities Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/api/utils_api.rst Functions for exporting simulation data into the NWB format. ```APIDOC ## NWB Data Export ### Description Utilities to export simulation data into the Neurodata Without Borders (NWB) format, promoting data sharing and interoperability. Requires optional dependencies (`pip install myogen[nwb]`). ### Functions - `export_to_nwb`: Exports simulation data to NWB format. - `export_simulation_to_nwb`: Exports the entire simulation state to NWB format. - `validate_nwb`: Validates an NWB file. ``` -------------------------------- ### Converting Neo Data to NumPy Arrays Source: https://github.com/nsquaredlab/myogen/blob/main/docs/neo_blocks.md Shows how to convert Neo AnalogSignal and SpikeTrain objects into standard NumPy arrays for further numerical processing. ```python # Convert to numpy values = signal.magnitude time = signal.times.magnitude ``` -------------------------------- ### Access SURFACE_EMG__Block Structure and Data (Python) Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/neo_blocks_guide.rst Explains how to access synthesized surface EMG signals stored in a SURFACE_EMG__Block. It details navigating electrode arrays and motor pools to retrieve the EMG signal as a 3D array or for a specific electrode. ```python # Access surface EMG electrode_array = surface_emg__Block.groups[array_idx] motor_pool = electrode_array.segments[pool_idx] emg_signal = motor_pool.analogsignals[0] # Extract data emg_array = emg_signal.magnitude # Shape: (time, rows, cols) electrode_emg = emg_signal[:, row, col] # Specific electrode ``` -------------------------------- ### Generate Motor Unit Action Potentials (MUAPs) in Python Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/README.md This Python code snippet demonstrates the process of generating Motor Unit Action Potentials (MUAPs) using the MyoGen simulator. It involves generating recruitment thresholds, creating a muscle model, setting up a surface electrode array, configuring a surface EMG simulator, and finally simulating the MUAPs with parallel processing. ```python from myogen import simulator import quantities as pq # 1. Generate recruitment thresholds (100 motor units) thresholds, _ = simulator.RecruitmentThresholds( N=100, recruitment_range__ratio=50, mode="fuglevand" ) # 2. Create muscle model with fiber distribution muscle = simulator.Muscle( recruitment_thresholds=thresholds, radius_bone__mm=1.0 * pq.mm, fiber_density__fibers_per_mm2=400 * pq.mm**-2, fat_thickness__mm=10 * pq.mm, autorun=True ) # 3. Set up surface electrode array electrode_array = simulator.SurfaceElectrodeArray( num_rows=5, num_cols=5, inter_electrode_distances__mm=5 * pq.mm, electrode_radius__mm=5 * pq.mm, bending_radius__mm=muscle.radius__mm + muscle.skin_thickness__mm + muscle.fat_thickness__mm, ) # 4. Create surface EMG simulator surface_emg = simulator.SurfaceEMG( muscle_model=muscle, electrode_arrays=[electrode_array], sampling_frequency__Hz=2048.0, MUs_to_simulate=[0, 1, 2, 3, 4] # First 5 motor units ) # 5. Simulate MUAPs (parallel processing) muaps = surface_emg.simulate_muaps(n_jobs=-2) ``` -------------------------------- ### Calculating Mean Firing Rate with Elephant Source: https://github.com/nsquaredlab/myogen/blob/main/docs/neo_blocks.md Shows how to compute the mean firing rate of a Neo SpikeTrain using the Elephant library, a common tool for analyzing neural data. ```python # Firing rate (requires elephant) import elephant.statistics rate = elephant.statistics.mean_firing_rate(spiketrain) ``` -------------------------------- ### Quantity Type Definitions Source: https://github.com/nsquaredlab/myogen/blob/main/docs/source/api/utils_api.rst Defines standard units for physical quantities used in simulations. ```APIDOC ## Quantity Types ### Description Defines standardized quantity types with associated units for use within MyoGen simulations, ensuring consistency in measurements. ### Defined Quantities - Time: `Quantity__s`, `Quantity__ms` - Angle: `Quantity__rad`, `Quantity__deg` - Voltage: `Quantity__mV`, `Quantity__uV` - Current: `Quantity__nA` - Conductance: `Quantity__uS`, `Quantity__S_per_m` - Frequency: `Quantity__Hz`, `Quantity__pps` - Length: `Quantity__mm`, `Quantity__m` - Area: `Quantity__mm2` - Density: `Quantity__per_mm2` - Velocity: `Quantity__m_per_s`, `Quantity__mm_per_s` ``` -------------------------------- ### Create Cylindrical Muscle Model Source: https://context7.com/nsquaredlab/myogen/llms.txt Creates a cylindrical muscle model with physiologically distributed motor units and muscle fibers, defining their spatial organization using Voronoi tessellation. Requires recruitment thresholds, anatomical parameters, and libraries like 'myogen', 'quantities', and 'joblib'. ```python from myogen import simulator import quantities as pq import joblib # Load or create recruitment thresholds thresholds, _ = simulator.RecruitmentThresholds( N=100, recruitment_range__ratio=50, mode="combined", deluca__slope=5 ) # Create muscle model with anatomical parameters muscle = simulator.Muscle( recruitment_thresholds=thresholds, radius_bone__mm=1.0 * pq.mm, # Bone radius at center fiber_density__fibers_per_mm2=400 * pq.mm**-2, # Fibers per mm² fat_thickness__mm=10 * pq.mm, # Subcutaneous fat layer skin_thickness__mm=1.0 * pq.mm, # Skin thickness (default) autorun=True, # Auto-generate fiber positions ) # Access muscle properties print(f"Muscle radius: {muscle.radius__mm}") print(f"Total fibers: {sum(muscle.resulting_number_of_innervated_fibers)}") print(f"Fibers in MU 0: {muscle.resulting_number_of_innervated_fibers[0]}") # Save for reuse (expensive computation) joblib.dump(muscle, "muscle_model.pkl") ```