// Author: Etay Hay 2014
// Dendritic excitability and gain control in recurrent cortical microcircuits (Hay and Segev, 2014, Cerebral Cortex)
//
// Parallel simulation code for microcircuits of L5 thick-tufted pyramidal cells (TTCs)
//====================== General files and tools =====================
{load_file("nrngui.hoc")}
//============================ general config ==========================
initialization_tstart = startsw()
strdef modelname
strdef cmd
strdef fileName
objref fileObj
fileObj = new File()
rdSeed = 1 //random seed
Nmc = 150 // number of TTCs in the microcircuit
condition = 0
// 0: spontaneous
// 1: step pulse 1.4 nA
// 2: noisy step pulse
// 3: step pulse 0.6 nA
// 4: step pulse 0.4 nA
// 5: step pulse 0.2 nA
// 6: activation of 20% of the cells
// 7: activation of 40% of the cells
// 8: activation of 60% of the cells
// 9: activation of 80% of the cells
// 10: EPSP at soma 0.8 nA
// 11: EPSP at soma 0.6 nA
// 12: step pulse 0.1 nA at soma and main bifurcation
// 13: step pulse 0.2 nA at soma and main bifurcation
// 14: step pulse 0.3 nA at soma and main bifurcation
// 15: step pulse 0.4 nA at soma and main bifurcation
// 16: step pulse 0.5 nA at soma and main bifurcation
// 17: step pulse 0.2 nA at main bifurcation
// 18: step pulse 0.4 nA at main bifurcation
// 19: step pulse 0.6 nA at main bifurcation
// 20: step pulse 0.7 nA at main bifurcation
// 21: step pulse 0.8 nA at main bifurcation
// 22: EPSP at soma 0.4 nA
// 23: EPSP at soma 0.2 nA
// 24: EPSP at soma 1 nA
// 25: spontaneous, with NMDA blocked
// 26: step pulse 1.4 nA, with NMDA blocked
// 27: step pulse 0.6 nA, with NMDA blocked
// 28: step pulse 0.4 nA, with NMDA blocked
// 29: step pulse 0.2 nA, with NMDA blocked
modelnum = 1
connectivity = 0 // 0 connected, 1 unconnected
if (modelnum==1){
modelname = "L5PCbiophys3"
}
if (modelnum==2){
modelname = "L5PCbiophys3_2"
}
if (modelnum==3){
modelname = "L5PCbiophys3_3"
}
if (modelnum==4){
modelname = "L5PCbiophys3_4"
}
if (modelnum==5){
modelname = "L5PCbiophys3_5"
}
if (modelnum==6){
modelname = "L5PCbiophys3_6"
}
if(condition==2){
noisyst = 1
} else {
noisyst = 0
}
tstart = 2000
timearound = 100 // time before and after stimulus
tstop = tstart+2*timearound
tstim = tstart+timearound
v_init = -75
rcpWeightFactor = 1.5 // the factor by which reciprocal weights are stronger than unidirectional weights
pT2Tr = 0.06 //probability of reciprocating an existing connection to another L5bPC
pT2T = 0.13 //probability of a L5bPC being connected to another L5bPC
Econ = 0.0004 //excitatory synaptic conductance
Icon = 0.001 //inhibitory synaptic conductance
NcontE = 5 // number of excitatory synaptic contacts per connection
NsynE = 10000 // number of excitatory synapses
NsynI = 2500 // number of inhibitory synapses
rateE = 0.72 // average rate of presynaptic excitatory cells
rateI = 7 // average rate of presynaptic inhibitory cells
mainBifurcation = 650
objref tempvec
tempvec = new Vector()
{tempvec.append(Nmc)}
//{tempvec.append(3)}
{Ncells2save = tempvec.min()}
//=================== creating neuron ================================
{load_file("import3d.hoc")}
strdef morphology_file
morphology_file = "cell1.asc"
sprint(cmd,"models/%s.hoc",modelname)
{load_file(cmd)}
{load_file("models/TTC.hoc")}
objref MC_TTC
objref sl //synaptic locations list
//=================== random variables ================================
objref rds1,rds2,rds3
{rds1 = new Random(1000*rdSeed)}
{rds1.uniform(0,1)} //random for microcircuit connectivity and noisyst
//=================== connectivity matrix ================================
//connectivity matrix where rows=pre, cols=post
objref conMat
conMat = new Matrix(Nmc,Nmc)
for(i=0;i<Nmc;i+=1){
conMat.x[i][i]=0
}
for(i=0;i<(Nmc-2);i+=1){
for(j=(i+1);j<Nmc;j+=1){
if (connectivity){
pcon = rds1.repick()
if (pcon<pT2Tr){
conMat.x[i][j]=rcpWeightFactor
conMat.x[j][i]=rcpWeightFactor
} else {
if (pcon<(pT2Tr + 0.5*pT2T)){
conMat.x[i][j]=1
conMat.x[j][i]=0
} else {
if (pcon<(pT2Tr + pT2T)){
conMat.x[i][j]=0
conMat.x[j][i]=1
} else {
conMat.x[i][j]=0
conMat.x[j][i]=0
}
}
}
} else {
conMat.x[i][j]=0
conMat.x[j][i]=0
}
}
}
//==================== presynaptic spike trains ====================
objref preTrainList
preTrainList = new List()
for(i=0;i<Nmc;i+=1){
{rds2 = new Random(1000*rdSeed+i)}//random for presynaptic trains
{rds3 = new Random(1000*rdSeed+i)}//random for presynaptic trains
{rds2.negexp(1/rateE)}
{rds3.negexp(1/rateI)}
{preTrainList.append(new List())}
for(i2=0;i2<(NsynE+NsynI);i2+=1){
{preTrainList.o[i].append(new Vector())}
pst=0 //presynaptic spike time
while(pst < tstop){
if (i2<NsynE) {
pst+= 1000*rds2.repick()
} else {
pst+= 1000*rds3.repick()
}
{preTrainList.o[i].o[preTrainList.o[i].count()-1].append(pst)}
}
}
}
//==================== parallel network manager initialization=========
{load_file("netparmpi.hoc")}
objref epnm
epnm = new ParallelNetManager(Nmc)
{epnm.round_robin()}
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
MC_TTC = new TTC(morphology_file)
epnm.register_cell(i,MC_TTC)
epnm.pc.gid2cell(i).initRand(1000*rdSeed+i)
epnm.pc.gid2cell(i).setnetworkparameters(rcpWeightFactor,Econ,Icon,NsynE,NsynI,NcontE)
epnm.pc.gid2cell(i).distributeSyn()
if ((condition>=25)&&(condition<=29)){
for(j=0;j<NsynE;j+=1){
epnm.pc.gid2cell(i).synlist.o[j].tau_r_NMDA = 0.00001
epnm.pc.gid2cell(i).synlist.o[j].tau_d_NMDA = 0.00002
epnm.pc.gid2cell(i).synlist.o[j].gmax = 3*epnm.pc.gid2cell(i).synlist.o[j].gmax
}
}
epnm.pc.gid2cell(i).setpretrains(preTrainList.o[i])
}
}
//========================== microcircuit connections =============================================
objref syninds
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
epnm.pc.gid2cell(i).insertMCcons(conMat.getcol(i))
}
}
syninds = new Vector()
for(i=0;i<Nmc;i+=1){
syninds.append(NsynE+NsynI)
}
// appending the microcircuit connections
for(i=0;i<Nmc;i+=1){
for(j=0;j<Nmc;j+=1){
if (conMat.x[j][i] != 0){
for(jj=0;jj<NcontE;jj+=1){
epnm.nc_append(j,i,syninds.x[i],1,0.5)
syninds.x[i] +=1
}
}
}
}
//=============================================================================
// initializing the synaptic events of the background network
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
{epnm.pc.gid2cell(i).queuePreTrains()}
}
}
//============================ current steps ==========================================
objref st1
objref stList
stList = new List()
if ((condition==1)||(condition==2)||(condition==26)){
for(i=0;i<Nmc;i+=1){
tj = 10*noisyst*rds1.repick()
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new IClamp(0.5))
stList.o[stList.count()-1].del = tstim + tj
stList.o[stList.count()-1].dur = 5
stList.o[stList.count()-1].amp = 1.4
}
}
}
if ((condition==3)||(condition==27)){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new IClamp(0.5))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
stList.o[stList.count()-1].amp = 0.6
}
}
}
if ((condition==4)||(condition==28)){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new IClamp(0.5))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
stList.o[stList.count()-1].amp = 0.4
}
}
}
if ((condition==5)||(condition==29)){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new IClamp(0.5))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
stList.o[stList.count()-1].amp = 0.2
}
}
}
if (condition==6){
for(i=0;i<Nmc*0.2;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new IClamp(0.5))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
stList.o[stList.count()-1].amp = 1.4
}
}
}
if (condition==7){
for(i=0;i<Nmc*0.4;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new IClamp(0.5))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
stList.o[stList.count()-1].amp = 1.4
}
}
}
if (condition==8){
for(i=0;i<Nmc*0.6;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new IClamp(0.5))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
stList.o[stList.count()-1].amp = 1.4
}
}
}
if (condition==9){
for(i=0;i<Nmc*0.8;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new IClamp(0.5))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
stList.o[stList.count()-1].amp = 1.4
}
}
}
if (condition==10){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new epsp(0.5))
stList.o[stList.count()-1].onset = tstim
stList.o[stList.count()-1].tau0 = 0.3
stList.o[stList.count()-1].tau1 = 5
stList.o[stList.count()-1].imax = 0.8
}
}
}
if (condition==11){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new epsp(0.5))
stList.o[stList.count()-1].onset = tstim
stList.o[stList.count()-1].tau0 = 0.3
stList.o[stList.count()-1].tau1 = 5
stList.o[stList.count()-1].imax = 0.6
}
}
}
if ((condition>=12)&&(condition<=16)){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new IClamp(0.5))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
if (condition==12){
stList.o[stList.count()-1].amp = 0.1
}
if (condition==13){
stList.o[stList.count()-1].amp = 0.2
}
if (condition==14){
stList.o[stList.count()-1].amp = 0.3
}
if (condition==15){
stList.o[stList.count()-1].amp = 0.4
}
if (condition==16){
stList.o[stList.count()-1].amp = 0.5
}
sl = epnm.pc.gid2cell(i).locateSites("apic",mainBifurcation)
maxdiam = 0
for(i1=0;i1<sl.count();i1+=1){
dd1 = sl.o[i1].x[1]
dd = epnm.pc.gid2cell(i).apic[sl.o[i1].x[0]].diam(dd1)
if (dd > maxdiam) {
j = i1
maxdiam = dd
}
}
access epnm.pc.gid2cell(i).apic[sl.o[j].x[0]]
stList.append(new IClamp(sl.o[j].x[1]))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
if (condition==12){
stList.o[stList.count()-1].amp = 0.1
}
if (condition==13){
stList.o[stList.count()-1].amp = 0.2
}
if (condition==14){
stList.o[stList.count()-1].amp = 0.3
}
if (condition==15){
stList.o[stList.count()-1].amp = 0.4
}
if (condition==16){
stList.o[stList.count()-1].amp = 0.5
}
}
}
}
if ((condition>=17)&&(condition<=21)){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
sl = epnm.pc.gid2cell(i).locateSites("apic",mainBifurcation)
maxdiam = 0
for(i1=0;i1<sl.count();i1+=1){
dd1 = sl.o[i1].x[1]
dd = epnm.pc.gid2cell(i).apic[sl.o[i1].x[0]].diam(dd1)
if (dd > maxdiam) {
j = i1
maxdiam = dd
}
}
access epnm.pc.gid2cell(i).apic[sl.o[j].x[0]]
stList.append(new IClamp(sl.o[j].x[1]))
stList.o[stList.count()-1].del = tstim
stList.o[stList.count()-1].dur = 5
if (condition==17){
stList.o[stList.count()-1].amp = 0.2
}
if (condition==18){
stList.o[stList.count()-1].amp = 0.4
}
if (condition==19){
stList.o[stList.count()-1].amp = 0.6
}
if (condition==20){
stList.o[stList.count()-1].amp = 0.7
}
if (condition==21){
stList.o[stList.count()-1].amp = 0.8
}
}
}
}
if (condition==22){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new epsp(0.5))
stList.o[stList.count()-1].onset = tstim
stList.o[stList.count()-1].tau0 = 0.3
stList.o[stList.count()-1].tau1 = 5
stList.o[stList.count()-1].imax = 0.4
}
}
}
if (condition==23){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new epsp(0.5))
stList.o[stList.count()-1].onset = tstim
stList.o[stList.count()-1].tau0 = 0.3
stList.o[stList.count()-1].tau1 = 5
stList.o[stList.count()-1].imax = 0.2
}
}
}
if (condition==24){
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
stList.append(new epsp(0.5))
stList.o[stList.count()-1].onset = tstim
stList.o[stList.count()-1].tau0 = 0.3
stList.o[stList.count()-1].tau1 = 5
stList.o[stList.count()-1].imax = 1
}
}
}
//=============================================================================
//=============================== output config files =========================
// connectivity matrix
strdef outDir
sprint(outDir,"simdata/%s/N%d_c%d_cond%d_seed%d",modelname,Nmc,connectivity,condition,rdSeed)
sprint(cmd,"system(\"mkdir -p %s\")",outDir)
execute(cmd)
if(epnm.gid_exists(0)){
sprint(fileName,"%s/conmat.txt",outDir)
fileObj.wopen(fileName)
conMat.fprint(0,fileObj)
fileObj.close()
}
//simulation parameters
if(epnm.gid_exists(0)){
sprint(fileName,"%s/simParam.txt",outDir)
fileObj.wopen(fileName)
fileObj.printf("tstop %d\n",tstop-tstart)
fileObj.printf("tstim %d\n",tstim-tstart)
fileObj.close()
}
/*
for(i=0;i<Ncells2save;i+=1){
if(epnm.gid_exists(i)){
sprint(fileName,"%s/synConductanceN%d.txt",outDir,i)
fileObj.wopen(fileName)
nsyn = epnm.pc.gid2cell(i).synlist.count()
for(j=0;j<nsyn;j+=1){
fileObj.printf("%2.6e\n",epnm.pc.gid2cell(i).synlist.o[j].gmax)
}
fileObj.close()
}
}
*/
//============================================================================
//==================== recording settings ==========================
objref vSomaList,vApicalList
objref apcvecList, apcList
apcvecList = new List()
apcList = new List()
vSomaList = new List()
vApicalList = new List()
for(i=0;i<Ncells2save;i+=1){
if (epnm.gid_exists(i)) {
vSomaList.append(new Vector())
vApicalList.append(new Vector())
sl = epnm.pc.gid2cell(i).locateSites("apic",mainBifurcation)
maxdiam = 0
for(i1=0;i1<sl.count();i1+=1){
dd1 = sl.o[i1].x[1]
dd = epnm.pc.gid2cell(i).apic[sl.o[i1].x[0]].diam(dd1)
if (dd > maxdiam) {
j = i1
maxdiam = dd
}
}
access epnm.pc.gid2cell(i).apic[sl.o[j].x[0]]
vApicalList.o[vApicalList.count()-1].record(&v(sl.o[j].x[1]),dt)
access epnm.pc.gid2cell(i).soma
vSomaList.o[vSomaList.count()-1].record(&v(0.5),dt)
}
}
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
access epnm.pc.gid2cell(i).soma
apcList.append(new APCount(0.5))
apcvecList.append(new Vector())
apcList.o[apcList.count()-1].thresh= -40
apcList.o[apcList.count()-1].record(apcvecList.o[apcList.count()-1])
}
}
//============================================================================
//================================ simulation ================================
{epnm.set_maxstep(100)}
stdinit()
if (epnm.gid_exists(0)) {
print "\n"
sim_tstart = startsw()
initializationtime = (sim_tstart-initialization_tstart)/3600
print "Initialization completed. Initialization took ", initializationtime, " hours\n"
print "Starting simulation\n"
print "\n"
}
{epnm.psolve(tstop)}
if (epnm.gid_exists(0)) {
simruntime = (startsw() - sim_tstart)/3600
print "Simulation took ", simruntime, " hours\n"
}
//============================================================================
//================================ output ====================================
i2=0
for(i=0;i<Ncells2save;i+=1){
if (epnm.gid_exists(i)) {
tempvec = new Vector()
tempvec = vSomaList.o[i2].c(tstart/dt)
sprint(fileName,"%s/vTraceN%d.txt",outDir,i)
fileObj.wopen(fileName)
tempvec.printf(fileObj,"%2.6e\n")
fileObj.close()
tempvec = new Vector()
tempvec = vApicalList.o[i2].c(tstart/dt)
sprint(fileName,"%s/vMidApicTraceN%d.txt",outDir,i)
fileObj.wopen(fileName)
tempvec.printf(fileObj,"%2.6e\n")
fileObj.close()
i2+=1
}
}
i2=0
for(i=0;i<Nmc;i+=1){
if (epnm.gid_exists(i)) {
i1 = apcvecList.o[i2].indwhere(">=",tstart)
tempvec = new Vector()
if (i1 > -1){
tempvec = apcvecList.o[i2].c(i1).sub(tstart)
}
sprint(fileName,"%s/spikeTimesN%d.txt",outDir,i)
fileObj.wopen(fileName)
tempvec.printf(fileObj,"%2.6e\n")
fileObj.close()
i2+=1
}
}
{epnm.pc.runworker()}
{epnm.pc.done()}
quit()