/* MAIN DISCRIMINATION C++ CODE To run the code: When the code is compiled, run the executable followed by a number which sets the frequencies of the two stimuli and initializes the random number generator. The last 4 digits give a number, N, which encodes the frequency, any digits before the last 4 are the initial seed to the random number generator. N/2 is the value of f1. An odd number for N equates to f2>f1, while an even number for f2 f1 and set N= 2 times f1 for f2 < f1. See netinmain.cpp. On a parallel machine use the script file which runs 14 trials in parallel, each trial with a different pair of f1,f2. The first input runs from 10 to 34 in steps of 4, corresponding to f1=10Hz to 34Hz in steps of 4Hz. f2 is set as f1+8Hz or f1-8Hz. Each neuron is a member of class CELL, (within class NET). The 5 types of cell are: EinCell[i] (i=0 to 399) the C-neurons or comparison cells in the model which receive input. EonCell[i] (i=0 to 399) the `ON' neurons which are a single bistable group, switched on but untuned during the task. ECell[i] (i=0 to 4799) the 12x400 bistable subpopulations of the memory network. ECell[i] (i=4800 to 5199) the 400 Readout cells of the memory network. ICell[i] (i=0 to 199) the 200 interneurons, which feedback the inhibition. Input files: connections_in.dat Contains the sets of weights for all connections in the network. Used by code in structure.cpp to form the complete weight-matrix. discrimnet_in.dat Contains all other inputs. First a set of single neuron parameters. Finally the set of cue times and durations for the simulation. Output files: Efiredout << goes to "Efired.dat" spike times and ISIs of selected E-neurons Ifiredout << goes to "Efired.dat" spike times and ISIs of selected I-neurons Eout[i] << goes to "Eout"i+1".dat" where i = 0 to 11 for the 12 bistable memory populations and i = 12 for the readout cells. Outputs time-binned population average firing rate. Eout[i] << goes to "Iout"i+1".dat" where i = 0 for the single interneuron population. Outputs time-binned population average firing rate. Einout << goes to "Einout.dat" Outputs average time-binned rates of C-neurons. Eonout << goes to "Eonout.dat" Outputs average time-binned rates of `ON' neurons. */ #include "MersenneTwister.h" //random number generator #include "dnet.h" extern MTRand rand1; extern MTRand rand2; void CELL::Init(Params* extpc, double vthadd=0.0, double gladd =0.0){ /* Initialization of each neuron extpc points to the values for the particular cell type (excitatory/inhibitory) */ vth = extpc->vth0 + vthadd; // voltage threshold gl = extpc->gl0 + gladd; // leak conductance /* The following section sets a random time since the last spike and an initial membrane potential accordingly, based on an assumed spontaneous rate of avrate */ double avrate = 1.0; lftime = -rand1()/avrate; if(lftime > -extpc->tref) vnow = extpc->vreset; else vnow = (vth - extpc->vreset)*(-lftime)*avrate + extpc->vreset; vold = vnow; vnew = vnow; numfired = 0; /* This section sets initial value of external noise input based one estimated time since last spike. */ double wait = -log(rand1())/extpc->rateExt; sExt = exp(-wait/extpc->tauExt); /* These variables ending in -bar are to calculate means across time */ gtildebar = 0.0; v0bar = 0.0; vshadowbar = 0.0; ISIbar = 0.0; /* pc = present cell */ pc = extpc; binrate = 0.0; Nves = extpc->N0; // number of vesicles in axon terminals for this cell type /* cellInh adds leak conductance, since the leak potential is equalt to the inhibitory reversal potential in this model. Default for parameter "vary" is zero, but when non-zero gives heterogeneity in leak conductances */ cellInh = Ran_Gaussian() * extpc->vary; } double CELL::findV(double tau, double deltat){ /* Basic temporal integration */ /* RUNGE KUTTA-4 double k1 = deltat*(-(vnow-v0)/tau); double k2 = deltat*(-(vnow+0.5*k1-v0)/tau); double k3 = deltat*(-(vnow+0.5*k2-v0)/tau); double k4 = deltat*(-(vnow+k3-v0)/tau); return vnow + k1/6.0 + k2/3.0 + k3/3.0 + k4/6.0; */ /* RUNGE KUTTA-2 */ double k1 = deltat*(-(vnow-v0)/tau); double k2 = deltat*(-(vnow+0.5*k1-v0)/tau); return vnow + k2; } double CELL::SExt(double sext,double rate,double tauext, double dt){ /* Updates the background noise input */ bool extfire = false; do if ( 1.0 - exp(-dt*rate) > rand1() ){ double delay = dt*rand1(); sext *= exp(-delay/tauext); sext +=1.0; extfire = true; dt = dt - delay; } else{ sext *= exp(-dt/tauext); extfire = false; } while (extfire == true); return sext; } void CELL::Integrate(double dt,double t){ /* Calculates currents needed for time integration of the membrane potential, then updates the membrane potential and checks if cell has fired. The shadow voltage is used (a membrane potential with no reset) as an approximation to the dendritic membrane potential used when calculating NMDA conductance */ sExt = SExt(sExt,pc->rateExt,pc->tauExt,dt); sExtI = SExt(sExtI,pc->rateExt,pc->tauExt,dt); gtilde = gl + pc->gExt*sExt + pc->gExtI*sExtI + pc->gSynE*sSynE + pc->gSynI*sSynI + pc->gApp*sApp*sAppFact; gtildebar += gtilde; v0 = (pc->vl*gl + (pc->gExtI*sExtI + pc->gSynI*sSynI)*pc->vSynI) /gtilde; v0bar += v0; tm = pc->cm / gtilde; vold = vnow; if ( t > lftime+pc->tref ){ if(t-dt >= lftime+pc->tref){ vnew = findV(tm,dt); } else{ vnew = findV(tm,t-lftime-pc->tref); } } vshadow = v0; // shadow voltage for NMDA conductance is not reset vshadowbar += vshadow; /* If threshold is crossed, calculate exact crossing time and reset for a time given by refractory period, tref */ if (vnew >= vth ){ cellfire = true; llftime = lftime; lftime = Fired(vold,vnew,t,dt); numfired++; binrate++; ISIbar += lftime-llftime; vnew = pc->vreset; if ( t-lftime > pc->tref ) { vnow = pc->vreset; vnew = findV(tm,t-lftime-pc->tref); } } vnow = vnew; } double CELL::FacDep(){ pv = 1.0; double deltat = lftime-llftime; for (int i=0; itau_f[i]); Ogate[i] = 1.0 - (1.0-Ogate[i])*pc->C_f[i]; pv *= Ogate[i]; } double p = 0.0; if ( pc->tau_d > 0.0 ) p = exp(-deltat/pc->tau_d); Nves += (pc->N0-Nves)*(1.0-p); return Nves*pv/pc->N0; } void NET::Datin(int istr1, int istr2){ /* Input all the single cell properties and simulation protocol. */ cuestrength1 = double(istr1); cuestrength2 = double(istr2); cout << " cuestrength1 " << cuestrength1 << " cuestrength2 " << cuestrength2 << endl; ifstream input; input.open("discrimnet_in.dat"); string dummy; input >> ECm >> dummy; input >> EVth >> dummy; input >> EVreset >> dummy; input >> EVl >> dummy; input >> Egl >> dummy; input >> Etref >> dummy; input >> Etaus >> dummy; input >> EtauAMPA >> dummy; input >> EgExt >> dummy; input >> EgExtI >> dummy; input >> ErateExt >> dummy; input >> EtauExt >> dummy; input >> ICm >> dummy; input >> IVth >> dummy; input >> IVreset >> dummy; input >> IVl >> dummy; input >> Igl >> dummy; input >> Itref >> dummy; input >> Itaus >> dummy; input >> IgExt >> dummy; input >> IgExtI >> dummy; input >> IrateExt >> dummy; input >> ItauExt >> dummy; input >> gEE >> dummy; input >> gEI >> dummy; input >> gIE >> dummy; input >> gII >> dummy; input >> gNMDAfact >> dummy; input >> gAMPAfact >> dummy; input >> gNMDAfactback >> dummy; input >> gAMPAfactback >> dummy; input >> gNMDAfactfwd >> dummy; input >> gAMPAfactfwd >> dummy; input >> VSynE >> dummy; input >> VSynI >> dummy; input >> Ealpha >> dummy; input >> Ialpha >> dummy; input >> dt >> dummy; input >> sigmaDistrib >> dummy; input >> Vthchange >> dummy; input >> glchange >> dummy; input >> VRshift >> dummy; input >> glRshift >> dummy; input >> Vinshift >> dummy; input >> glinshift >> dummy; input >> Vonshift >> dummy; input >> glonshift >> dummy; input >> gonApp >> dummy; input >> maxrate >> dummy; input >> bintime >> dummy; input >> rApp0 >> dummy; input >> EgApp >> dummy; input >> AppFact >> dummy; input >> range >> dummy; input >> Ethresh_shift >> dummy; input >> Ithresh_shift >> dummy; input >> Evary >> dummy; input >> Ivary >> dummy; for (int j = 0; j < Ncues; j++) input >> cuetime[j] >> dummy; cuetime[Ncues] = 999; for (int j = 0; j < Ncues; j++) input >> cuelength[j] >> dummy; cout << " inputs done " << endl; string logString = createString( "net1log",NEsub,3); logString += ".dat"; cout << logString << endl; logOut.open(logString.c_str()); logOut << " NE " << NE << endl; logOut << " NI " << NI << endl; logOut << " Nreadout " << Nreadout << endl; logOut << " ECm " << ECm << endl; logOut << " EVth " << EVth << endl; logOut << " EVreset " << EVreset << endl; logOut << " EVl " << EVl << endl; logOut << " Egl " << Egl << endl; logOut << " Etref " << Etref << endl; logOut << " Etaus " << Etaus << endl; logOut << " EtauAMPA " << EtauAMPA << endl; logOut << " EgExt " << EgExt << endl; logOut << " EgExtI " << EgExtI << endl; logOut << " ErateExt " << ErateExt << endl; logOut << " EtauExt " << EtauExt << endl; logOut << " ICm " << ICm << endl; logOut << " IVth " << IVth << endl; logOut << " IVreset " << IVreset << endl; logOut << " IVl " << IVl << endl; logOut << " Igl " << Igl << endl; logOut << " Itref " << Itref << endl; logOut << " Itaus " << Itaus << endl; logOut << " IgExt " << IgExt << endl; logOut << " IgExtI " << IgExtI << endl; logOut << " IrateExt " << IrateExt << endl; logOut << " ItauExt " << ItauExt << endl; logOut << " gEE " << gEE << endl; logOut << " gEI " << gEI << endl; logOut << " gIE " << gIE << endl; logOut << " gII " << gII << endl; logOut << " gNMDAfact " << gNMDAfact << endl; logOut << " gAMPAfact " << gAMPAfact << endl; logOut << " gNMDAfactback " << gNMDAfactback << endl; logOut << " gAMPAfactback " << gAMPAfactback << endl; logOut << " gNMDAfactfwd " << gNMDAfactfwd << endl; logOut << " gAMPAfactfwd " << gAMPAfactfwd << endl; logOut << " VSynE " << VSynE << endl; logOut << " VSynI " << VSynI << endl; logOut << " Ealpha " << Ealpha << endl; logOut << " Ialpha " << Ialpha << endl; logOut << " dt " << dt << endl; logOut << " sigmaDistrib " << sigmaDistrib << endl; logOut << " Vthchange " << Vthchange << endl; logOut << " glchange " << glchange << endl; logOut << " VRshift " << VRshift << endl; logOut << " glRshift " << glRshift << endl; logOut << " Vinshift " << Vinshift << endl; logOut << " glinshift " << glinshift << endl; logOut << " Vonshift " << Vonshift << endl; logOut << " glonshift " << glonshift << endl; logOut << " gonApp " << gonApp << endl; logOut << " maxrate " << maxrate << endl; maxfired = maxrate*float(NE+NI)*(cuetime[Ncues-1]+5.0); logOut << " maxfired " << maxfired << endl; logOut << " bintime " << bintime << endl; logOut << " Ethresh_shift " << Ethresh_shift << endl; logOut << " Ithresh_shift " << Ithresh_shift << endl; logOut << " Evary " << Evary << endl; logOut << " Ivary " << Ivary << endl; logOut << " gApp " << EgApp << endl; logOut << " rApp0 " << rApp0 << endl; logOut << " AppFact " << AppFact << endl; for ( int j = 0; j < Ncues ; j++) logOut << " cuetime " << j << " " << cuetime[j] << endl; for ( int j = 0; j < Ncues ; j++) logOut << " cuelength " << j << " " << cuelength[j] << endl; } void NET::Init(){ ECell = new CELL[NE+Nreadout]; EinCell = new CELL[NEsub]; EonCell = new CELL[NEsub]; ICell = new CELL[NI]; sE = new double[NE+Nreadout]; sAMPA = new double[NE+Nreadout]; sEin = new double[NEsub]; sAMPAin = new double[NEsub]; sEon = new double[NEsub]; sAMPAon = new double[NEsub]; sI = new double[NI]; sEPlus = new double[NE+Nreadout]; sAMPAPlus = new double[NE+Nreadout]; sEinPlus = new double[NEsub]; sAMPAinPlus = new double[NEsub]; sEonPlus = new double[NEsub]; sAMPAonPlus = new double[NEsub]; sIPlus = new double[NI]; cout << " IN Init" << endl; EGetParams(); IGetParams(); for ( int i = 0; i 1 ) fac = -0.5 + float(j)/float(NEpops-1); else fac = 0.0; for ( int i = 0; i < NEsub ; i++){ ECell[i+NEsub*j].Init(&Epar,Vthchange*fac,glchange*fac); } } for ( int i = 0; i < NE ; i++){ ECell[i].sAppFact = 0.0; } /* Now initialize readout cells */ for ( int i = 0; i < Nreadout ; i++){ ECell[i+NE].Init(&Epar,VRshift,glRshift); ECell[i+NE].sAppFact = 0.0; } /* Now initialize input cells */ for ( int i = 0; i < NEsub ; i++){ EinCell[i].Init(&Epar,Vinshift,glinshift); EinCell[i].sAppFact = 1.0; EonCell[i].Init(&Epar,Vonshift,glonshift); EonCell[i].sAppFact = 1.0; } /* Now initialize interneurons */ for ( int i = 0; i < NI ; i++){ ICell[i].Init(&Ipar); } Efiredout.open("Efired.dat"); Ifiredout.open("Ifired.dat"); for ( int i = 0; i 1 ){ for (int i=0; icuetime[cue] ) && (t < cuetime[cue] + cuelength[cue] ) ) { rApp = 0.0; if ( cue == 1 ) rApp = rApp0*cuestrength1; if ( cue == 2 ) rApp = rApp0*cuestrength2; rApp2 = 0.0; } else{ rApp = 0.0; rApp2 = 0.0; } if ( cue < Ncues-1 ){ if ( t > cuetime[cue+1] - 1 ) cue++; } /* First do input cells */ for ( int i = 0; i 0.0 ){ cellbin[9] /= ECell[1].binrate; cellbin[10] /= ECell[1].binrate; } else{ cellbin[9] = 0.0; cellbin[10] = 0.0; } cellout << " " << setw(6) << cellbin[9]; cellout << " " << setw(6) << cellbin[10]; cellout << " " << rApp << endl; for (int i=0;i<11;i++){ cellbin[i] = 0.0; } cell2out << t; for (int i=0;i<9;i++){ cell2bin[i] *=dt/bint; cell2out << " " << setw(6) << cell2bin[i]; } if ( ECell[4*NEsub+1].binrate > 0.0 ){ cell2bin[9] /= ECell[4*NEsub+1].binrate; cell2bin[10] /= ECell[4*NEsub+1].binrate; } else{ cell2bin[9] = 0.0; cell2bin[10] = 0.0; } cell2out << " " << setw(6) << cell2bin[9]; cell2out << " " << setw(6) << cell2bin[10]; cell2out << " " << rApp << endl; for (int i=0;i<11;i++){ cell2bin[i] = 0.0; } double Eratebin[NEbins+1]; double Einratebin; double Eonratebin; for (int i=0; i cuetime[cue] ) && ( t < cuetime[cue] + cuelength[cue] ) ){ for ( int i = 0; i= maxfired ) cout << " MAX. FIRED REACHED! " << endl; for ( int j=0; j < Ncues; j++){ for ( int i = 0; i