Example #1
0
    def __init__(self, conf, pool, index, kind, muscleThickness,
                 skinThickness):
        '''
        Constructor

        - Inputs:
            + **conf**: Configuration object with the simulation parameters.

            + **pool**: string with Motor unit pool to which the motor
            unit belongs.

            + **index**: integer corresponding to the motor unit order in
            the pool, according to the Henneman's principle (size principle).

            + **kind**: string with the type of the motor unit. It can
            be *S* (slow), *FR* (fast and resistant), and
            *FF* (fast and fatigable).
        '''

        ## Configuration object with the simulation parameters.
        self.conf = conf

        ## String with the type of the motor unit. It can be
        ## *S* (slow), *FR* (fast and resistant) and
        ## *FF** (fast and fatigable).
        self.kind = kind

        self.pool = pool

        # Neural compartments
        ## The instant of the last spike of the Motor unit
        ## at the Soma compartment.
        self.tSomaSpike = float("-inf")

        NumberOfAxonNodes = int(
            conf.parameterSet('NumberAxonNodes', pool, index))

        compartmentsList = ['dendrite', 'soma']
        for i in xrange(0, NumberOfAxonNodes):
            compartmentsList.append('internode')
            compartmentsList.append('node')

        ## Integer corresponding to the motor unit order in the pool, according to the Henneman's principle (size principle).
        self.index = int(index)
        ## Dictionary of Compartment of the Motor Unit.
        self.compartment = dict()
        ## Value of the membrane potential, in mV, that is considered a spike.
        self.threshold_mV = conf.parameterSet('threshold', pool, index)

        ## Anatomical position of the neuron, in mm.
        self.position_mm = conf.parameterSet('position', pool, index)

        # EMG data
        self.MUSpatialDistribution = conf.parameterSet('MUSpatialDistribution',
                                                       pool, 0)
        if self.MUSpatialDistribution == 'random':
            radius = (muscleThickness / 2) * np.random.uniform(0.0, 1.0)
            angle = 2.0 * math.pi * np.random.uniform(0.0, 1.0)

        x = radius * math.sin(angle)
        y = radius * math.cos(angle)
        ## Anatomical coordinate of the muscle unit in a muscle section, in (mm,mm).
        self.muSectionPosition_mm = [x, y]

        ## Distance of the MU to the EMG elctrode, in mm.
        self.distance_mm = math.sqrt((x + muscleThickness / 2.0 +
                                      skinThickness)**2 + y**2)

        ## Attenuation of the MUAP amplitude, as measured in the electrode.
        self.attenuationToSkin = math.exp(-self.distance_mm /
                                          conf.EMGAttenuation_mm1)

        ## Widening of the MUAP duration, as measured in the electrode.
        self.timeWidening = 1 + conf.EMGWidening_mm1 * self.distance_mm

        ## Type of the Hermitez-Rodiguez curve. It can be 1 or 2.
        self.hrType = np.random.random_integers(1, 2)

        ## MUAP amplitude in mV.
        self.ampEMG_mV = conf.parameterSet('EMGAmplitude', pool, index)
        self.ampEMG_mV = self.ampEMG_mV * self.attenuationToSkin

        ## MUAP time constant, in ms.
        self.timeCteEMG_ms = conf.parameterSet('EMGDuration', pool, index)
        self.timeCteEMG_ms = self.timeCteEMG_ms * self.timeWidening

        for i in xrange(len(compartmentsList)):
            self.compartment[i] = Compartment(compartmentsList[i], conf, pool,
                                              index, self.kind)

        ## Number of compartments.
        self.compNumber = len(self.compartment)
        ## Vector with membrane potential,in mV, of all compartments.
        self.v_mV = np.zeros((self.compNumber), dtype=np.float64)
        ## Vector with the last instant of spike of all compartments.
        self.tSpikes = np.zeros((self.compNumber), dtype=np.float64)

        gCoupling_muS = np.zeros_like(self.v_mV, dtype='d')

        for i in xrange(len(self.compartment) - 1):
            gCoupling_muS[i] = calcGCoupling(
                float(conf.parameterSet('cytR', pool, index)),
                self.compartment[i].length_mum,
                self.compartment[i + 1].length_mum,
                self.compartment[i].diameter_mum,
                self.compartment[i + 1].diameter_mum)

        gLeak = np.zeros_like(self.v_mV, dtype='d')
        capacitance_nF = np.zeros_like(self.v_mV, dtype='d')
        EqPot = np.zeros_like(self.v_mV, dtype='d')
        IPump = np.zeros_like(self.v_mV, dtype='d')
        compLength = np.zeros_like(self.v_mV, dtype='d')

        for i in xrange(len(self.compartment)):
            capacitance_nF[i] = self.compartment[i].capacitance_nF
            gLeak[i] = self.compartment[i].gLeak_muS
            EqPot[i] = self.compartment[i].EqPot_mV
            IPump[i] = self.compartment[i].IPump_nA
            compLength[i] = self.compartment[i].length_mum
            self.v_mV[i] = self.compartment[i].EqPot_mV

        ## Vector with  the inverse of the capacitance of all compartments.
        self.capacitanceInv = 1.0 / capacitance_nF

        ## Vector with current, in nA,  of each compartment coming from other elements of the model. For example
        ## from ionic channels and synapses.
        self.iIonic = np.full_like(self.v_mV, 0.0)
        ## Vector with the current, in nA, injected in each compartment.
        self.iInjected = np.zeros_like(self.v_mV, dtype='d')
        #self.iInjected = np.array([0, 10.0])

        GC = compGCouplingMatrix(gCoupling_muS)

        GL = -np.diag(gLeak)

        ## Matrix of the conductance of the motoneuron. Multiplied by the vector self.v_mV,
        ## results in the passive currents of each compartment.
        self.G = np.float64(GC + GL)

        self.EqCurrent_nA = np.dot(-GL, EqPot) + IPump

        ## index of the soma compartment.
        self.somaIndex = compartmentsList.index('soma')

        ## index of the last compartment.
        self.lastCompIndex = self.compNumber - 1

        ## Refractory period, in ms, of the motoneuron.
        self.MNRefPer_ms = float(conf.parameterSet('MNSomaRefPer', pool,
                                                   index))

        # delay
        ## String with type of the nerve. It can be PTN (posterior tibial nerve) or CPN
        ## (common peroneal nerve).
        if pool == 'SOL' or pool == 'MG' or pool == 'LG':
            self.nerve = 'PTN'
        elif pool == 'TA':
            self.nerve = 'CPN'

        ## Distance, in m, of the stimulus position to the terminal.
        self.stimulusPositiontoTerminal = float(
            conf.parameterSet('stimDistToTerm_' + self.nerve, pool, index))
        ## AxonDelay object of the motor unit.
        if NumberOfAxonNodes == 0:
            dynamicNerveLength = 0
        else:
            dynamicNerveLength = np.sum(compLength[2:-1]) * 1e-6

        self.nerveLength = float(
            conf.parameterSet('nerveLength_' + self.nerve, pool, index))

        delayLength = self.nerveLength - dynamicNerveLength

        if self.stimulusPositiontoTerminal < delayLength:
            self.Delay = AxonDelay(conf, self.nerve, pool, delayLength,
                                   self.stimulusPositiontoTerminal, index)
            self.stimulusCompartment = 'delay'
        else:
            self.Delay = AxonDelay(conf, self.nerve, pool, delayLength, -1,
                                   index)
            self.stimulusCompartment = -1
        # Nerve stimulus function
        self.stimulusMeanFrequency_Hz = float(
            conf.parameterSet('stimFrequency_' + self.nerve, pool, 0))
        self.stimulusPulseDuration_ms = float(
            conf.parameterSet('stimPulseDuration_' + self.nerve, pool, 0))
        self.stimulusIntensity_mA = float(
            conf.parameterSet('stimIntensity_' + self.nerve, pool, 0))
        self.stimulusStart_ms = float(
            conf.parameterSet('stimStart_' + self.nerve, pool, 0))
        self.stimulusStop_ms = float(
            conf.parameterSet('stimStop_' + self.nerve, pool, 0))
        self.stimulusModulationStart_ms = float(
            conf.parameterSet('stimModulationStart_' + self.nerve, pool, 0))
        self.stimulusModulationStop_ms = float(
            conf.parameterSet('stimModulationStop_' + self.nerve, pool, 0))

        exec 'def axonStimModulation(t): return ' + conf.parameterSet(
            'stimModulation_' + self.nerve, pool, 0)

        startStep = int(np.rint(self.stimulusStart_ms / self.conf.timeStep_ms))
        self.axonStimModulation = axonStimModulation
        ## Vector with the nerve stimulus, in mA.
        self.nerveStimulus_mA = np.zeros(
            (int(np.rint(conf.simDuration_ms / conf.timeStep_ms)), 1),
            dtype=float)
        for i in xrange(len(self.nerveStimulus_mA)):
            if (i * self.conf.timeStep_ms >= self.stimulusStart_ms
                    and i * self.conf.timeStep_ms <= self.stimulusStop_ms):
                if (i * self.conf.timeStep_ms > self.stimulusModulationStart_ms
                        and i * self.conf.timeStep_ms <
                        self.stimulusModulationStop_ms):
                    stimulusFrequency_Hz = self.stimulusMeanFrequency_Hz + axonStimModulation(
                        i * self.conf.timeStep_ms)
                else:
                    stimulusFrequency_Hz = self.stimulusMeanFrequency_Hz
                if stimulusFrequency_Hz > 0:
                    stimulusPeriod_ms = 1000.0 / stimulusFrequency_Hz
                    numberOfSteps = int(
                        np.rint(stimulusPeriod_ms / self.conf.timeStep_ms))
                    if ((i - startStep) % numberOfSteps == 0):
                        self.nerveStimulus_mA[i:int(
                            np.rint(i + self.stimulusPulseDuration_ms /
                                    self.conf.timeStep_ms)
                        )] = self.stimulusIntensity_mA

        #
        ## Vector with the instants of spikes at the soma.
        self.somaSpikeTrain = []
        ## Vector with the instants of spikes at the last compartment.
        self.lastCompSpikeTrain = []
        ## Vector with the instants of spikes at the terminal.
        self.terminalSpikeTrain = []

        # contraction DataMUnumber_S = int(conf.parameterSet('MUnumber_S_' + pool, pool, 0))
        activationModel = conf.parameterSet('activationModel', pool, 0)

        ## Contraction time of the twitch muscle unit, in ms.
        self.TwitchTc_ms = conf.parameterSet('twitchTimePeak', pool, index)
        ## Amplitude of the muscle unit twitch, in N.
        self.TwitchAmp_N = conf.parameterSet('twitchPeak', pool, index)
        ## Parameter of the saturation.
        self.bSat = conf.parameterSet('bSat' + activationModel, pool, index)
        ## Twitch- tetanus relationship
        self.twTet = conf.parameterSet('twTet' + activationModel, pool, index)

        ## EMG data

        ## Build synapses

        self.SynapsesOut = []
        self.transmitSpikesThroughSynapses = []
        self.indicesOfSynapsesOnTarget = []
