class NeuralTractUnit(object): """ Class that implements a neural tract unit. It consists of a point process generator. """ def __init__(self, conf, pool, GammaOrder, index): """ Constructor - Inputs: + **conf**: Configuration object with the simulation parameters. + **pool**: string with the name of the Neural tract. + **index**: integer corresponding to the neural tract unit identification. """ # point process generator data ## Integer order of the Gamma distribution. self.GammaOrder = GammaOrder ## A PointProcessGenerator object, corresponding the generator of ## spikes of the neural tract unit. self.spikesGenerator = PointProcessGenerator(self.GammaOrder, index) ## List of the spikes of the neural tract unit. self.terminalSpikeTrain = self.spikesGenerator.points self.kind = "" # Build synapses ## self.SynapsesOut = [] self.transmitSpikesThroughSynapses = [] self.indicesOfSynapsesOnTarget = [] ## Integer corresponding to the neural tract unit identification. self.index = index def atualizeNeuralTractUnit(self, t, FR): """ - Inputs: + **t**: current instant, in ms. + **FR**: """ self.spikesGenerator.atualizeGenerator(t, FR) if self.terminalSpikeTrain and abs(t - self.terminalSpikeTrain[-1][0]) < 1e-3: self.transmitSpikes(t) 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])
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 = []
class NeuralTractUnit(object): ''' Class that implements a neural tract unit. It consists of a point process generator. ''' def __init__(self, conf, pool, index): ''' Constructor - Inputs: + **conf**: Configuration object with the simulation parameters. + **pool**: string with the name of the Neural tract. + **index**: integer corresponding to the neural tract unit identification. ''' ## A PointProcessGenerator object, corresponding the generator of ## spikes of the neural tract unit. self.spikesGenerator = PointProcessGenerator(index) ## List of the spikes of the neural tract unit. self.terminalSpikeTrain = self.spikesGenerator.points self.kind = '' # Build synapses ## self.SynapsesOut = [] self.transmitSpikesThroughSynapses = [] self.indicesOfSynapsesOnTarget = [] ## Integer corresponding to the neural tract unit identification. self.index = index def atualizeNeuralTractUnit(self, t, FR, GammaOrder): ''' - Inputs: + **t**: current instant, in ms. + **FR**: ''' self.spikesGenerator.atualizeGenerator(t, FR, GammaOrder) if self.terminalSpikeTrain and -1e-3 < ( t - self.terminalSpikeTrain[-1][0]) < 1e-3: self.transmitSpikes(t) 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 reset(self): self.spikesGenerator.reset() self.terminalSpikeTrain = self.spikesGenerator.points