/* Author: Johannes Luthman
This file connects the synapses and the corresponding stimulus elements,
and then steps the simulation forward in the runSimulation() proc.
Subroutines in this file:
main: DCNrun()
setupSimulation()
runSimulation()
isItTimeToSaveTrace()
getSizeOfTraceVectors()
*/
objref oRndInh, oRndExc
objref gammaStimPC[PCtoDCNconvergence]
objref netconPC[INHTOTALSYNAPSES]
// Declare instances of the GammaStim objects for excitatory synapses
// (1 GammaStim activates 1 AMPA + 1 fNMDA + 1 sNMDA) and the corresponding
// NetCon objects (=1 each for AMPA, fNMDA, and sNMDA).
objref gammaStimExc[EXCTOTALSYNAPSES]
objref netconExc[3 * EXCTOTALSYNAPSES]
///////////////////////////////////////////////////////////////
proc DCNrun() {
load_file("DCN_recording.hoc")
setupSimulation()
runSimulation()
}
proc setupSimulation() {
// Work around the error that sets in when both tTraceStart and tTraceStop = 0
// (the latter setting is used to not record any traces).
if (tTraceStop[0] == 0) {
tTraceStart[0] = 1
}
// Set up size of recording vectors.
nRecVectElements = int(runTime/recInterval) + 2 //+1 is ok for recInterval=100us,
// but +2 is needed for recInterval=50us.
stepsPerRec = int(recInterval/dt)
// Set up a different size for the trace vectors.
if (tTraceStop[0] > 0) {
recordTraces = 1
sizeVectorOfTrace = getSizeOfTraceVectors()
} else {
recordTraces = 0
}
} // end of proc setupSimulation()
proc runSimulation() {
// Set up the excitatory synapses
oRndExc = new Random()
oRndExc.ACG(randomiserSeed)
// Add GammaStims and connect them with the synaptic mechanisms using NetCons.
// As an ARTIFICIAL_CELL, it doesn't matter where a GammaStim.mod is placed.
// For convenience, I place all the GammaStims in the soma.
for (c=0; c < EXCTOTALSYNAPSES; c+=1) {
soma gammaStimExc[c] = new GammaStim(0.5)
gammaStimExc[c].start = 0
gammaStimExc[c].noise = noiseFractionExcSyn
gammaStimExc[c].duration = runTime
gammaStimExc[c].order = gammaOrderExc
gammaStimExc[c].refractoryPeriod = refractoryPeriodExc
}
// Set up the excitatory NetCons.
ncIndex = 0
for (c=0; c < EXCTOTALSYNAPSES; c+=1) {
// Create three NetCons for each excitatory GammaStim to connect it
// to the ampa and the two nmda receptors.
netconExc[ncIndex] = new NetCon(gammaStimExc[c], ampa[c])
netconExc[ncIndex].threshold = 0 //mV
netconExc[ncIndex].weight = gAMPA
netconExc[ncIndex+1] = new NetCon(gammaStimExc[c], fnmda[c])
netconExc[ncIndex+1].threshold = 0 //mV
netconExc[ncIndex+1].weight = gfNMDA
netconExc[ncIndex+2] = new NetCon(gammaStimExc[c], snmda[c])
netconExc[ncIndex+2].threshold = 0 //mV
netconExc[ncIndex+2].weight = gsNMDA
ncIndex = ncIndex + 3
}
// Set up the inhibitory synapses
// For synapses not incorporating synaptic depression, set the max GABA
// conductance to equal what is reached for depressed synapses on
// completely regular input at the used input frequency.
if (useGABAsyndep == 0) {
// The following calculation is the same as in DCN_mechs.hoc where it's explained:
initDeprLevel = 0.08 + 0.60*exp(-2.84*inhibitoryHz) + 0.32*exp(-0.02*inhibitoryHz)
gGABA = gGABA*initDeprLevel
}
oRndInh = new Random()
oRndInh.ACG(randomiserSeed)
for (c=0; c<PCtoDCNconvergence; c+=1) {
soma gammaStimPC[c] = new GammaStim(0.5)
gammaStimPC[c].start = 0
gammaStimPC[c].noise = noiseFractionInhSyn
gammaStimPC[c].duration = runTime
gammaStimPC[c].order = gammaOrderPC
gammaStimPC[c].refractoryPeriod = refractoryPeriodPC
}
// Set up the GABA NetCons.
gsIndex = 0
counterOfNetCons = 0
for (cGABA=0; cGABA < INHTOTALSYNAPSES; cGABA=cGABA+1) {
netconPC[cGABA] = new NetCon(gammaStimPC[gsIndex], gaba[cGABA])
netconPC[cGABA].threshold = 0 //mV
netconPC[cGABA].weight = gGABA
// If we've used all synapses that fit onto one GammaStim, then start
// using the next GammaStim.
if (counterOfNetCons == (nDCNsynsPerPC-1)) {
gsIndex += 1
counterOfNetCons = 0
} else {
counterOfNetCons+=1
}
}
// All the artifical cell elements have been set up. Seed them. Calling
// .seed() affects the event streams generated by all GammaStims,
// and thus needs to be done for only one of them.
gammaStimExc[0].seed(randomiserSeed)
iRecTimeVolt = 0 //index of spike recording vectors (time and volt)
// If the user has set to record volt/current traces then setup index for that.
if (tTraceStop[0] > 0) {
iRecTrace = 0
}
// Counter for when to record variables
ndtSinceRecording = stepsPerRec
InstantiateRecObjects() // procedure in file DCN_recording.hoc
SetupOutputFiles() // procedure in file DCN_recording.hoc
t = 0
finitialize (vInit)
// Set properties of the inhibitory GammaStim elements
if (inhibitoryHz > 0) {
intervalInh = 1000 / inhibitoryHz
delayInh = oRndInh.uniform(0, intervalInh)
} else {
// No inhibitory input is to be provided - set delay so the
// first spike occurs outside of the simulation time.
intervalInh = 1e5
delayInh = runTime
}
for (c=0; c < PCtoDCNconvergence; c+=1) {
gammaStimPC[c].interval = intervalInh
}
// Set delays of the inhibitory netCons.
counterOfNetCons = 0
for (cGABA=0; cGABA < INHTOTALSYNAPSES; cGABA=cGABA+1) {
netconPC[cGABA].delay = delayInh
if (counterOfNetCons == (nDCNsynsPerPC-1)) {
if (inhibitoryHz > 0) {
delayInh = oRndInh.repick()
}
counterOfNetCons = 0
} else {
counterOfNetCons+=1
}
}
// Excitatory synaptic inputs
if (excitatoryHz > 0) {
intervalExc = 1000 / excitatoryHz
delayExc = oRndExc.uniform(0, intervalExc)
} else {
// No excitatory input is to be provided - set delay so the
// first spike occurs outside of the simulation time.
intervalExc = 1e5
delayExc = runTime
}
for (c=0; c < EXCTOTALSYNAPSES; c+=1) {
gammaStimExc[c].interval = intervalExc
}
// Set delay for this stage.
for (c=0; c < (3 * EXCTOTALSYNAPSES); c=c+3) {
if (excitatoryHz > 0) {
delayExc = oRndExc.repick()
}
netconExc[c].delay = delayExc
netconExc[c+1].delay = delayExc
netconExc[c+2].delay = delayExc
}
// Step through the simulation
while (t < runTime) {
// Write variables to vectors if the time interval since the last recording
// has been reached
if (ndtSinceRecording == stepsPerRec) {
writeToTimeAndVoltVectors() // procedure in file DCN_recording.hoc
iRecTimeVolt+=1
if (recordTraces == 1) {
if (isItTimeToSaveTrace() == 1) {
writeToTraceVectors()
iRecTrace = iRecTrace+1
}
}
ndtSinceRecording = 0
}
fadvance()
ndtSinceRecording+=1
}
// Save any recordings of traces to file (they're usually set to only a small interval
// of the whole simulation, making it more efficient to save all of it here at the end.
if (recordTraces == 1) {
writeTracesToFile() // procedure in file DCN_recording.hoc
}
writeSpikeTimesToFile()
} // end of "proc runSimulation()".
func isItTimeToSaveTrace() { local subBoolean
// Check if the current time is within the time frame set in DCN_simulation.hoc
// for recording of the traces (there's no "exit for" in hoc..)
subBoolean = 0
for (c=0; c < nStepsSaveTrace; c+=1) {
if (t>=tTraceStart[c] && t<=tTraceStop[c]) {
subBoolean = 1
}
}
return subBoolean
}
func getSizeOfTraceVectors() { local subC, subSumIndeces
// For each step of recording the full voltage/current trace/s, calculate
// how many vector indeces will be needed for it. In the following,
// +1 is to get the extra index a exactly time
// tTraceStart[subC].
subSumIndeces = 0
for (subC=0; subC < nStepsSaveTrace; subC=subC+1) {
subSumIndeces = subSumIndeces + int((tTraceStop[subC] - tTraceStart[subC]) \
/ recInterval) + 2
}
return int(subSumIndeces)
}
func getPCtoDCNdelay() { local subTemp, subMean, subSD
subMean = $1
subSD = $2
if (subSD >= 0.000001) {
subTemp = oRndInh.repick()
while (subTemp < 0) {
subTemp = oRndInh.repick()
}
} else {
subTemp = subMean
}
return subTemp
}
xpanel("Luthman et al. 2011")
xbutton("DCNrun()","DCNrun()")
xpanel()