Example #2
0
    def __init__(self, conf, pool, muscle, index):
        '''
        Constructor

        - Inputs:
            + **conf**: Configuration object with the simulation parameters.

            + **pool**: string with Motor unit pool to which the motor
            unit belongs.

            + **muscle**: 

            + **index**: integer corresponding to the motor unit order in
            the pool, according to the Henneman's principle (size principle).
        '''

        ## Configuration object with the simulation parameters.
        self.conf = conf

        self.timeStep_ms = self.conf.timeStep_ms
        self.timeStepByTwo_ms = self.conf.timeStepByTwo_ms
        self.timeStepBySix_ms = self.conf.timeStepBySix_ms
        
        self.kind = muscle

        self.muscle = muscle
        # Neural compartments

        self.pool = pool

        NumberOfAxonNodes = int(conf.parameterSet('NumberAxonNodes', pool, index))


        compartmentsList = []
        for i in xrange(0, NumberOfAxonNodes):
              compartmentsList.append('internode')
              compartmentsList.append('node')

        ## Integer corresponding to the motor unit order in the pool, according to the Henneman's principle (size principle).
        self.index = int(index)
        ## Dictionary of Compartment of the Motor Unit.
        self.compartment = dict()

        for i in xrange(len(compartmentsList)):
            self.compartment[i] = Compartment(compartmentsList[i], conf, pool, index, self.kind)

        ## Number of compartments.
        self.compNumber = len(self.compartment)
        ## Value of the membrane potential, in mV, that is considered a spike.
        if self.compNumber:
            self.threshold_mV  = conf.parameterSet('threshold', pool + '-' + muscle, index)
        else:
            self.threshold_mV = 0
        ## Vector with membrane potential,in mV, of all compartments. 
        self.v_mV = np.zeros((self.compNumber), dtype = np.float64)
        ## Vector with the last instant of spike of all compartments. 
        self.tSpikes = np.zeros((self.compNumber), dtype = np.float64)


        gCoupling_muS = np.zeros_like(self.v_mV, dtype = 'd')
        
            
        for i in xrange(len(self.compartment)-1): 
            gCoupling_muS[i] = calcGCoupling(float(conf.parameterSet('cytR',pool, index)), 
                                             self.compartment[i].length_mum,
                                             self.compartment[i + 1].length_mum,
                                             self.compartment[i].diameter_mum,
                                             self.compartment[i + 1].diameter_mum)
        
        
        gLeak = np.zeros_like(self.v_mV, dtype = 'd')    
        capacitance_nF = np.zeros_like(self.v_mV, dtype = 'd')
        EqPot = np.zeros_like(self.v_mV, dtype = 'd')
        IPump = np.zeros_like(self.v_mV, dtype = 'd')
        compLength = np.zeros_like(self.v_mV, dtype = 'd')        
        
        for i in xrange(len(self.compartment)):                                                              
            capacitance_nF[i] = self.compartment[i].capacitance_nF
            gLeak[i] = self.compartment[i].gLeak_muS
            EqPot[i] = self.compartment[i].EqPot_mV
            IPump[i] = self.compartment[i].IPump_nA
            compLength[i] = self.compartment[i].length_mum
            self.v_mV[i] = self.compartment[i].EqPot_mV
        
        
        ## Vector with  the inverse of the capacitance of all compartments. 
        self.capacitanceInv = 1.0 / capacitance_nF

        
        ## Vector with current, in nA,  of each compartment coming from other elements of the model. For example 
        ## from ionic channels and synapses.       
        self.iIonic = np.full_like(self.v_mV, 0.0)
        ## Vector with the current, in nA, injected in each compartment.
        self.iInjected = np.zeros_like(self.v_mV, dtype = 'd')
        #self.iInjected = np.array([0, 10.0])
        
        GC = compGCouplingMatrix(gCoupling_muS)
        
        GL = -np.diag(gLeak)
        
        ## Matrix of the conductance of the motoneuron. Multiplied by the vector self.v_mV,
        ## results in the passive currents of each compartment.
        self.G = np.float64(GC + GL)

        
        

        self.EqCurrent_nA = np.dot(-GL, EqPot) + IPump 

        
        
        ## index of the last compartment.
        self.lastCompIndex = self.compNumber - 1
        
        ## Refractory period, in ms, of the motoneuron.
        self.AFRefPer_ms = float(conf.parameterSet('AFRefPer', pool, index))
        
        # delay
        ## String with type of the nerve. It can be PTN (posterior tibial nerve) or CPN
        ## (common peroneal nerve).
        if self.muscle == 'SOL' or self.muscle == 'MG' or self.muscle == 'LG':
            self.nerve = 'PTN'
        elif self.muscle == 'TA':
            self.nerve = 'CPN'

       
        ## AxonDelay object of the motor unit.
        if NumberOfAxonNodes == 0:
            dynamicNerveLength = 0
        else:
            dynamicNerveLength = np.sum(compLength[2:-1]) * 1e-6
        
        self.nerveLength = float(conf.parameterSet('nerveLength_' + self.nerve, pool, index))    

         ## Distance, in m, of the stimulus position to the terminal. 
        self.stimulusPositiontoTerminal = self.nerveLength - float(conf.parameterSet('stimDistToTerm_' + self.nerve, pool, index))   

        ##Frequency threshold of the afferent to th proprioceptor input
        self.frequencyThreshold_Hz = float(conf.parameterSet('frequencyThreshold',  
                                                             pool + '-' + muscle, index)) 
        
        delayLength =  self.nerveLength - dynamicNerveLength

        if self.stimulusPositiontoTerminal < delayLength:
            self.Delay = AxonDelay(conf, self.nerve, pool + '-' + self.muscle, delayLength, self.stimulusPositiontoTerminal, index)
            self.stimulusCompartment = 'delay'
        else:
            self.Delay = AxonDelay(conf, self.nerve, pool + '-' + self.muscle, delayLength, -1, index)
            self.stimulusCompartment = -1    
        # Nerve stimulus function    
        self.stimulusMeanFrequency_Hz = float(conf.parameterSet('stimFrequency_' + self.nerve, pool, 0))
        self.stimulusPulseDuration_ms = float(conf.parameterSet('stimPulseDuration_' + self.nerve, pool, 0))
        self.stimulusIntensity_mA = float(conf.parameterSet('stimIntensity_' + self.nerve, pool, 0))
        self.stimulusStart_ms = float(conf.parameterSet('stimStart_' + self.nerve, pool, 0))
        self.stimulusStop_ms = float(conf.parameterSet('stimStop_' + self.nerve, pool, 0))
        self.stimulusModulationStart_ms = float(conf.parameterSet('stimModulationStart_' + self.nerve, pool, 0))
        self.stimulusModulationStop_ms = float(conf.parameterSet('stimModulationStop_' + self.nerve, pool, 0))

        exec 'def axonStimModulation(t): return '   +  conf.parameterSet('stimModulation_' + self.nerve, pool, 0)
        self.axonStimModulation = axonStimModulation
        ## Vector with the nerve stimulus, in mA.
        self.nerveStimulus_mA = np.zeros((int(np.rint(conf.simDuration_ms/conf.timeStep_ms)), 1), dtype = float)
        self.createStimulus()
        # 
        ## Vector with the instants of spikes at the last compartment.
        self.lastCompSpikeTrain = []
        ## Vector with the instants of spikes at the terminal.
        self.terminalSpikeTrain = []
        
        self.GammaOrder = int(conf.parameterSet('GammaOrder_' + self.pool + '-' + self.muscle, pool, 0))
        ## A PointProcessGenerator object, corresponding the generator of
        ## spikes of the neural tract unit.   
        self.spikesGenerator = PointProcessGenerator(index) 
        self.proprioceptorSpikeTrain = self.spikesGenerator.points 
        
        ## Build synapses       
         
        self.SynapsesOut = []
        self.transmitSpikesThroughSynapses = []
        self.indicesOfSynapsesOnTarget = []
