Source code for nrv.nmod._myelinated

"""
NRV-:class:`.myelinated` handling.
"""

import math

import numpy as np
import matplotlib.pyplot as plt

from nrv.nmod.results._axons_results import axon_results

from ._axons import (
    axon,
    neuron,
    myelinated_models,
    rotate_list,
    d_lambda_rule,
    create_Nseg_freq_shape,
)
from .results._myelinated_results import myelinated_results
from ..backend._log_interface import rise_warning
from ..backend._NRV_Class import is_empty_iterable
from ..utils._misc import (
    nearest_idx,
    get_MRG_parameters,
    get_length_from_nodes,
)


[docs] class myelinated(axon): """ Myelinated axon class. Automatic refinition of all neuron sections and properties. User-friendly object including model definition Inherit from axon class. see axon for further detail. Parameters ---------- y : float y coordinate for the axon, in um z : float z coordinate for the axon, in um d : float axon diameter, in um L : float axon length along the x axins, in um model : str choice of conductance double-cable based model, possibly: "MRG" : see [1] for details "Gaines_motor" : Gaines motor model, see [2] "Gaines_sensory": Gaines sensory model, see [2] dt : float computation step for simulations, in ms. By default equal to 1 us node_shift : float shift of the first node of Ranvier to zeros, as a fraction of internode length (0<= node_shift < 1) Nseg_per_sec : int Number of segment per section in the axon. If set to 0, the number of segment is automatically computed using d-lambda rule and following paramters. If set by user, please use odd numbers freq : float Frequency used for the d-lmbda rule, corresponding to the maximum membrane current frequency, by default set to 100 Hz freq_min : float Minimal frequency fot the d-lambda rule when using an irregular number of segment along the axon, if set to 0, all sections have the same frequency determined by the previous parameter mesh_shape : str Shape of the frequencial distribution for the dlmabda rule along the axon, pick between: "pyramidal" -> min frequencies on both sides and linear increase up to the middle at the maximum frequency "sigmoid" -> same a befor with sigmoid increase instead of linear "plateau" -> sale as pyramidal except the max frequency is holded on a central plateau "plateau_sigmoid" -> same as previous with sigmoid increase alpha_max : float Proportion of the axon set to the maximum frequency for plateau shapes, by default set to 0.3 d_lambda : float value of d-lambda for the dlambda rule rec : str recording zones for the membrane potential, eiter: "nodes" -> record only at the nodes of Ranvier or "all" -> all computation points in nodes of Ranvier and over myelin v_init : float Initial value of the membrane voltage in mV, set None to get an automatically model attributed value T : gloat temperature in C, set None to get an automatically model attributed value ID : int axon ID, by default set to 0, threshold : float voltage threshold in mV for further spike detection in post-processing, by defautl set to -40mV, see post-processing library for further help Note ---- scientific sources for models: [1] McIntyre CC, Richardson AG, and Grill WM. Modeling the excitability of mammalian nerve fibers: influence of afterpotentials on the recovery cycle. Journal of Neurophysiology 87:995-1006, 2002. [2] Gaines, J. L., Finn, K. E., Slopsema, J. P., Heyboer, L. A., Polasek, K. H. (2018). A model of motor and sensory axon activation in the median nerve using surface electrical stimulation. Journal of computational neuroscience, 45(1), 29-43. """
[docs] def __init__( self, y=0, z=0, d=10, L=10000, model="MRG", dt=0.001, node_shift=0, Nseg_per_sec=1, freq=100, freq_min=0, mesh_shape="plateau_sigmoid", alpha_max=0.3, d_lambda=0.1, rec="nodes", v_init=None, T=None, ID=0, threshold=-40, **kwargs, ): """ initialisation of a myelinted axon """ super().__init__( y, z, d, L, dt=dt, Nseg_per_sec=Nseg_per_sec, freq=freq, freq_min=freq_min, mesh_shape=mesh_shape, alpha_max=alpha_max, d_lambda=d_lambda, v_init=v_init, T=T, ID=ID, threshold=threshold, **kwargs, ) self.myelinated = True self.thin = False self.rec = rec self.node_shift = node_shift if model in myelinated_models: self.model = model else: self.model = "MRG" self.__compute_axon_parameters()
def __compute_axon_parameters(self): """ generate axon from parameters set by user """ if self.v_init is None: # model driven if self.model == "Gaines_sensory": self.v_init = -79.3565 elif self.model == "Gaines_motor": self.v_init = -85.9411 else: self.v_init = -80 else: # user driven self.v_init = self.v_init ## Handling temperature if self.T is None: # model driven self.T = 37 ############################################ ## PARMETERS FOR THE COMPARTIMENTAL MODEL ## ############################################ # compute variable MRG parameters, (usefull also if non MRG models) ( self.g, self.axonD, self.nodeD, self.paraD1, self.paraD2, self.deltax, self.paralength2, self.nl, ) = get_MRG_parameters(self.d) # Morphological parameters self.paralength1 = 3 self.nodelength = 1.0 self.space_p1 = 0.002 self.space_p2 = 0.004 self.space_i = 0.004 self.interlength = ( self.deltax - self.nodelength - (2 * self.paralength1) - (2 * self.paralength2) ) / 6 # electrical parameters self.rhoa = 0.7e6 # Ohm-um self.mycm = 0.1 # uF/cm2/lamella membrane self.mygm = 0.001 # S/cm2/lamella membrane self.Rpn0 = (self.rhoa * 0.01) / ( math.pi * ((((self.nodeD / 2) + self.space_p1) ** 2) - ((self.nodeD / 2) ** 2)) ) self.Rpn1 = (self.rhoa * 0.01) / ( math.pi * ((((self.paraD1 / 2) + self.space_p1) ** 2) - ((self.paraD1 / 2) ** 2)) ) self.Rpn2 = (self.rhoa * 0.01) / ( math.pi * ((((self.paraD2 / 2) + self.space_p2) ** 2) - ((self.paraD2 / 2) ** 2)) ) self.Rpx = (self.rhoa * 0.01) / ( math.pi * ((((self.axonD / 2) + self.space_i) ** 2) - ((self.axonD / 2) ** 2)) ) ######################### ## morphology planning ## ######################### # basic MRG sequence self.MRG_Sequence = [ "node", "MYSA", "FLUT", "STIN", "STIN", "STIN", "STIN", "STIN", "STIN", "FLUT", "MYSA", ] # basic MRG starts with the node, if needed, adapt the sequence if self.node_shift == 0 or self.node_shift == 1: # no Rotation self.this_ax_sequence = self.MRG_Sequence self.first_section_size = self.nodelength elif self.node_shift < (self.paralength1) / self.deltax: # rotation of less than 1 MYSA self.this_ax_sequence = rotate_list(self.MRG_Sequence, 1) self.first_section_size = self.node_shift * self.deltax elif self.node_shift < (self.paralength1 + self.paralength2) / self.deltax: # rotation of 1 MYSA and less than one FLUT self.this_ax_sequence = rotate_list(self.MRG_Sequence, 2) self.first_section_size = self.node_shift * self.deltax - self.paralength1 elif ( self.node_shift < (self.paralength1 + self.paralength2 + self.interlength) / self.deltax ): # rotation of 1 MYSA, 1 FLUT and less than a STIN self.this_ax_sequence = rotate_list(self.MRG_Sequence, 3) self.first_section_size = ( self.node_shift * self.deltax - self.paralength1 - self.paralength2 ) elif ( self.node_shift < (self.paralength1 + self.paralength2 + 2 * self.interlength) / self.deltax ): # rotation of 1 MYSA, 1 FLUT, 1 STIN and less than a STIN self.this_ax_sequence = rotate_list(self.MRG_Sequence, 4) self.first_section_size = ( self.node_shift * self.deltax - self.paralength1 - self.paralength2 - self.interlength ) elif ( self.node_shift < (self.paralength1 + self.paralength2 + 3 * self.interlength) / self.deltax ): # rotation of 1 MYSA, 1 FLUT, 2 STIN and less than a STIN self.this_ax_sequence = rotate_list(self.MRG_Sequence, 5) self.first_section_size = ( self.node_shift * self.deltax - self.paralength1 - self.paralength2 - 2 * self.interlength ) elif ( self.node_shift < (self.paralength1 + self.paralength2 + 4 * self.interlength) / self.deltax ): # rotation of 1 MYSA, 1 FLUT, 3 STIN and less than a STIN self.this_ax_sequence = rotate_list(self.MRG_Sequence, 6) self.first_section_size = ( self.node_shift * self.deltax - self.paralength1 - self.paralength2 - 3 * self.interlength ) elif ( self.node_shift < (self.paralength1 + self.paralength2 + 5 * self.interlength) / self.deltax ): # rotation of 1 MYSA, 1 FLUT, 4 STIN and less than a STIN self.this_ax_sequence = rotate_list(self.MRG_Sequence, 7) self.first_section_size = ( self.node_shift * self.deltax - self.paralength1 - self.paralength2 - 4 * self.interlength ) elif ( self.node_shift < (self.paralength1 + self.paralength2 + 6 * self.interlength) / self.deltax ): # rotation of 1 MYSA, 1 FLUT, 5 STIN and less than a STIN self.this_ax_sequence = rotate_list(self.MRG_Sequence, 8) self.first_section_size = ( self.node_shift * self.deltax - self.paralength1 - self.paralength2 - 5 * self.interlength ) elif ( self.node_shift < (self.paralength1 + 2 * self.paralength2 + 6 * self.interlength) / self.deltax ): # rotation of 1 MYSA, 1 FLUT, 6 STIN and less than a FLUT self.this_ax_sequence = rotate_list(self.MRG_Sequence, 9) self.first_section_size = ( self.node_shift * self.deltax - self.paralength1 - self.paralength2 - 6 * self.interlength ) else: # rotation of 1 MYSA, 2 FLUT, 6 STIN and less than a MYSA # WARNING FOR DEV : the unprobable case of a node cut in two halfs is not considered... self.this_ax_sequence = rotate_list(self.MRG_Sequence, 10) self.first_section_size = self.deltax * (1 - self.node_shift) ################ ## morphology ## ################ self.axonnodes = 0 # number of nodes in the axon self.node = [] # list of nodes in the axon self.paranodes1 = 0 # number of MYSA in the axon self.MYSA = [] # list of MYSA in the axon self.paranodes2 = 0 # number of FLUT in the axon self.FLUT = [] # list of FLUT in the axon self.axoninter = 0 # number of STIN in the axon self.STIN = [] # list of STIN in the axon prov_length = 0 self.Nsec = 0 self.last_section_size = 0 self.last_section_kind = None self.axon_path_type = [] self.axon_path_index = [] while prov_length < self.L: # axon is too short, create a section pos_in_sequence = (self.Nsec) % len( self.this_ax_sequence ) # find the current position in the node sequence if self.this_ax_sequence[pos_in_sequence] == "node": # you need to create a node self.node.append(neuron.h.Section(name="node[%d]" % self.axonnodes)) self.axon_path_type.append("node") self.axon_path_index.append(self.axonnodes) self.axonnodes += 1 self.Nsec += 1 # increment the prov length and check it is not to much if prov_length + self.nodelength >= self.L: # it will be the last section to add to the axon self.last_section_kind = "node" self.last_section_size = self.L - prov_length prov_length += self.nodelength # CONNECT THE NODE TO ITS PARENT: a node can only have a MYSA for parent, check it"s not the start... if self.paranodes1 != 0: self.node[-1].connect(self.MYSA[-1], 1, 0) elif self.this_ax_sequence[pos_in_sequence] == "MYSA": # you need to create a MYSA self.MYSA.append(neuron.h.Section(name="MYSA[%d]" % self.paranodes1)) self.axon_path_type.append("MYSA") self.axon_path_index.append(self.paranodes1) self.paranodes1 += 1 self.Nsec += 1 # increment the prov length and check it is not to much if prov_length + self.paralength1 >= self.L: # it will be the last section to add to the axon self.last_section_kind = "MYSA" self.last_section_size = self.L - prov_length prov_length += self.paralength1 # CONNECT THE MYSA TO ITS PARENT: a MYSA can have for parent a node or a FLUT, check it"s not the start... connect_to_type = self.this_ax_sequence[ pos_in_sequence - 1 ] # get parent type if connect_to_type == "node" and self.axonnodes != 0: self.MYSA[-1].connect(self.node[-1], 1, 0) if connect_to_type == "FLUT" and self.paranodes2 != 0: self.MYSA[-1].connect(self.FLUT[-1], 1, 0) elif self.this_ax_sequence[pos_in_sequence] == "FLUT": # you need to create a FLUT self.FLUT.append(neuron.h.Section(name="FLUT[%d]" % self.paranodes2)) self.axon_path_type.append("FLUT") self.axon_path_index.append(self.paranodes2) self.paranodes2 += 1 self.Nsec += 1 # increment the prov length and check it is not to much if prov_length + self.paralength2 >= self.L: # it will be the last section to add to the axon self.last_section_kind = "FLUT" self.last_section_size = self.L - prov_length prov_length += self.paralength2 # CONNECT THE FLUT TO ITS PARENT: a FLUT can have for parent a MYSA of a STIN, check it"s not the start... connect_to_type = self.this_ax_sequence[ pos_in_sequence - 1 ] # get parent type if connect_to_type == "MYSA" and self.paranodes1 != 0: self.FLUT[-1].connect(self.MYSA[-1], 1, 0) if connect_to_type == "STIN" and self.axoninter != 0: self.FLUT[-1].connect(self.STIN[-1], 1, 0) else: # you need to create a STIN self.STIN.append(neuron.h.Section(name="STIN[%d]" % self.axoninter)) self.axon_path_type.append("STIN") self.axon_path_index.append(self.axoninter) self.axoninter += 1 self.Nsec += 1 # increment the prov length and check it is not to much if prov_length + self.interlength >= self.L: # it will be the last section to add to the axon self.last_section_kind = "STIN" self.last_section_size = self.L - prov_length prov_length += self.interlength # CONNECT THE STIN TO ITS PARENT: a STIN can have for parent a STIN od a FLUT, check it"s not the start... connect_to_type = self.this_ax_sequence[pos_in_sequence - 1] if connect_to_type == "STIN" and self.axoninter > 1: self.STIN[-1].connect(self.STIN[-2], 1, 0) if connect_to_type == "FLUT" and self.paranodes2 != 0: self.STIN[-1].connect(self.FLUT[-1], 1, 0) if is_empty_iterable(self.node): rise_warning( "Warning, myelinated axon without node... this can cause latter errors and is maybe unwanted ?\n" ) # logging.warning("Warning, myelinated axon without node... this can cause latter errors and is maybe unwanted ?\n") #################### ## programm model ## #################### self.__set_model(self.model) # adjust the length of the first section if self.this_ax_sequence[0] == "node": self.node[0].L = self.first_section_size elif self.this_ax_sequence[0] == "MYSA": self.MYSA[0].L = self.first_section_size elif self.this_ax_sequence[0] == "FLUT": self.FLUT[0].L = self.first_section_size else: # should be a STIN self.STIN[0].L = self.first_section_size # adjust the length if the last section if self.last_section_kind == "node": self.node[-1].L = self.last_section_size elif self.last_section_kind == "MYSA": self.MYSA[-1].L = self.last_section_size elif self.last_section_kind == "FLUT": self.FLUT[-1].L = self.last_section_size else: # should be a STIN self.STIN[-1].L = self.last_section_size # define the geometry of the axon self._axon__define_shape() # define the number of segments self.__set_Nseg() # get nodes positions self.__get_seg_positions() self.__get_rec_positions() @property def n_nodes(self)->int: """ number of nodes of Ranvier Returns ------- int """ return len(self.node)
[docs] def save( self, save=False, fname="axon.json", extracel_context=False, intracel_context=False, rec_context=False, blacklist=[], ): """ Return axon as dictionary and eventually save it as json file Parameters ---------- save : bool if True, save in json files fname : str Path and Name of the saving file, by default "axon.json" Returns ------- ax_dic : dict dictionary containing all information """ blacklist += ["node", "MYSA", "FLUT", "STIN"] return super().save( save=save, fname=fname, extracel_context=extracel_context, intracel_context=intracel_context, rec_context=rec_context, blacklist=blacklist, )
[docs] def plot( self, axes: plt.axes, color: str = "red", node_color: str = "lightgray", elec_color="gold", **kwgs, ) -> None: super().plot(axes, color, elec_color, **kwgs) alpha = 1 if "alpha" in kwgs: alpha = kwgs["alpha"] axes.add_patch( plt.Circle( (self.y, self.z), self.nodeD / 2, fc=node_color, fill=True, alpha=alpha, ) )
def __set_model(self, model): """ Set the double cable model. For internal use only. Parameters ---------- model : str choice of conductance double-cable based model, possibly: "MRG" : see [1] for details "Gaines_motor" : Gaines motor model, see [2] "Gaines_sensory": Gaines sensory model, see [2] Note ---- scientific sources for models: [1] McIntyre CC, Richardson AG, and Grill WM. Modeling the excitability of mammalian nerve fibers: influence of afterpotentials on the recovery cycle. Journal of Neurophysiology 87:995-1006, 2002. [2] Gaines, J. L., Finn, K. E., Slopsema, J. P., Heyboer, L. A., Polasek, K. H. (2018). A model of motor and sensory axon activation in the median nerve using surface electrical stimulation. Journal of computational neuroscience, 45(1), 29-43. """ for n in self.node: n.nseg = 1 n.diam = self.nodeD n.L = self.nodelength n.Ra = self.rhoa / 10000 n.cm = 2 if model == "Gaines_sensory": n.insert("node_sensory") elif model == "Gaines_motor": n.insert("node_motor") else: n.insert("axnode") n.insert("extracellular") n.xraxial[0] = self.Rpn0 n.xg[0] = 1e10 n.xc[0] = 0 for m in self.MYSA: m.nseg = 1 m.diam = self.d m.L = self.paralength1 m.Ra = self.rhoa * (1 / (self.paraD1 / self.d) ** 2) / 10000 m.cm = 2 * self.paraD1 / self.d if model == "Gaines_sensory": m.insert("mysa_sensory") elif model == "Gaines_motor": m.insert("mysa_motor") else: m.insert("pas") m.g_pas = 0.001 * self.paraD1 / self.d m.e_pas = -80 m.insert("extracellular") m.xraxial[0] = self.Rpn1 m.xg[0] = self.mygm / (self.nl * 2) m.xc[0] = self.mycm / (self.nl * 2) for f in self.FLUT: f.nseg = 1 f.diam = self.d f.L = self.paralength2 f.Ra = self.rhoa * (1 / (self.paraD2 / self.d) ** 2) / 10000 f.cm = 2 * self.paraD2 / self.d if model == "Gaines_sensory": f.insert("flut_sensory") elif model == "Gaines_motor": f.insert("flut_motor") else: f.insert("pas") f.g_pas = 0.0001 * self.paraD2 / self.d f.e_pas = -80 f.insert("extracellular") f.xraxial[0] = self.Rpn2 f.xg[0] = self.mygm / (self.nl * 2) f.xc[0] = self.mycm / (self.nl * 2) for s in self.STIN: s.nseg = 1 s.diam = self.d s.L = self.interlength s.Ra = self.rhoa * (1 / (self.axonD / self.d) ** 2) / 10000 s.cm = 2 * self.axonD / self.d if model == "Gaines_sensory": s.insert("stin_sensory") elif model == "Gaines_motor": s.insert("stin_motor") else: s.insert("pas") s.g_pas = 0.0001 * self.axonD / self.d s.e_pas = -80 s.insert("extracellular") s.xraxial[0] = self.Rpx s.xg[0] = self.mygm / (self.nl * 2) s.xc[0] = self.mycm / (self.nl * 2)
[docs] def set_Markov_Nav(self, list_of_nodes=[]): """ Change typical particle-Na sodium in Hodgking-Huxley formalism to Markov-channel population model. Parameters ---------- list_of_nodes : list, array, np.array list of Nodes of Ranier to modify, if empty, all nodes sodium channels are changed Note ---- based on: Yi, G., and Grill, W. M. (2020). Kilohertz waveforms optimized to produce closed-state Na+ channel inactivation eliminate onset response in nerve conduction block. PLoS computational biology, 16(6), e1007766. !!! TO USE WITH CAUTION !!! """ if is_empty_iterable(list_of_nodes): list_of_nodes = np.arange(self.axonnodes) if self.model == "MRG": for NoR in list_of_nodes: self.node[NoR].gnapbar_axnode = 0 self.node[NoR].gnabar_axnode = 0 elif self.model == "Gaines_motor": for NoR in list_of_nodes: self.node[NoR].gnapbar_node_motor = 0 self.node[NoR].gnabar_node_motor = 0 elif self.model == "Gaines_sensory": for NoR in list_of_nodes: self.node[NoR].gnapbar_node_sensory = 0 self.node[NoR].gnabar_node_sensory = 0 # insert channel specific mechanisms # Nav1.1 models fast sodium # Nav1.6 models persistant sodium, to be confirmed, Warning gnabar is different than MRG and Gaines for NoR in list_of_nodes: # insert Nav1.1 model self.node[NoR].insert("na11a") self.node[NoR].gbar_na11a = 11.9 # insert Nav1.6 model self.node[NoR].insert("na16a") self.node[NoR].gbar_na16a = 0.01 ## WARINING - Sodium Nernst potential is defined for axnode as ena_axnode, and is common ## for fast and persistant sodium channels (see lines 98 and 99 in AXNOE.mod) ## This is not the case for Nav1.x, which uses the NEURON instruction USEION na READ ena ## meaning the following line is tuning directly the na11a and na16a mechanisms self.node[NoR].ena = 50 self.Markov_Nav_modeled_NoR = list_of_nodes
def __set_Nseg(self): """ Set the number of segments automatically acording initialization. For internal use only. """ if type(self.Nseg_per_sec) is dict: for n in self.node: n.nseg = self.Nseg_per_sec["node"] for m in self.MYSA: m.nseg = self.Nseg_per_sec["MYSA"] for f in self.FLUT: f.nseg = self.Nseg_per_sec["FLUT"] for s in self.STIN: s.nseg = self.Nseg_per_sec["STIN"] self.node_Nseg = self.axonnodes * self.Nseg_per_sec["node"] self.MYSA_Nseg = self.paranodes1 * self.Nseg_per_sec["MYSA"] self.FLUT_Nseg = self.paranodes2 * self.Nseg_per_sec["FLUT"] self.STIN_Nseg = self.axoninter * self.Nseg_per_sec["STIN"] elif self.Nseg_per_sec != 0: # all sections will have a fixed number of segment chosen by user for n in self.node: n.nseg = self.Nseg_per_sec for m in self.MYSA: m.nseg = self.Nseg_per_sec for f in self.FLUT: f.nseg = self.Nseg_per_sec for s in self.STIN: s.nseg = self.Nseg_per_sec self.node_Nseg = self.axonnodes * self.Nseg_per_sec self.MYSA_Nseg = self.paranodes1 * self.Nseg_per_sec self.FLUT_Nseg = self.paranodes2 * self.Nseg_per_sec self.STIN_Nseg = self.axoninter * self.Nseg_per_sec else: # here comes the dlambda rule self.node_Nseg = 0 self.MYSA_Nseg = 0 self.FLUT_Nseg = 0 self.STIN_Nseg = 0 if self.freq_min == 0: # uniform meshing for n in self.node: Nseg = d_lambda_rule(n.L, self.d_lambda, self.freq, n) n.nseg = Nseg self.node_Nseg += Nseg for m in self.MYSA: Nseg = d_lambda_rule(m.L, self.d_lambda, self.freq, m) m.nseg = Nseg self.MYSA_Nseg += Nseg for f in self.FLUT: Nseg = d_lambda_rule(f.L, self.d_lambda, self.freq, f) f.nseg = Nseg self.FLUT_Nseg += Nseg for s in self.STIN: Nseg = d_lambda_rule(s.L, self.d_lambda, self.freq, s) s.nseg = Nseg self.STIN_Nseg += Nseg else: # non-uniform meshing freqs = create_Nseg_freq_shape( self.Nsec, self.mesh_shape, self.freq, self.freq_min, self.alpha_max ) for k in range(len(self.axon_path_type)): sec_type = self.axon_path_type[k] sec_index = self.axon_path_index[k] if sec_type == "node": Nseg = d_lambda_rule( self.node[sec_index].L, self.d_lambda, freqs[k], self.node[sec_index], ) self.node[sec_index].nseg = Nseg self.node_Nseg += Nseg elif sec_type == "MYSA": Nseg = d_lambda_rule( self.MYSA[sec_index].L, self.d_lambda, freqs[k], self.MYSA[sec_index], ) self.MYSA[sec_index].nseg = Nseg self.MYSA_Nseg += Nseg elif sec_type == "FLUT": Nseg = d_lambda_rule( self.FLUT[sec_index].L, self.d_lambda, freqs[k], self.FLUT[sec_index], ) self.FLUT[sec_index].nseg = Nseg self.FLUT_Nseg += Nseg else: # should be STIN Nseg = d_lambda_rule( self.STIN[sec_index].L, self.d_lambda, freqs[k], self.STIN[sec_index], ) self.STIN[sec_index].nseg = Nseg self.STIN_Nseg += Nseg self.Nseg = self.node_Nseg + self.MYSA_Nseg + self.FLUT_Nseg + self.STIN_Nseg def __get_seg_positions(self): """ Get segment positions, for internal use only. """ x_offset = 0 x = [] x_nodes = [] nodes_index = [] self.rec_position_list = [] # print(self.axon_path_type) for k in range(len(self.axon_path_type)): sec_type = self.axon_path_type[k] sec_index = self.axon_path_index[k] self.rec_position_list.append([]) if sec_type == "node": x_nodes.append(x_offset + self.node[sec_index].L / 2) for seg in self.node[sec_index].allseg(): if is_empty_iterable(x): x.append(seg.x * (self.node[sec_index].L) + x_offset) nodes_index.append(0) self.rec_position_list[-1].append(seg.x) else: x_seg = seg.x * (self.node[sec_index].L) + x_offset if x_seg != x[-1]: x.append(x_seg) nodes_index.append(len(x) - 1) self.rec_position_list[-1].append(seg.x) x_offset += self.node[sec_index].L elif sec_type == "MYSA": for seg in self.MYSA[sec_index].allseg(): if is_empty_iterable(x): x.append(seg.x * (self.MYSA[sec_index].L) + x_offset) self.rec_position_list[-1].append(seg.x) else: x_seg = seg.x * (self.MYSA[sec_index].L) + x_offset if x_seg != x[-1]: x.append(x_seg) self.rec_position_list[-1].append(seg.x) x_offset += self.MYSA[sec_index].L elif sec_type == "FLUT": for seg in self.FLUT[sec_index].allseg(): if is_empty_iterable(x): x.append(seg.x * (self.FLUT[sec_index].L) + x_offset) self.rec_position_list[-1].append(seg.x) else: x_seg = seg.x * (self.FLUT[sec_index].L) + x_offset if x_seg != x[-1]: x.append(x_seg) self.rec_position_list[-1].append(seg.x) x_offset += self.FLUT[sec_index].L else: # should be STIN for seg in self.STIN[sec_index].allseg(): if is_empty_iterable(x): x.append(seg.x * (self.STIN[sec_index].L) + x_offset) self.rec_position_list[-1].append(seg.x) else: x_seg = seg.x * (self.STIN[sec_index].L) + x_offset if x_seg != x[-1]: x.append(x_seg) self.rec_position_list[-1].append(seg.x) x_offset += self.STIN[sec_index].L self.x = np.asarray(x) self.x_nodes = np.asarray(x_nodes) # self.node_index = np.asarray(nodes_index) self.node_index = [ nearest_idx(self.x, x_n) for x_n in x_nodes ] # LR: to avoid duplicates in node_index calculated previously... def __get_rec_positions(self): """ Get the position of points with voltage recording. For internal use only. """ if self.rec == "nodes": self.x_rec = self.x_nodes else: self.x_rec = self.x ############################### ## Intracellular stimulation ## ###############################
[docs] def insert_I_Clamp_node(self, index, t_start, duration, amplitude): """ Insert a IC clamp stimulation on a Ranvier node at its midd point position Parameters ---------- index : int node number of the node to stimulate t_start : float starting time (ms) duration : float duration of the pulse(ms) amplitude : float amplitude of the pulse (nA) """ # add the stimulation to the axon self.intra_current_stim.append(neuron.h.IClamp(0.5, sec=self.node[index])) # modify the stimulation parameters self.intra_current_stim[-1].delay = t_start self.intra_current_stim[-1].dur = duration self.intra_current_stim[-1].amp = amplitude # save the stimulation parameter for results self.intra_current_stim_positions.append(self.x_nodes[index]) self.intra_current_stim_starts.append(t_start) self.intra_current_stim_durations.append(duration) self.intra_current_stim_amplitudes.append(amplitude)
[docs] def insert_I_Clamp(self, position, t_start, duration, amplitude): """ Insert a IC clamp stimulation at the midd point of the nearest node to the specified position Parameters ---------- position : float relative position over the axon t_start : float starting time (ms) duration : duration of the pulse(ms) amplitude : amplitude of the pulse (nA) """ # adapt position to the number of sections index = round((position * (self.axonnodes - 1) + 0.5)) self.insert_I_Clamp_node(index, t_start, duration, amplitude)
[docs] def clear_I_Clamp(self): """ Clear any I-clamp attached to the axon """ self.intra_current_stim = [] self.intra_current_stim_positions = [] self.intra_current_stim_starts = [] self.intra_current_stim_durations = [] self.intra_current_stim_amplitudes = []
[docs] def insert_V_Clamp_node(self, index, stimulus): """ Insert a V clamp stimulation Parameters ---------- index : int node number of the node to stimulate stimulus : stimulus object stimulus for the clamp, see Stimulus.py for more information """ # add the stimulation to the axon self.intra_voltage_stim = neuron.h.VClamp(0.5, sec=self.node[index]) # save the stimulation parameter for results self.intra_voltage_stim_position.append(self.x_nodes[index]) # save the stimulus for later use self.intra_voltage_stim_stimulus = stimulus # set fake duration self.intra_voltage_stim.dur[0] = 1e9
[docs] def insert_V_Clamp(self, position, stimulus): """ Insert a V clamp stimulation at the midd point of the nearest node to the specified position Parameters ---------- position : float relative position over the axon stimulus : stimulus object stimulus for the clamp, see Stimulus.py for more information """ # adapt position to the number of sections index = round((position * (self.axonnodes - 1) + 0.5)) self.insert_V_Clamp_node(index, stimulus)
[docs] def clear_V_Clamp(self): """ Clear any V-clamp attached to the axon """ self.intra_voltage_stim = None self.intra_voltage_stim_position = [] self.intra_voltage_stim_stimulus = None
############################## ## Result recording methods ## ############################## def __set_recorders_with_key( self, reclist, key=None, single_mod=True, key_node=None, key_MYSA=None, key_FLUT=None, key_STIN=None, ): """ To automate the methods set_recorder. For internal use only. Parameters ---------- reclist : neuron.h.List List in witch the reccorders should be saved key : str Name of the key which should be recorded, if None result of the recording set to [0], by default None single_mod : bool if True key will be used for all the section, else specific key will be used in each section, by default True key_node : str Name of the key which should be recorded in node, if None result of the recording set to [0], by default None key_MYSA : str Name of the key which should be recorded in MYSA, if None result of the recording set to [0], by default None key_FLUT : str Name of the key which should be recorded in FLUT, if None result of the recording set to [0], by default None key_STIN : str Name of the key which should be recorded in STIN, if None result of the recording set to [0], by default None """ if single_mod: key_node, key_MYSA, key_FLUT, key_STIN = key, key, key, key if self.rec == "nodes": # recording only on middle of all nodes for n in self.node: if key_node is not None: rec = neuron.h.Vector().record(getattr(n(0.5), key_node), sec=n) else: rec = neuron.h.Vector([0]) reclist.append(rec) else: # recording on all segments for k in range(len(self.axon_path_type)): sec_type = self.axon_path_type[k] sec_index = self.axon_path_index[k] for position in self.rec_position_list[k]: if sec_type == "node": if key_node is not None: rec = neuron.h.Vector().record( getattr(self.node[sec_index](position), key_node), sec=self.node[sec_index], ) else: rec = neuron.h.Vector([0]) reclist.append(rec) elif sec_type == "MYSA": if key_MYSA is not None: rec = neuron.h.Vector().record( getattr(self.MYSA[sec_index](position), key_MYSA), sec=self.MYSA[sec_index], ) else: rec = neuron.h.Vector([0]) reclist.append(rec) elif sec_type == "FLUT": if key_FLUT is not None: rec = neuron.h.Vector().record( getattr(self.FLUT[sec_index](position), key_FLUT), sec=self.FLUT[sec_index], ) else: rec = neuron.h.Vector([0]) reclist.append(rec) else: # should be STIN if key_STIN is not None: rec = neuron.h.Vector().record( getattr(self.STIN[sec_index](position), key_STIN), sec=self.STIN[sec_index], ) else: rec = neuron.h.Vector([0]) reclist.append(rec) def __get_recorders_from_list(self, reclist): """ Convert reclist in np.array To automate methods set_recorder. For internal use only. Parameters ---------- reclist : neuron.h.List List in witch the reccorders are saved Returns ------- val : np.array array of every recorded value for all rec point and time """ if self.rec == "nodes": dim = (self.axonnodes, self.t_len) else: dim = (len(self.x_rec), self.t_len) val = np.zeros(dim) for k in range(dim[0]): val[k, :] = np.asarray(reclist[k]) return val def __get_var_from_mod( self, key=None, single_mod=True, key_node=None, key_MYSA=None, key_FLUT=None, key_STIN=None, ): """ return a column with value in every recording point of a constant from a mod. For internal use only. """ if single_mod: key_node, key_MYSA, key_FLUT, key_STIN = key, key, key, key if self.rec == "nodes": val = np.zeros(len(self.node)) if key_node is not None: val[:] = getattr(self.node[0](0.5), key_node)[0] else: val = np.zeros((len(self.x_rec))) i = -1 for k in range(len(self.axon_path_type)): sec_type = self.axon_path_type[k] sec_index = self.axon_path_index[k] for position in self.rec_position_list[k]: i += 1 if sec_type == "node": if key_node is not None: v = getattr(self.node[sec_index](position), key_node)[0] elif sec_type == "MYSA": if key_MYSA is not None: v = getattr(self.MYSA[sec_index](position), key_MYSA)[0] elif sec_type == "FLUT": if key_FLUT is not None: v = getattr(self.FLUT[sec_index](position), key_FLUT)[0] else: # should be STIN if key_STIN is not None: v = getattr(self.STIN[sec_index](position), key_STIN)[0] if isinstance(v, float): val[i] = v else: # needed for xc, xg, xraxial (see if it can be simplify) val[i] = v[0] return val
[docs] def set_membrane_voltage_recorders(self): """ setup the membrane voltage recording. For internal use only. """ self.v_reclist = neuron.h.List() key = "_ref_v" self.__set_recorders_with_key(self.v_reclist, key)
[docs] def get_membrane_voltage(self): """ get the membrane voltage at the end of simulation. For internal use only. """ return self.__get_recorders_from_list(self.v_reclist)
[docs] def set_membrane_current_recorders(self): """ setup the membrane current recording. For internal use only. """ self.i_reclist = neuron.h.List() key = "_ref_i_membrane" self.__set_recorders_with_key(self.i_reclist, key)
[docs] def get_membrane_current(self): """ get the membrane current at the end of simulation. For internal use only. """ return self.__get_recorders_from_list(self.i_reclist)
[docs] def set_ionic_current_recorders(self): """ setup the ionic channels current recording. For internal use only. """ if self.model == "MRG": self.ina_reclist = neuron.h.List() self.__set_recorders_with_key( self.ina_reclist, single_mod=False, key_node="_ref_ina_axnode" ) self.inap_reclist = neuron.h.List() self.__set_recorders_with_key( self.inap_reclist, single_mod=False, key_node="_ref_inap_axnode" ) self.ik_reclist = neuron.h.List() self.__set_recorders_with_key( self.ik_reclist, single_mod=False, key_node="_ref_ik_axnode" ) self.il_reclist = neuron.h.List() self.__set_recorders_with_key( self.il_reclist, single_mod=False, key_node="_ref_il_axnode" ) else: # should be Gaines, motor or sensory if self.model == "Gaines_motor": key_mod = "_motor" else: key_mod = "_sensory" self.ina_reclist = neuron.h.List() self.__set_recorders_with_key( self.ina_reclist, single_mod=False, key_node="_ref_ina_node" + key_mod ) self.inap_reclist = neuron.h.List() self.__set_recorders_with_key( self.inap_reclist, single_mod=False, key_node="_ref_inap_node" + key_mod ) self.ik_reclist = neuron.h.List() self.__set_recorders_with_key( self.ik_reclist, single_mod=False, key_node="_ref_ik_node" + key_mod, key_MYSA="_ref_ik_mysa" + key_mod, key_FLUT="_ref_ik_flut" + key_mod, key_STIN="_ref_ik_stin" + key_mod, ) self.ikf_reclist = neuron.h.List() self.__set_recorders_with_key( self.ikf_reclist, single_mod=False, key_node="_ref_ikf_node" + key_mod, key_MYSA="_ref_ikf_mysa" + key_mod, key_FLUT="_ref_ikf_flut" + key_mod, key_STIN="_ref_ikf_stin" + key_mod, ) self.iq_reclist = neuron.h.List() self.__set_recorders_with_key( self.iq_reclist, single_mod=False, key_MYSA="_ref_iq_mysa" + key_mod, key_FLUT="_ref_iq_flut" + key_mod, key_STIN="_ref_iq_stin" + key_mod, ) self.il_reclist = neuron.h.List() self.__set_recorders_with_key( self.il_reclist, single_mod=False, key_node="_ref_il_node" + key_mod, key_MYSA="_ref_il_mysa" + key_mod, key_FLUT="_ref_il_flut" + key_mod, key_STIN="_ref_il_stin" + key_mod, )
[docs] def get_ionic_current(self): """ get the ionic channels currents at the end of simulation. For internal use only. """ results = [] results += [self.__get_recorders_from_list(self.ina_reclist)] results += [self.__get_recorders_from_list(self.inap_reclist)] results += [self.__get_recorders_from_list(self.ik_reclist)] if self.model == "Gaines_motor" or self.model == "Gaines_sensory": results += [self.__get_recorders_from_list(self.ikf_reclist)] results += [self.__get_recorders_from_list(self.iq_reclist)] results += [self.__get_recorders_from_list(self.il_reclist)] return results
[docs] def set_particules_values_recorders(self): """ setup the particules current recording. For internal use only. """ if self.model == "MRG": self.m_reclist = neuron.h.List() self.__set_recorders_with_key( self.m_reclist, single_mod=False, key_node="_ref_m_axnode" ) self.mp_reclist = neuron.h.List() self.__set_recorders_with_key( self.mp_reclist, single_mod=False, key_node="_ref_mp_axnode" ) self.h_reclist = neuron.h.List() self.__set_recorders_with_key( self.h_reclist, single_mod=False, key_node="_ref_h_axnode" ) self.s_reclist = neuron.h.List() self.__set_recorders_with_key( self.s_reclist, single_mod=False, key_node="_ref_s_axnode" ) else: # should be Gaines, motor or sensory if self.model == "Gaines_motor": key_mod = "_motor" else: key_mod = "_sensory" self.m_reclist = neuron.h.List() self.__set_recorders_with_key( self.m_reclist, single_mod=False, key_node="_ref_m_node" + key_mod ) self.mp_reclist = neuron.h.List() self.__set_recorders_with_key( self.mp_reclist, single_mod=False, key_node="_ref_mp_node" + key_mod ) self.h_reclist = neuron.h.List() self.__set_recorders_with_key( self.h_reclist, single_mod=False, key_node="_ref_h_node" + key_mod ) self.s_reclist = neuron.h.List() self.__set_recorders_with_key( self.s_reclist, single_mod=False, key_node="_ref_s_node" + key_mod, key_MYSA="_ref_s_mysa" + key_mod, key_FLUT="_ref_s_flut" + key_mod, key_STIN="_ref_s_stin" + key_mod, ) self.n_reclist = neuron.h.List() self.__set_recorders_with_key( self.n_reclist, single_mod=False, key_node="_ref_n_node" + key_mod, key_MYSA="_ref_n_mysa" + key_mod, key_FLUT="_ref_n_flut" + key_mod, key_STIN="_ref_n_stin" + key_mod, ) self.q_reclist = neuron.h.List() self.__set_recorders_with_key( self.q_reclist, single_mod=False, key_MYSA="_ref_q_mysa" + key_mod, key_FLUT="_ref_q_flut" + key_mod, key_STIN="_ref_q_stin" + key_mod, )
[docs] def get_particles_values(self): """ get the particules values at the end of simulation. For internal use only. """ results = [] results += [self.__get_recorders_from_list(self.m_reclist)] results += [self.__get_recorders_from_list(self.mp_reclist)] results += [self.__get_recorders_from_list(self.h_reclist)] results += [self.__get_recorders_from_list(self.s_reclist)] if self.model == "Gaines_motor" or self.model == "Gaines_sensory": results += [self.__get_recorders_from_list(self.n_reclist)] results += [self.__get_recorders_from_list(self.q_reclist)] return results
[docs] def set_conductance_recorders(self): """ setup the ionic channels conductance recording. For internal use only. """ self.gna_reclist = neuron.h.List() self.gnap_reclist = neuron.h.List() self.gk_reclist = neuron.h.List() self.gl_reclist = neuron.h.List() if self.model == "MRG": self.__set_recorders_with_key( self.gna_reclist, single_mod=False, key_node="_ref_gna_axnode" ) self.__set_recorders_with_key( self.gnap_reclist, single_mod=False, key_node="_ref_gnap_axnode" ) self.__set_recorders_with_key( self.gk_reclist, single_mod=False, key_node="_ref_gk_axnode" ) self.__set_recorders_with_key( self.gl_reclist, single_mod=False, key_node="_ref_gl_axnode" ) if not self.rec == "nodes": self.gi_reclist = neuron.h.List() self.__set_recorders_with_key( self.gi_reclist, single_mod=False, key_MYSA="_ref_g_pas", key_FLUT="_ref_g_pas", key_STIN="_ref_g_pas", ) else: # should be Gaines motor or sensory self.gkf_reclist = neuron.h.List() self.gq_reclist = neuron.h.List() if self.model == "Gaines_motor": key_mod = "_motor" else: key_mod = "_sensory" self.__set_recorders_with_key( self.gna_reclist, single_mod=False, key_node="_ref_gna_node" + key_mod, ) self.__set_recorders_with_key( self.gnap_reclist, single_mod=False, key_node="_ref_gnap_node" + key_mod, ) self.__set_recorders_with_key( self.gk_reclist, single_mod=False, key_node="_ref_gk_node" + key_mod, key_MYSA="_ref_gk_mysa" + key_mod, key_FLUT="_ref_gk_flut" + key_mod, key_STIN="_ref_gk_stin" + key_mod, ) self.__set_recorders_with_key( self.gl_reclist, single_mod=False, key_node="_ref_gl_node" + key_mod, key_MYSA="_ref_gl_mysa" + key_mod, key_FLUT="_ref_gl_flut" + key_mod, key_STIN="_ref_gl_stin" + key_mod, ) self.__set_recorders_with_key( self.gkf_reclist, single_mod=False, key_node="_ref_gkf_node" + key_mod, key_MYSA="_ref_gkf_mysa" + key_mod, key_FLUT="_ref_gkf_flut" + key_mod, key_STIN="_ref_gkf_stin" + key_mod, ) if not self.rec == "nodes": self.__set_recorders_with_key( self.gq_reclist, single_mod=False, key_MYSA="_ref_gq_mysa" + key_mod, key_FLUT="_ref_gq_flut" + key_mod, key_STIN="_ref_gq_stin" + key_mod, )
[docs] def get_ionic_conductance(self): """ get the ionic channels conductance at the end of simulation. For internal use only. """ results = [] results += [self.__get_recorders_from_list(self.gna_reclist)] results += [self.__get_recorders_from_list(self.gnap_reclist)] results += [self.__get_recorders_from_list(self.gk_reclist)] results += [self.__get_recorders_from_list(self.gl_reclist)] if self.model == "MRG": if self.rec == "nodes": results += [np.zeros((self.axonnodes, self.t_len))] else: results += [self.__get_recorders_from_list(self.gi_reclist)] else: # should be Gaines, motor or sensory results += [self.__get_recorders_from_list(self.gkf_reclist)] if self.rec == "nodes": results += [np.zeros((self.axonnodes, self.t_len))] else: results += [self.__get_recorders_from_list(self.gq_reclist)] return results
[docs] def get_membrane_conductance(self): """ get the total membrane conductance at the end of simulation. For internal use only. """ return sum(self.get_ionic_conductance())
[docs] def get_membrane_capacitance(self): """ get the membrane capacitance NB: [uF/cm^{2}] (see Neuron unit) """ return self.__get_var_from_mod("_ref_cm")
[docs] def get_myelin_conductance(self): """ get the membrane capacitance NB: [S/cm^{2}] (see Neuron unit) """ return self.__get_var_from_mod("_ref_xg")
[docs] def get_myelin_capacitance(self): """ get the membrane capacitance NB: [uF/cm^{2}] (see Neuron unit) """ return self.__get_var_from_mod("_ref_xc")
[docs] def set_Nav_recorders(self): """ setup the markov model recording. For internal use only. """ # Nav1.1 variables self.I_nav11_reclist = neuron.h.List() self.C1_nav11_reclist = neuron.h.List() self.C2_nav11_reclist = neuron.h.List() self.O1_nav11_reclist = neuron.h.List() self.O2_nav11_reclist = neuron.h.List() self.I1_nav11_reclist = neuron.h.List() self.I2_nav11_reclist = neuron.h.List() # Nav1.6 variables self.I_nav16_reclist = neuron.h.List() self.C1_nav16_reclist = neuron.h.List() self.C2_nav16_reclist = neuron.h.List() self.O1_nav16_reclist = neuron.h.List() self.O2_nav16_reclist = neuron.h.List() self.I1_nav16_reclist = neuron.h.List() self.I2_nav16_reclist = neuron.h.List() for k in self.Markov_Nav_modeled_NoR: # Nav1.1 I_nav11 = neuron.h.Vector().record( self.node[k](0.5)._ref_ina_na11a, sec=self.node[k] ) C1_nav11 = neuron.h.Vector().record( self.node[k](0.5)._ref_C1_na11a, sec=self.node[k] ) C2_nav11 = neuron.h.Vector().record( self.node[k](0.5)._ref_C2_na11a, sec=self.node[k] ) O1_nav11 = neuron.h.Vector().record( self.node[k](0.5)._ref_O1_na11a, sec=self.node[k] ) O2_nav11 = neuron.h.Vector().record( self.node[k](0.5)._ref_O2_na11a, sec=self.node[k] ) I1_nav11 = neuron.h.Vector().record( self.node[k](0.5)._ref_I1_na11a, sec=self.node[k] ) I2_nav11 = neuron.h.Vector().record( self.node[k](0.5)._ref_I2_na11a, sec=self.node[k] ) self.I_nav11_reclist.append(I_nav11) self.C1_nav11_reclist.append(C1_nav11) self.C2_nav11_reclist.append(C2_nav11) self.O1_nav11_reclist.append(O1_nav11) self.O2_nav11_reclist.append(O2_nav11) self.I1_nav11_reclist.append(I1_nav11) self.I2_nav11_reclist.append(I2_nav11) # Nav1.6 I_nav16 = neuron.h.Vector().record( self.node[k](0.5)._ref_ina_na16a, sec=self.node[k] ) C1_nav16 = neuron.h.Vector().record( self.node[k](0.5)._ref_C1_na16a, sec=self.node[k] ) C2_nav16 = neuron.h.Vector().record( self.node[k](0.5)._ref_C2_na16a, sec=self.node[k] ) O1_nav16 = neuron.h.Vector().record( self.node[k](0.5)._ref_O1_na16a, sec=self.node[k] ) O2_nav16 = neuron.h.Vector().record( self.node[k](0.5)._ref_O2_na16a, sec=self.node[k] ) I1_nav16 = neuron.h.Vector().record( self.node[k](0.5)._ref_I1_na16a, sec=self.node[k] ) I2_nav16 = neuron.h.Vector().record( self.node[k](0.5)._ref_I2_na16a, sec=self.node[k] ) self.I_nav16_reclist.append(I_nav16) self.C1_nav16_reclist.append(C1_nav16) self.C2_nav16_reclist.append(C2_nav16) self.O1_nav16_reclist.append(O1_nav16) self.O2_nav16_reclist.append(O2_nav16) self.I1_nav16_reclist.append(I1_nav16) self.I2_nav16_reclist.append(I2_nav16)
[docs] def get_Nav_values(self): """ get the markov model at the end of simulation. For internal use only. """ # Nav1.1 values I_nav11_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) C1_nav11_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) C2_nav11_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) O1_nav11_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) O2_nav11_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) I1_nav11_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) I2_nav11_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) for k in range(len(self.I_nav11_reclist)): I_nav11_ax[k, :] = np.asarray(self.I_nav11_reclist[k]) C1_nav11_ax[k, :] = np.asarray(self.C1_nav11_reclist[k]) C2_nav11_ax[k, :] = np.asarray(self.C2_nav11_reclist[k]) O1_nav11_ax[k, :] = np.asarray(self.O1_nav11_reclist[k]) O2_nav11_ax[k, :] = np.asarray(self.O2_nav11_reclist[k]) I1_nav11_ax[k, :] = np.asarray(self.I1_nav11_reclist[k]) I2_nav11_ax[k, :] = np.asarray(self.I2_nav11_reclist[k]) # Nav1.6 values I_nav16_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) C1_nav16_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) C2_nav16_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) O1_nav16_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) O2_nav16_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) I1_nav16_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) I2_nav16_ax = np.zeros((len(self.Markov_Nav_modeled_NoR), self.t_len)) for k in range(len(self.I_nav11_reclist)): I_nav16_ax[k, :] = np.asarray(self.I_nav16_reclist[k]) C1_nav16_ax[k, :] = np.asarray(self.C1_nav16_reclist[k]) C2_nav16_ax[k, :] = np.asarray(self.C2_nav16_reclist[k]) O1_nav16_ax[k, :] = np.asarray(self.O1_nav16_reclist[k]) O2_nav16_ax[k, :] = np.asarray(self.O2_nav16_reclist[k]) I1_nav16_ax[k, :] = np.asarray(self.I1_nav16_reclist[k]) I2_nav16_ax[k, :] = np.asarray(self.I2_nav16_reclist[k]) return ( I_nav11_ax, C1_nav11_ax, C2_nav11_ax, O1_nav11_ax, O2_nav11_ax, I1_nav11_ax, I2_nav11_ax, I_nav16_ax, C1_nav16_ax, C2_nav16_ax, O1_nav16_ax, O2_nav16_ax, I1_nav16_ax, I2_nav16_ax, )
# Simulate method, for output type
[docs] def simulate(self, **kwargs) -> myelinated_results: return super().simulate(**kwargs)