Source pulse parameter on EM-LF simulation on Yoon-son model
-
Hi all,
I'm running an EM-LF (Electro Ohmic Quasi-static) simulation using the Yoon-son anatomical model and would like to apply a bi-phasic pulse with a defined amplitude and pulse width across an electrode pair.
What is the recommended approach for implementing this type of time-dependent source condition in the simulation setup?
Can this be directly defined in the solver settings, or does it need to be modeled through post-processing?Any guidance or examples would be greatly appreciated.
Many thanks in advance.
-
There are different ways to apply the modulation pulse in your simulation.
-
If you are aiming to simulate neuro-stimulation, you should link your EM-LF simulation to a NEURON simulation. In this case, you can define the modulation pulse using the NEURON Source settings by selecting "Bipolar" as the Pulse Type. For a detailed example, I recommend checking out the Yoon-Sun Arm Stimulation tutorial.
-
If you are not doing neuromodulation, but instead you are interested in dosimetry, you can also apply the modulation pulse as a post-processing step using the Python API. Below is an implementation example (to adapt to your pulse signal and project).
I hope this helps.
from collections import defaultdict from pathlib import Path import matplotlib.pyplot as plt import numpy as np import s4l_v1.analysis as analysis import s4l_v1.document as document import s4l_v1.materials.database as database import s4l_v1.model as model import s4l_v1.units as units import XCoreModeling as xcm import XPostProcessor as xp from s4l_v1.data import TutorialDataDirectory from s4l_v1.model import Vec3 from s4l_v1.renderer import SetViewDirection, ShowScreenCapture, ZoomToEntity from s4l_v1.simulation import emlf, neuron import numpy as np def create_data_producer( x_array, data_array, x_name, x_unit, y_name, y_unit, name, iscomplex=True ): if iscomplex: data = xp.ComplexFloatXYData() else: data = xp.FloatXYData() quantity = xp.Quantity() quantity.Name = y_name quantity.Unit = xp.Unit(y_unit) data.Quantity = quantity assert data.Allocate(len(data_array), [1]) data.Axis = x_array.astype(np.float64) quantity = xp.Quantity() quantity.Name = x_name quantity.Unit = xp.Unit(x_unit) data.AxisQuantity = quantity if iscomplex: data.SetComponent(0, data_array.astype(np.complex64)) else: data.SetComponent(0, data_array.astype(np.float32)) # producer producer = analysis.core.TrivialProducer() producer.SetDataObject(data) producer.Description = str(name) document.AllAlgorithms.Add(producer) return producer # define short rectangular pulse (to be changed with custom pulse) t_1 = 0.5 * 1e-3 # s pulse_amplitude = 1 pulse_duration = 0.3 * 1e-3 # s t_max = 3 * 1e-3 Nt = 5001 dt = t_max / Nt t_array = np.linspace(0, t_max, Nt).astype(np.float32) pulse_array = np.zeros_like(t_array) pulse_array = np.where( (t_array > t_1) & (t_array <= t_1 + pulse_duration), pulse_amplitude, pulse_array, ) modulating_pulse_producer = create_data_producer( t_array, pulse_array, "Time", "s", "Modulation(t)", "", "Modulating Pulse", iscomplex=False, ) # Creating the analysis pipeline # Adding a new SimulationExtractor simulation = document.AllSimulations["Your Simulation Name"] simulation_extractor = simulation.Results() # Adding a new EmSensorExtractor em_sensor_extractor = simulation_extractor["Overall Field"] em_sensor_extractor.FrequencySettings.ExtractedFrequency = u"All" document.AllAlgorithms.Add(em_sensor_extractor) # Attach modulation to quasi-static EM field inputs = [em_sensor_extractor.Outputs[0], modulating_pulse_producer.Outputs[0]] modulated_field = analysis.core.ModulatedFieldEvaluator(inputs=inputs) modulated_field.UpdateAttributes() modulated_field.Name = "Modulated Efield" document.AllAlgorithms.Add(modulated_field)
-
-
Hi @carbonell ,
Thanks for the information.
I’m currently working on Sim4Life IO, but this is my first time using the Python API within this platform.
Here’s what I’ve tried so far:
-
I launched JupyterLab from the Sim4Life IO interface.
-
I copied and pasted the example code into a notebook and ran it cell by cell.
However, I encountered the following error:
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[4], line 37 34 # Creating the analysis pipeline 35 # Adding a new SimulationExtractor 36 simulation = document.AllSimulations["Simple ES"] ---> 37 simulation_extractor = simulation.Results() 39 # Adding a new EmSensorExtractor 40 em_sensor_extractor = simulation_extractor["Overall Field"] AttributeError: 'NoneType' object has no attribute 'Results'
It seems like simulation is returning None, but I’ve already created a simulation named “Simple ES” in the GUI.
Is there something I’m missing in how simulations are referenced or accessed in Sim4Life IO via Python?
Any help or pointers to relevant documentation would be greatly appreciated.
Thanks
-
-
Hi @carbonell ,
Thanks for the information.
I’m currently working on Sim4Life IO, but this is my first time using the Python API within this platform.
Here’s what I’ve tried so far:
-
I launched JupyterLab from the Sim4Life IO interface.
-
I copied and pasted the example code into a notebook and ran it cell by cell.
However, I encountered the following error:
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[4], line 37 34 # Creating the analysis pipeline 35 # Adding a new SimulationExtractor 36 simulation = document.AllSimulations["Simple ES"] ---> 37 simulation_extractor = simulation.Results() 39 # Adding a new EmSensorExtractor 40 em_sensor_extractor = simulation_extractor["Overall Field"] AttributeError: 'NoneType' object has no attribute 'Results'
It seems like simulation is returning None, but I’ve already created a simulation named “Simple ES” in the GUI.
Is there something I’m missing in how simulations are referenced or accessed in Sim4Life IO via Python?
Any help or pointers to relevant documentation would be greatly appreciated.
Thanks
-