Example #3
0
class AfferentUnit(object):
    '''
    Class that implements a motor unit model. Encompasses a motoneuron
    and a muscle unit.
    '''

    def __init__(self, conf, pool, muscle, index):
        '''
        Constructor

        - Inputs:
            + **conf**: Configuration object with the simulation parameters.

            + **pool**: string with Motor unit pool to which the motor
            unit belongs.

            + **muscle**: 

            + **index**: integer corresponding to the motor unit order in
            the pool, according to the Henneman's principle (size principle).
        '''

        ## Configuration object with the simulation parameters.
        self.conf = conf

        self.timeStep_ms = self.conf.timeStep_ms
        self.timeStepByTwo_ms = self.conf.timeStepByTwo_ms
        self.timeStepBySix_ms = self.conf.timeStepBySix_ms
        
        self.kind = muscle

        self.muscle = muscle
        # Neural compartments

        self.pool = pool

        NumberOfAxonNodes = int(conf.parameterSet('NumberAxonNodes', pool, index))


        compartmentsList = []
        for i in xrange(0, NumberOfAxonNodes):
              compartmentsList.append('internode')
              compartmentsList.append('node')

        ## Integer corresponding to the motor unit order in the pool, according to the Henneman's principle (size principle).
        self.index = int(index)
        ## Dictionary of Compartment of the Motor Unit.
        self.compartment = dict()

        for i in xrange(len(compartmentsList)):
            self.compartment[i] = Compartment(compartmentsList[i], conf, pool, index, self.kind)

        ## Number of compartments.
        self.compNumber = len(self.compartment)
        ## Value of the membrane potential, in mV, that is considered a spike.
        if self.compNumber:
            self.threshold_mV  = conf.parameterSet('threshold', pool + '-' + muscle, index)
        else:
            self.threshold_mV = 0
        ## Vector with membrane potential,in mV, of all compartments. 
        self.v_mV = np.zeros((self.compNumber), dtype = np.float64)
        ## Vector with the last instant of spike of all compartments. 
        self.tSpikes = np.zeros((self.compNumber), dtype = np.float64)


        gCoupling_muS = np.zeros_like(self.v_mV, dtype = 'd')
        
            
        for i in xrange(len(self.compartment)-1): 
            gCoupling_muS[i] = calcGCoupling(float(conf.parameterSet('cytR',pool, index)), 
                                             self.compartment[i].length_mum,
                                             self.compartment[i + 1].length_mum,
                                             self.compartment[i].diameter_mum,
                                             self.compartment[i + 1].diameter_mum)
        
        
        gLeak = np.zeros_like(self.v_mV, dtype = 'd')    
        capacitance_nF = np.zeros_like(self.v_mV, dtype = 'd')
        EqPot = np.zeros_like(self.v_mV, dtype = 'd')
        IPump = np.zeros_like(self.v_mV, dtype = 'd')
        compLength = np.zeros_like(self.v_mV, dtype = 'd')        
        
        for i in xrange(len(self.compartment)):                                                              
            capacitance_nF[i] = self.compartment[i].capacitance_nF
            gLeak[i] = self.compartment[i].gLeak_muS
            EqPot[i] = self.compartment[i].EqPot_mV
            IPump[i] = self.compartment[i].IPump_nA
            compLength[i] = self.compartment[i].length_mum
            self.v_mV[i] = self.compartment[i].EqPot_mV
        
        
        ## Vector with  the inverse of the capacitance of all compartments. 
        self.capacitanceInv = 1.0 / capacitance_nF

        
        ## Vector with current, in nA,  of each compartment coming from other elements of the model. For example 
        ## from ionic channels and synapses.       
        self.iIonic = np.full_like(self.v_mV, 0.0)
        ## Vector with the current, in nA, injected in each compartment.
        self.iInjected = np.zeros_like(self.v_mV, dtype = 'd')
        #self.iInjected = np.array([0, 10.0])
        
        GC = compGCouplingMatrix(gCoupling_muS)
        
        GL = -np.diag(gLeak)
        
        ## Matrix of the conductance of the motoneuron. Multiplied by the vector self.v_mV,
        ## results in the passive currents of each compartment.
        self.G = np.float64(GC + GL)

        
        

        self.EqCurrent_nA = np.dot(-GL, EqPot) + IPump 

        
        
        ## index of the last compartment.
        self.lastCompIndex = self.compNumber - 1
        
        ## Refractory period, in ms, of the motoneuron.
        self.AFRefPer_ms = float(conf.parameterSet('AFRefPer', pool, index))
        
        # delay
        ## String with type of the nerve. It can be PTN (posterior tibial nerve) or CPN
        ## (common peroneal nerve).
        if self.muscle == 'SOL' or self.muscle == 'MG' or self.muscle == 'LG':
            self.nerve = 'PTN'
        elif self.muscle == 'TA':
            self.nerve = 'CPN'

       
        ## AxonDelay object of the motor unit.
        if NumberOfAxonNodes == 0:
            dynamicNerveLength = 0
        else:
            dynamicNerveLength = np.sum(compLength[2:-1]) * 1e-6
        
        self.nerveLength = float(conf.parameterSet('nerveLength_' + self.nerve, pool, index))    

         ## Distance, in m, of the stimulus position to the terminal. 
        self.stimulusPositiontoTerminal = self.nerveLength - float(conf.parameterSet('stimDistToTerm_' + self.nerve, pool, index))   

        ##Frequency threshold of the afferent to th proprioceptor input
        self.frequencyThreshold_Hz = float(conf.parameterSet('frequencyThreshold',  
                                                             pool + '-' + muscle, index)) 
        
        delayLength =  self.nerveLength - dynamicNerveLength

        if self.stimulusPositiontoTerminal < delayLength:
            self.Delay = AxonDelay(conf, self.nerve, pool + '-' + self.muscle, delayLength, self.stimulusPositiontoTerminal, index)
            self.stimulusCompartment = 'delay'
        else:
            self.Delay = AxonDelay(conf, self.nerve, pool + '-' + self.muscle, delayLength, -1, index)
            self.stimulusCompartment = -1    
        # Nerve stimulus function    
        self.stimulusMeanFrequency_Hz = float(conf.parameterSet('stimFrequency_' + self.nerve, pool, 0))
        self.stimulusPulseDuration_ms = float(conf.parameterSet('stimPulseDuration_' + self.nerve, pool, 0))
        self.stimulusIntensity_mA = float(conf.parameterSet('stimIntensity_' + self.nerve, pool, 0))
        self.stimulusStart_ms = float(conf.parameterSet('stimStart_' + self.nerve, pool, 0))
        self.stimulusStop_ms = float(conf.parameterSet('stimStop_' + self.nerve, pool, 0))
        self.stimulusModulationStart_ms = float(conf.parameterSet('stimModulationStart_' + self.nerve, pool, 0))
        self.stimulusModulationStop_ms = float(conf.parameterSet('stimModulationStop_' + self.nerve, pool, 0))

        exec 'def axonStimModulation(t): return '   +  conf.parameterSet('stimModulation_' + self.nerve, pool, 0)
        self.axonStimModulation = axonStimModulation
        ## Vector with the nerve stimulus, in mA.
        self.nerveStimulus_mA = np.zeros((int(np.rint(conf.simDuration_ms/conf.timeStep_ms)), 1), dtype = float)
        self.createStimulus()
        # 
        ## Vector with the instants of spikes at the last compartment.
        self.lastCompSpikeTrain = []
        ## Vector with the instants of spikes at the terminal.
        self.terminalSpikeTrain = []
        
        self.GammaOrder = int(conf.parameterSet('GammaOrder_' + self.pool + '-' + self.muscle, pool, 0))
        ## A PointProcessGenerator object, corresponding the generator of
        ## spikes of the neural tract unit.   
        self.spikesGenerator = PointProcessGenerator(index) 
        self.proprioceptorSpikeTrain = self.spikesGenerator.points 
        
        ## Build synapses       
         
        self.SynapsesOut = []
        self.transmitSpikesThroughSynapses = []
        self.indicesOfSynapsesOnTarget = []

         
    
    def atualizeAfferentUnit(self, t, proprioceptorFR):
        '''
        Atualize the dynamical and nondynamical (delay) parts of the motor unit.

        - Inputs:
            + **t**: current instant, in ms.

            + **proprioceptorFR**: proprioceptor firing rate, in Hz.
        ''' 

        self.spikesGenerator.atualizeGenerator(t, proprioceptorFR, self.GammaOrder)
        if self.proprioceptorSpikeTrain and -1e-3 < (t - self.proprioceptorSpikeTrain[-1][0]) < 1e-3:
            self.Delay.addSpinalSpike(t)
        if self.compNumber: 
            self.atualizeCompartments(t)
        self.atualizeDelay(t)

    #@profile    
    def atualizeCompartments(self, t):
        '''
        Atualize all neural compartments.

        - Inputs:
            + **t**: current instant, in ms.

        '''
        
        np.clip(runge_kutta(self.dVdt, t, self.v_mV, self.timeStep_ms, self.timeStepByTwo_ms, self.conf.timeStepBySix_ms), -30.0, 120.0, self.v_mV)
        for i in xrange(self.somaIndex, self.compNumber):
            if self.v_mV[i] > self.threshold_mV and t-self.tSpikes[i] > self.MNRefPer_ms: 
                self.addCompartmentSpike(t, i)    
     
    #@profile   
    def dVdt(self, t, V): 
        '''
        Compute the potential derivative of all compartments of the motor unit.

        - Inputs:
            + **t**: current instant, in ms.

            + **V**: Vector with the current potential value of all neural
            compartments of the motor unit.
        
        \f{equation}{
            \frac{dV}{dt} = (I_{active} + GV+ I_{inj} + I_{eq})C_inv   
        }
        where all the variables are vectors with the number of elements equal
        to the number of compartments and \f$G\f$ is the conductance matrix built
        in the compGCouplingMatrix function.
        '''
        
        for i in xrange(self.compNumber): 
            self.iIonic.itemset(i, self.compartment[i].computeCurrent(t, V.item(i)))

              
        return (self.iIonic + self.G.dot(V)  + self.iInjected + self.EqCurrent_nA) * self.capacitanceInv
    
    #@profile
    def addCompartmentSpike(self, t, comp):
        '''
        When the soma potential is above the threshold a spike is added tom the soma.

        - Inputs:
            + **t**: current instant, in ms.

            + **comp**: integer with the compartment index.
        '''
        self.tSpikes[comp] = t
        if comp == self.somaIndex:
            self.somaSpikeTrain.append([t, int(self.index)])
            self.transmitSpikes(t)
        if comp == self.lastCompIndex:     
            self.lastCompSpikeTrain.append([t, int(self.index)])
            self.Delay.addSpinalSpike(t)
        
        for channel in self.compartment[comp].Channels:
            for channelState in channel.condState: channelState.changeState(t)    
              
              
    def atualizeDelay(self, t):
        '''
        Atualize the terminal spike train, by considering the Delay of the nerve.

        - Inputs:
            + **t**: current instant, in ms.
        '''

        if -1e-3 < (t - self.Delay.terminalSpikeTrain) < 1e-3: 
            self.terminalSpikeTrain.append([t, self.index])
            self.transmitSpikes(t)
        
        if self.stimulusCompartment == 'delay':
            self.Delay.atualizeStimulus(t, self.nerveStimulus_mA[int(np.rint(t/self.conf.timeStep_ms))])

    def transmitSpikes(self, t):
        '''
        - Inputs:
            + **t**: current instant, in ms.
        '''
        for i in xrange(len(self.indicesOfSynapsesOnTarget)):
            self.transmitSpikesThroughSynapses[i].receiveSpike(t, self.indicesOfSynapsesOnTarget[i])

    def createStimulus(self):
        '''
        '''
        self.stimulusMeanFrequency_Hz = float(self.conf.parameterSet('stimFrequency_' + self.nerve, self.pool, 0))
        self.stimulusPulseDuration_ms = float(self.conf.parameterSet('stimPulseDuration_' + self.nerve, self.pool, 0))
        self.stimulusIntensity_mA = float(self.conf.parameterSet('stimIntensity_' + self.nerve, self.pool, 0))
        self.stimulusStart_ms = float(self.conf.parameterSet('stimStart_' + self.nerve, self.pool, 0))
        self.stimulusStop_ms = float(self.conf.parameterSet('stimStop_' + self.nerve, self.pool, 0))
        self.stimulusModulationStart_ms = float(self.conf.parameterSet('stimModulationStart_' + self.nerve, self.pool, 0))
        self.stimulusModulationStop_ms = float(self.conf.parameterSet('stimModulationStop_' + self.nerve, self.pool, 0))

        
        
        ## Vector with the nerve stimulus, in mA.
        self.nerveStimulus_mA = np.zeros((int(np.rint(self.conf.simDuration_ms/self.conf.timeStep_ms)), 1), dtype = float)
        startStep = int(np.rint(self.stimulusStart_ms / self.conf.timeStep_ms))
        for i in xrange(len(self.nerveStimulus_mA)):
            if (i * self.conf.timeStep_ms >= self.stimulusStart_ms and  i * self.conf.timeStep_ms <= self.stimulusStop_ms):
                if (i * self.conf.timeStep_ms > self.stimulusModulationStart_ms and  i * self.conf.timeStep_ms < self.stimulusModulationStop_ms):
                    stimulusFrequency_Hz = self.stimulusMeanFrequency_Hz + self.axonStimModulation(i * self.conf.timeStep_ms)
                else:
                    stimulusFrequency_Hz = self.stimulusMeanFrequency_Hz
                if stimulusFrequency_Hz > 0:
                    stimulusPeriod_ms = 1000.0 / stimulusFrequency_Hz
                    numberOfSteps = int(np.rint(stimulusPeriod_ms / self.conf.timeStep_ms))
                    if ((i - startStep) % numberOfSteps == 0):
                        self.nerveStimulus_mA[i:int(np.rint(i + self.stimulusPulseDuration_ms / self.conf.timeStep_ms))] = self.stimulusIntensity_mA


    def reset(self):
        '''

        '''
        self.v_mV = np.zeros((self.compNumber), dtype = np.float64)
        for i in xrange(len(self.compartment)):                                                              
            self.v_mV[i] = self.compartment[i].EqPot_mV
        self.Delay.reset()
        self.tSpikes = np.zeros((self.compNumber), dtype = np.float64)
        self.lastCompSpikeTrain = []
        ## Vector with the instants of spikes at the terminal.
        self.terminalSpikeTrain = []
Example #4
0
    def __init__(self, conf, pool, index, kind):
        '''
        Constructor

        - Inputs:
            + **conf**: Configuration object with the simulation parameters.

cyto            + **pool**: string with Motor unit pool to which the motor
            unit belongs.

            + **index**: integer corresponding to the motor unit order in
            the pool, according to the Henneman's principle (size principle).

            + **kind**: string with the type of the motor unit. It can
            be *S* (slow), *FR* (fast and resistant), and
            *FF* (fast and fatigable).
        '''

        ## Configuration object with the simulation parameters.
        self.conf = conf

        ## String with the type of the motor unit. It can be
        ## *S* (slow), *FR* (fast and resistant) and
        ## *FF** (fast and fatigable).
        self.kind = kind
        
        # Neural compartments
        ## The instant of the last spike of the Motor unit
        ## at the Soma compartment.
        self.tSomaSpike = float("-inf")
        compartmentsList = ['dendrite', 'soma']
        ## Vector with the instants of spikes at the soma.
        self.somaSpikeTrain = []
        ## Integer corresponding to the motor unit order in the pool, according to the Henneman's principle (size principle).
        self.index = int(index)
        ## Vector of Compartment of the Motor Unit.
        self.compartment = []
        ## Value of the membrane potential, in mV, that is considered a spike.
        self.threshold_mV = conf.parameterSet('threshold', pool, index)
                
        ## Anatomical position of the neuron, in mm.
        self.position_mm = conf.parameterSet('position', pool, index)
        
        for i in compartmentsList: self.compartment.append(Compartment(i, conf, pool, index, self.kind))        
        
        ## Number of compartments.
        self.compNumber = len(self.compartment)
        ## Vector with membrane potential,in mV, of all compartments. 
        self.v_mV = np.zeros((self.compNumber), dtype = np.float64)
        
        
        gCoupling_MS = np.zeros_like(self.v_mV, dtype = 'd')
        gLeak = np.zeros_like(self.v_mV, dtype = 'd')        
        for i in self.compartment[0:-1]: gCoupling_MS[self.compartment.index(i)] = calcGCoupling(float(conf.parameterSet('cytR',pool, index)), 
                                                                                                 self.compartment[self.compartment.index(i)].length_mum,
                                                                                                 self.compartment[self.compartment.index(i) + 1].length_mum,
                                                                                                 self.compartment[self.compartment.index(i)].diameter_mum,
                                                                                                 self.compartment[self.compartment.index(i) + 1].diameter_mum)
        
        
        capacitance_nF = np.zeros_like(self.v_mV, dtype = 'd')  
        
        for i in self.compartment:                                                              
            capacitance_nF[self.compartment.index(i)] = i.capacitance_nF
            gLeak[self.compartment.index(i)] = i.gLeak
            

        ## Vector with  the inverse of the capacitance of all compartments. 
        self.capacitanceInv = 1 / capacitance_nF

        ## Vector with current, in nA,  of each compartment coming from other elements of the model. For example 
        ## from ionic channels and synapses.       
        self.iIonic = np.full_like(self.v_mV, 0.0)
        ## Vector with the current, in nA, injected in each compartment.
        self.iInjected = np.zeros_like(self.v_mV, dtype = 'd')
        #self.iInjected = np.array([0, 10.0])
        
        GC = compGCouplingMatrix(gCoupling_MS)
        
        GL = -np.diag(gLeak)
        
        ## Matrix of the conductance of the motoneuron. Multiplied by the vector self.v_mV,
        ## results in the passive currents of each compartment.
        self.G = np.float64(GC + GL)


        ## index of the soma compartment.
        self.somaIndex = compartmentsList.index('soma')
        
        ## Refractory period, in ms, of the motoneuron.
        self.MNRefPer_ms = float(conf.parameterSet('MNSomaRefPer', pool, index))
        
        # delay
        ## String with type of the nerve. It can be PTN (posterior tibial nerve) or CPN
        ## (common peroneal nerve).
        if (pool == 'SOL' or pool == 'MG' or pool == 'LG'):
            self.nerve = 'PTN'
        else:
            self.nerve = 'CPN'
            
        ## AxonDelay object of the motor unit.
        self.Delay = AxonDelay(conf, self.nerve, pool, index)


        ## Vector with the instants of spikes at the terminal.
        self.terminalSpikeTrain = []
                
        
        # contraction DataMUnumber_S = int(conf.parameterSet('MUnumber_S_' + pool, pool, 0))
        activationModel = conf.parameterSet('activationModel', pool, 0)
        
        ## Contraction time of the twitch muscle unit, in ms.
        self.TwitchTc_ms = conf.parameterSet('twitchTimePeak', pool, index)
        ## Amplitude of the muscle unit twitch, in N.
        self.TwitchAmp_N = conf.parameterSet('twitchPeak', pool, index)
        ## Parameter of the saturation.
        self.bSat = conf.parameterSet('bSat'+ activationModel,pool,index)
        ## Twitch- tetanus relationship
        self.twTet = conf.parameterSet('twTet' + activationModel,pool,index)
        
        ## EMG data
        
        ## Build synapses       
         
        self.SynapsesOut = []
        self.transmitSpikesThroughSynapses = []
        self.indicesOfSynapsesOnTarget = []
Example #5
0
class MotorUnit(object):
    '''
    Class that implements a motor unit model. Encompasses a motoneuron
    and a muscle unit.
    '''

    def __init__(self, conf, pool, index, kind):
        '''
        Constructor

        - Inputs:
            + **conf**: Configuration object with the simulation parameters.

cyto            + **pool**: string with Motor unit pool to which the motor
            unit belongs.

            + **index**: integer corresponding to the motor unit order in
            the pool, according to the Henneman's principle (size principle).

            + **kind**: string with the type of the motor unit. It can
            be *S* (slow), *FR* (fast and resistant), and
            *FF* (fast and fatigable).
        '''

        ## Configuration object with the simulation parameters.
        self.conf = conf

        ## String with the type of the motor unit. It can be
        ## *S* (slow), *FR* (fast and resistant) and
        ## *FF** (fast and fatigable).
        self.kind = kind
        
        # Neural compartments
        ## The instant of the last spike of the Motor unit
        ## at the Soma compartment.
        self.tSomaSpike = float("-inf")
        compartmentsList = ['dendrite', 'soma']
        ## Vector with the instants of spikes at the soma.
        self.somaSpikeTrain = []
        ## Integer corresponding to the motor unit order in the pool, according to the Henneman's principle (size principle).
        self.index = int(index)
        ## Vector of Compartment of the Motor Unit.
        self.compartment = []
        ## Value of the membrane potential, in mV, that is considered a spike.
        self.threshold_mV = conf.parameterSet('threshold', pool, index)
                
        ## Anatomical position of the neuron, in mm.
        self.position_mm = conf.parameterSet('position', pool, index)
        
        for i in compartmentsList: self.compartment.append(Compartment(i, conf, pool, index, self.kind))        
        
        ## Number of compartments.
        self.compNumber = len(self.compartment)
        ## Vector with membrane potential,in mV, of all compartments. 
        self.v_mV = np.zeros((self.compNumber), dtype = np.float64)
        
        
        gCoupling_MS = np.zeros_like(self.v_mV, dtype = 'd')
        gLeak = np.zeros_like(self.v_mV, dtype = 'd')        
        for i in self.compartment[0:-1]: gCoupling_MS[self.compartment.index(i)] = calcGCoupling(float(conf.parameterSet('cytR',pool, index)), 
                                                                                                 self.compartment[self.compartment.index(i)].length_mum,
                                                                                                 self.compartment[self.compartment.index(i) + 1].length_mum,
                                                                                                 self.compartment[self.compartment.index(i)].diameter_mum,
                                                                                                 self.compartment[self.compartment.index(i) + 1].diameter_mum)
        
        
        capacitance_nF = np.zeros_like(self.v_mV, dtype = 'd')  
        
        for i in self.compartment:                                                              
            capacitance_nF[self.compartment.index(i)] = i.capacitance_nF
            gLeak[self.compartment.index(i)] = i.gLeak
            

        ## Vector with  the inverse of the capacitance of all compartments. 
        self.capacitanceInv = 1 / capacitance_nF

        ## Vector with current, in nA,  of each compartment coming from other elements of the model. For example 
        ## from ionic channels and synapses.       
        self.iIonic = np.full_like(self.v_mV, 0.0)
        ## Vector with the current, in nA, injected in each compartment.
        self.iInjected = np.zeros_like(self.v_mV, dtype = 'd')
        #self.iInjected = np.array([0, 10.0])
        
        GC = compGCouplingMatrix(gCoupling_MS)
        
        GL = -np.diag(gLeak)
        
        ## Matrix of the conductance of the motoneuron. Multiplied by the vector self.v_mV,
        ## results in the passive currents of each compartment.
        self.G = np.float64(GC + GL)


        ## index of the soma compartment.
        self.somaIndex = compartmentsList.index('soma')
        
        ## Refractory period, in ms, of the motoneuron.
        self.MNRefPer_ms = float(conf.parameterSet('MNSomaRefPer', pool, index))
        
        # delay
        ## String with type of the nerve. It can be PTN (posterior tibial nerve) or CPN
        ## (common peroneal nerve).
        if (pool == 'SOL' or pool == 'MG' or pool == 'LG'):
            self.nerve = 'PTN'
        else:
            self.nerve = 'CPN'
            
        ## AxonDelay object of the motor unit.
        self.Delay = AxonDelay(conf, self.nerve, pool, index)


        ## Vector with the instants of spikes at the terminal.
        self.terminalSpikeTrain = []
                
        
        # contraction DataMUnumber_S = int(conf.parameterSet('MUnumber_S_' + pool, pool, 0))
        activationModel = conf.parameterSet('activationModel', pool, 0)
        
        ## Contraction time of the twitch muscle unit, in ms.
        self.TwitchTc_ms = conf.parameterSet('twitchTimePeak', pool, index)
        ## Amplitude of the muscle unit twitch, in N.
        self.TwitchAmp_N = conf.parameterSet('twitchPeak', pool, index)
        ## Parameter of the saturation.
        self.bSat = conf.parameterSet('bSat'+ activationModel,pool,index)
        ## Twitch- tetanus relationship
        self.twTet = conf.parameterSet('twTet' + activationModel,pool,index)
        
        ## EMG data
        
        ## Build synapses       
         
        self.SynapsesOut = []
        self.transmitSpikesThroughSynapses = []
        self.indicesOfSynapsesOnTarget = []
    
    def atualizeMotorUnit(self, t):
        '''
        Atualize the dynamical and nondynamical (delay) parts of the motor unit.

        - Inputs:
            + **t**: current instant, in ms.
        ''' 
        self.atualizeCompartments(t)
        self.atualizeDelay(t)
        
    def atualizeCompartments(self, t):
        '''
        Atualize all neural compartments.

        - Inputs:
            + **t**: current instant, in ms.

        '''
        
        np.clip(runge_kutta(self.dVdt, t, self.v_mV, self.conf.timeStep_ms, self.conf.timeStepByTwo_ms, self.conf.timeStepBySix_ms), -16.0, 120.0, self.v_mV)
        if (self.v_mV[self.somaIndex] > self.threshold_mV and t-self.tSomaSpike > self.MNRefPer_ms): self.addSomaSpike(t)    
     
       
    def dVdt(self, t, V): 
        '''
        Compute the potential derivative of all compartments of the motor unit.

        - Inputs:
            + **t**: current instant, in ms.

            + **V**: Vector with the current potential value of all neural
            compartments of the motor unit.
        
        \f{equation}{
            \frac{dV}{dt} = (I_{active} + GV+ I_{inj})C_inv   
        }
        where all the variables are vectors with the number of elements equal
        to the number of compartments and \f$G\f$ is the conductance matrix built
        in the compGCouplingMatrix function.
        '''
        for compartment in xrange(0, self.compNumber):  
            self.iIonic.itemset(compartment, self.compartment[compartment].computeCurrent(t, V.item(compartment)))
              
        return (self.iIonic + np.dot(self.G, V)  + self.iInjected) * self.capacitanceInv
    
    
    def addSomaSpike(self, t):
        '''
        When the soma potential is above the threshold a spike is added tom the soma.

        - Inputs:
            + **t**: current instant, in ms.
        '''
        self.tSomaSpike = t
        self.somaSpikeTrain.append([t, int(self.index)])
        self.Delay.addSpinalSpike(t)
        self.transmitSpikes(t)
        
        for channel in self.compartment[self.somaIndex].Channels:
            for channelState in channel.condState: channelState.changeState(t)    
              
              
    def atualizeDelay(self, t):
        '''
        Atualize the terminal spike train, by considering the Delay of the nerve.

        - Inputs:
            + **t**: current instant, in ms.
        '''
        if abs(t - self.Delay.terminalSpikeTrain) < 1e-3: 
            self.terminalSpikeTrain.append([t, self.index])

    def transmitSpikes(self, t):
        '''

        - Inputs:
            + **t**: current instant, in ms.
        '''
        for i in xrange(len(self.indicesOfSynapsesOnTarget)):
            self.transmitSpikesThroughSynapses[i].receiveSpike(t, self.indicesOfSynapsesOnTarget[i])
Example #6
0
class MotorUnit(object):
    '''
    Class that implements a motor unit model. Encompasses a motoneuron
    and a muscle unit.
    '''
    def __init__(self, conf, pool, index, kind, muscleThickness,
                 skinThickness):
        '''
        Constructor

        - Inputs:
            + **conf**: Configuration object with the simulation parameters.

            + **pool**: string with Motor unit pool to which the motor
            unit belongs.

            + **index**: integer corresponding to the motor unit order in
            the pool, according to the Henneman's principle (size principle).

            + **kind**: string with the type of the motor unit. It can
            be *S* (slow), *FR* (fast and resistant), and
            *FF* (fast and fatigable).
        '''

        ## Configuration object with the simulation parameters.
        self.conf = conf

        ## String with the type of the motor unit. It can be
        ## *S* (slow), *FR* (fast and resistant) and
        ## *FF** (fast and fatigable).
        self.kind = kind

        self.pool = pool

        # Neural compartments
        ## The instant of the last spike of the Motor unit
        ## at the Soma compartment.
        self.tSomaSpike = float("-inf")

        NumberOfAxonNodes = int(
            conf.parameterSet('NumberAxonNodes', pool, index))

        compartmentsList = ['dendrite', 'soma']
        for i in xrange(0, NumberOfAxonNodes):
            compartmentsList.append('internode')
            compartmentsList.append('node')

        ## Integer corresponding to the motor unit order in the pool, according to the Henneman's principle (size principle).
        self.index = int(index)
        ## Dictionary of Compartment of the Motor Unit.
        self.compartment = dict()
        ## Value of the membrane potential, in mV, that is considered a spike.
        self.threshold_mV = conf.parameterSet('threshold', pool, index)

        ## Anatomical position of the neuron, in mm.
        self.position_mm = conf.parameterSet('position', pool, index)

        # EMG data
        self.MUSpatialDistribution = conf.parameterSet('MUSpatialDistribution',
                                                       pool, 0)
        if self.MUSpatialDistribution == 'random':
            radius = (muscleThickness / 2) * np.random.uniform(0.0, 1.0)
            angle = 2.0 * math.pi * np.random.uniform(0.0, 1.0)

        x = radius * math.sin(angle)
        y = radius * math.cos(angle)
        ## Anatomical coordinate of the muscle unit in a muscle section, in (mm,mm).
        self.muSectionPosition_mm = [x, y]

        ## Distance of the MU to the EMG elctrode, in mm.
        self.distance_mm = math.sqrt((x + muscleThickness / 2.0 +
                                      skinThickness)**2 + y**2)

        ## Attenuation of the MUAP amplitude, as measured in the electrode.
        self.attenuationToSkin = math.exp(-self.distance_mm /
                                          conf.EMGAttenuation_mm1)

        ## Widening of the MUAP duration, as measured in the electrode.
        self.timeWidening = 1 + conf.EMGWidening_mm1 * self.distance_mm

        ## Type of the Hermitez-Rodiguez curve. It can be 1 or 2.
        self.hrType = np.random.random_integers(1, 2)

        ## MUAP amplitude in mV.
        self.ampEMG_mV = conf.parameterSet('EMGAmplitude', pool, index)
        self.ampEMG_mV = self.ampEMG_mV * self.attenuationToSkin

        ## MUAP time constant, in ms.
        self.timeCteEMG_ms = conf.parameterSet('EMGDuration', pool, index)
        self.timeCteEMG_ms = self.timeCteEMG_ms * self.timeWidening

        for i in xrange(len(compartmentsList)):
            self.compartment[i] = Compartment(compartmentsList[i], conf, pool,
                                              index, self.kind)

        ## Number of compartments.
        self.compNumber = len(self.compartment)
        ## Vector with membrane potential,in mV, of all compartments.
        self.v_mV = np.zeros((self.compNumber), dtype=np.float64)
        ## Vector with the last instant of spike of all compartments.
        self.tSpikes = np.zeros((self.compNumber), dtype=np.float64)

        gCoupling_muS = np.zeros_like(self.v_mV, dtype='d')

        for i in xrange(len(self.compartment) - 1):
            gCoupling_muS[i] = calcGCoupling(
                float(conf.parameterSet('cytR', pool, index)),
                self.compartment[i].length_mum,
                self.compartment[i + 1].length_mum,
                self.compartment[i].diameter_mum,
                self.compartment[i + 1].diameter_mum)

        gLeak = np.zeros_like(self.v_mV, dtype='d')
        capacitance_nF = np.zeros_like(self.v_mV, dtype='d')
        EqPot = np.zeros_like(self.v_mV, dtype='d')
        IPump = np.zeros_like(self.v_mV, dtype='d')
        compLength = np.zeros_like(self.v_mV, dtype='d')

        for i in xrange(len(self.compartment)):
            capacitance_nF[i] = self.compartment[i].capacitance_nF
            gLeak[i] = self.compartment[i].gLeak_muS
            EqPot[i] = self.compartment[i].EqPot_mV
            IPump[i] = self.compartment[i].IPump_nA
            compLength[i] = self.compartment[i].length_mum
            self.v_mV[i] = self.compartment[i].EqPot_mV

        ## Vector with  the inverse of the capacitance of all compartments.
        self.capacitanceInv = 1.0 / capacitance_nF

        ## Vector with current, in nA,  of each compartment coming from other elements of the model. For example
        ## from ionic channels and synapses.
        self.iIonic = np.full_like(self.v_mV, 0.0)
        ## Vector with the current, in nA, injected in each compartment.
        self.iInjected = np.zeros_like(self.v_mV, dtype='d')
        #self.iInjected = np.array([0, 10.0])

        GC = compGCouplingMatrix(gCoupling_muS)

        GL = -np.diag(gLeak)

        ## Matrix of the conductance of the motoneuron. Multiplied by the vector self.v_mV,
        ## results in the passive currents of each compartment.
        self.G = np.float64(GC + GL)

        self.EqCurrent_nA = np.dot(-GL, EqPot) + IPump

        ## index of the soma compartment.
        self.somaIndex = compartmentsList.index('soma')

        ## index of the last compartment.
        self.lastCompIndex = self.compNumber - 1

        ## Refractory period, in ms, of the motoneuron.
        self.MNRefPer_ms = float(conf.parameterSet('MNSomaRefPer', pool,
                                                   index))

        # delay
        ## String with type of the nerve. It can be PTN (posterior tibial nerve) or CPN
        ## (common peroneal nerve).
        if pool == 'SOL' or pool == 'MG' or pool == 'LG':
            self.nerve = 'PTN'
        elif pool == 'TA':
            self.nerve = 'CPN'

        ## Distance, in m, of the stimulus position to the terminal.
        self.stimulusPositiontoTerminal = float(
            conf.parameterSet('stimDistToTerm_' + self.nerve, pool, index))
        ## AxonDelay object of the motor unit.
        if NumberOfAxonNodes == 0:
            dynamicNerveLength = 0
        else:
            dynamicNerveLength = np.sum(compLength[2:-1]) * 1e-6

        self.nerveLength = float(
            conf.parameterSet('nerveLength_' + self.nerve, pool, index))

        delayLength = self.nerveLength - dynamicNerveLength

        if self.stimulusPositiontoTerminal < delayLength:
            self.Delay = AxonDelay(conf, self.nerve, pool, delayLength,
                                   self.stimulusPositiontoTerminal, index)
            self.stimulusCompartment = 'delay'
        else:
            self.Delay = AxonDelay(conf, self.nerve, pool, delayLength, -1,
                                   index)
            self.stimulusCompartment = -1
        # Nerve stimulus function
        self.stimulusMeanFrequency_Hz = float(
            conf.parameterSet('stimFrequency_' + self.nerve, pool, 0))
        self.stimulusPulseDuration_ms = float(
            conf.parameterSet('stimPulseDuration_' + self.nerve, pool, 0))
        self.stimulusIntensity_mA = float(
            conf.parameterSet('stimIntensity_' + self.nerve, pool, 0))
        self.stimulusStart_ms = float(
            conf.parameterSet('stimStart_' + self.nerve, pool, 0))
        self.stimulusStop_ms = float(
            conf.parameterSet('stimStop_' + self.nerve, pool, 0))
        self.stimulusModulationStart_ms = float(
            conf.parameterSet('stimModulationStart_' + self.nerve, pool, 0))
        self.stimulusModulationStop_ms = float(
            conf.parameterSet('stimModulationStop_' + self.nerve, pool, 0))

        exec 'def axonStimModulation(t): return ' + conf.parameterSet(
            'stimModulation_' + self.nerve, pool, 0)

        startStep = int(np.rint(self.stimulusStart_ms / self.conf.timeStep_ms))
        self.axonStimModulation = axonStimModulation
        ## Vector with the nerve stimulus, in mA.
        self.nerveStimulus_mA = np.zeros(
            (int(np.rint(conf.simDuration_ms / conf.timeStep_ms)), 1),
            dtype=float)
        for i in xrange(len(self.nerveStimulus_mA)):
            if (i * self.conf.timeStep_ms >= self.stimulusStart_ms
                    and i * self.conf.timeStep_ms <= self.stimulusStop_ms):
                if (i * self.conf.timeStep_ms > self.stimulusModulationStart_ms
                        and i * self.conf.timeStep_ms <
                        self.stimulusModulationStop_ms):
                    stimulusFrequency_Hz = self.stimulusMeanFrequency_Hz + axonStimModulation(
                        i * self.conf.timeStep_ms)
                else:
                    stimulusFrequency_Hz = self.stimulusMeanFrequency_Hz
                if stimulusFrequency_Hz > 0:
                    stimulusPeriod_ms = 1000.0 / stimulusFrequency_Hz
                    numberOfSteps = int(
                        np.rint(stimulusPeriod_ms / self.conf.timeStep_ms))
                    if ((i - startStep) % numberOfSteps == 0):
                        self.nerveStimulus_mA[i:int(
                            np.rint(i + self.stimulusPulseDuration_ms /
                                    self.conf.timeStep_ms)
                        )] = self.stimulusIntensity_mA

        #
        ## Vector with the instants of spikes at the soma.
        self.somaSpikeTrain = []
        ## Vector with the instants of spikes at the last compartment.
        self.lastCompSpikeTrain = []
        ## Vector with the instants of spikes at the terminal.
        self.terminalSpikeTrain = []

        # contraction DataMUnumber_S = int(conf.parameterSet('MUnumber_S_' + pool, pool, 0))
        activationModel = conf.parameterSet('activationModel', pool, 0)

        ## Contraction time of the twitch muscle unit, in ms.
        self.TwitchTc_ms = conf.parameterSet('twitchTimePeak', pool, index)
        ## Amplitude of the muscle unit twitch, in N.
        self.TwitchAmp_N = conf.parameterSet('twitchPeak', pool, index)
        ## Parameter of the saturation.
        self.bSat = conf.parameterSet('bSat' + activationModel, pool, index)
        ## Twitch- tetanus relationship
        self.twTet = conf.parameterSet('twTet' + activationModel, pool, index)

        ## EMG data

        ## Build synapses

        self.SynapsesOut = []
        self.transmitSpikesThroughSynapses = []
        self.indicesOfSynapsesOnTarget = []

    def atualizeMotorUnit(self, t):
        '''
        Atualize the dynamical and nondynamical (delay) parts of the motor unit.

        - Inputs:
            + **t**: current instant, in ms.
        '''
        self.atualizeCompartments(t)
        self.atualizeDelay(t)

    #@profile
    def atualizeCompartments(self, t):
        '''
        Atualize all neural compartments.

        - Inputs:
            + **t**: current instant, in ms.

        '''
        np.clip(
            runge_kutta(self.dVdt, t, self.v_mV, self.conf.timeStep_ms,
                        self.conf.timeStepByTwo_ms,
                        self.conf.timeStepBySix_ms), -30.0, 120.0, self.v_mV)
        for i in xrange(self.somaIndex, self.compNumber):
            if self.v_mV[i] > self.threshold_mV and t - self.tSpikes[
                    i] > self.MNRefPer_ms:
                self.addCompartmentSpike(t, i)

    #@profile
    def dVdt(self, t, V):
        '''
        Compute the potential derivative of all compartments of the motor unit.

        - Inputs:
            + **t**: current instant, in ms.

            + **V**: Vector with the current potential value of all neural
            compartments of the motor unit.
        
        \f{equation}{
            \frac{dV}{dt} = (I_{active} + GV+ I_{inj} + I_{eq})C_inv   
        }
        where all the variables are vectors with the number of elements equal
        to the number of compartments and \f$G\f$ is the conductance matrix built
        in the compGCouplingMatrix function.
        '''

        for i in xrange(self.compNumber):
            self.iIonic.itemset(
                i, self.compartment[i].computeCurrent(t, V.item(i)))

        return (self.iIonic + self.G.dot(V) + self.iInjected +
                self.EqCurrent_nA) * self.capacitanceInv

    #@profile
    def addCompartmentSpike(self, t, comp):
        '''
        When the soma potential is above the threshold a spike is added tom the soma.

        - Inputs:
            + **t**: current instant, in ms.

            + **comp**: integer with the compartment index.
        '''
        self.tSpikes[comp] = t
        if comp == self.somaIndex:
            self.somaSpikeTrain.append([t, int(self.index)])
            self.transmitSpikes(t)
        if comp == self.lastCompIndex:
            self.lastCompSpikeTrain.append([t, int(self.index)])
            self.Delay.addSpinalSpike(t)

        for channel in self.compartment[comp].Channels:
            for channelState in channel.condState:
                channelState.changeState(t)

    def atualizeDelay(self, t):
        '''
        Atualize the terminal spike train, by considering the Delay of the nerve.

        - Inputs:
            + **t**: current instant, in ms.
        '''

        if -1e-3 < (t - self.Delay.terminalSpikeTrain) < 1e-3:
            self.terminalSpikeTrain.append([t, self.index])

        # Check whether there is antidromic impulse reaching soma or RC
        if self.Delay.indexAntidromicSpike < len(
                self.Delay.antidromicSpikeTrain) and -1e-2 < (
                    t - self.Delay.antidromicSpikeTrain[
                        self.Delay.indexAntidromicSpike]) < 1e-2:

            # Considers only MN-RC connections
            self.transmitSpikes(t)

            # Refractory period of MN soma
            if t - self.tSpikes[self.somaIndex] > self.MNRefPer_ms:
                self.tSpikes[self.somaIndex] = t
                self.somaSpikeTrain.append([t, int(self.index)])
                self.Delay.indexAntidromicSpike += 1
                for channel in self.compartment[self.somaIndex].Channels:
                    for channelState in channel.condState:
                        channelState.changeState(t)

        if self.stimulusCompartment == 'delay':
            self.Delay.atualizeStimulus(
                t,
                self.nerveStimulus_mA[int(np.rint(t / self.conf.timeStep_ms))])

    def transmitSpikes(self, t):
        '''
        - Inputs:
            + **t**: current instant, in ms.
        '''
        for i in xrange(len(self.indicesOfSynapsesOnTarget)):
            self.transmitSpikesThroughSynapses[i].receiveSpike(
                t, self.indicesOfSynapsesOnTarget[i])

    def getEMG(self, t):
        '''

        '''
        emg = 0
        numberOfSpikesUntilt = []
        ta = 0

        if (len(self.terminalSpikeTrain) == 0):
            emg = 0
        else:
            for spike in self.terminalSpikeTrain:
                if spike[0] < t:
                    numberOfSpikesUntilt.append(spike[0])

        for spikeInstant in numberOfSpikesUntilt:
            ta = t - spikeInstant - 3 * self.timeCteEMG_ms
            if (ta <= 6 * self.timeCteEMG_ms):

                if (self.hrType == 1):
                    emg += 1.19 * self.ampEMG_mV * ta * math.exp(
                        -(ta / self.timeCteEMG_ms)**2) / self.timeCteEMG_ms
                elif (self.hrType == 2):
                    emg += 0.69 * self.ampEMG_mV * (1 - 2 * (
                        (ta / self.timeCteEMG_ms)**2)) * math.exp(
                            -(ta / self.timeCteEMG_ms)**2)

        return emg

    def createStimulus(self):
        '''

        '''
        self.stimulusMeanFrequency_Hz = float(
            self.conf.parameterSet('stimFrequency_' + self.nerve, self.pool,
                                   0))
        self.stimulusPulseDuration_ms = float(
            self.conf.parameterSet('stimPulseDuration_' + self.nerve,
                                   self.pool, 0))
        self.stimulusIntensity_mA = float(
            self.conf.parameterSet('stimIntensity_' + self.nerve, self.pool,
                                   0))
        self.stimulusStart_ms = float(
            self.conf.parameterSet('stimStart_' + self.nerve, self.pool, 0))
        self.stimulusStop_ms = float(
            self.conf.parameterSet('stimStop_' + self.nerve, self.pool, 0))
        self.stimulusModulationStart_ms = float(
            self.conf.parameterSet('stimModulationStart_' + self.nerve,
                                   self.pool, 0))
        self.stimulusModulationStop_ms = float(
            self.conf.parameterSet('stimModulationStop_' + self.nerve,
                                   self.pool, 0))

        startStep = int(np.rint(self.stimulusStart_ms / self.conf.timeStep_ms))
        for i in xrange(len(self.nerveStimulus_mA)):
            if (i * self.conf.timeStep_ms >= self.stimulusStart_ms
                    and i * self.conf.timeStep_ms <= self.stimulusStop_ms):
                if (i * self.conf.timeStep_ms > self.stimulusModulationStart_ms
                        and i * self.conf.timeStep_ms <
                        self.stimulusModulationStop_ms):
                    stimulusFrequency_Hz = self.stimulusMeanFrequency_Hz + self.axonStimModulation(
                        i * self.conf.timeStep_ms)
                else:
                    stimulusFrequency_Hz = self.stimulusMeanFrequency_Hz
                if stimulusFrequency_Hz > 0:
                    stimulusPeriod_ms = 1000.0 / stimulusFrequency_Hz
                    numberOfSteps = int(
                        np.rint(stimulusPeriod_ms / self.conf.timeStep_ms))
                    if ((i - startStep) % numberOfSteps == 0):
                        self.nerveStimulus_mA[
                            i:int(np.rint(i + 1.0 / self.conf.timeStep_ms)
                                  )] = self.stimulusIntensity_mA

    def reset(self):
        '''

        '''
        self.tSomaSpike = float("-inf")
        self.v_mV = np.zeros((self.compNumber), dtype=np.float64)
        for i in xrange(len(self.compartment)):
            self.v_mV[i] = self.compartment[i].EqPot_mV
            self.compartment[i].reset()
        self.Delay.reset()
        self.tSpikes = np.zeros((self.compNumber), dtype=np.float64)
        self.iIonic = np.full_like(self.v_mV, 0.0)
        self.iInjected = np.zeros_like(self.v_mV, dtype='d')

        self.somaSpikeTrain = []
        ## Vector with the instants of spikes at the last compartment.
        self.lastCompSpikeTrain = []
        ## Vector with the instants of spikes at the terminal.
        self.terminalSpikeTrain = []