// Threshold spacetests using a binary search method. For real cells, detecting // a somatic depolarization of an input value (usually +5 mV from resting) // // Program flow: // Takes location range, Gaussian width for time distribution, and location increments. // Also takes type of run: AMPA only, NMDA only, or both. // Records number of synapses at which the threshold is reached. strdef filename, brStr, ibrStr proc ThreshSpaceS() { local sVT,UPPERLIM,resetHere,locRange,gaussTime,branchNum,incrBy,found,branchLength,toggle,matInd,jvar localobj spMap,search_ind,finMat,floovec // Runs the whole test. // Inputs: // $1: locRange is the range to be uniformly sampled in space // $2: gaussTime is the width of the Gaussian to be sampled for timing // $3: branchNum is the column to be read in the spine index file. // $4: incrBy is the distance in microns each trial is separated by. // $5: toggle is the kind of synapse: 0 BOTH, 1 AMPA, 2 NMDA // $s6: filename. // $s7: name of the spine map file. // $8: seed // $9: soma threshold voltage // $o10: the cell UPPERLIM = 10000 // If the number of synapses goes above this, the trial moves on. locRange = $1 gaussTime = $2 branchNum = $3 incrBy = $4 toggle = $5 filename = $s6 ibrStr = $s7 seed = $8 sVT = $9 spMap = new Vector() spMap = makeMap(ibrStr,branchNum) // The binary search vector holding indices. Order: lower bound, current test number, upper bound. search_ind = resetVec(10) floovec = new Vector(1,(spMap.size()-locRange)/incrBy) floovec.floor() finMat = new Matrix(floovec.x[0]+1,1) matInd = -1 for (l_ind=0;l_ind<(spMap.size()-locRange);l_ind=l_ind+incrBy) { // For each run, search_ind starts from the previous threshold level found = 0 matInd = matInd+1 if (search_ind.x[1] == -1) { resetHere = UPPERLIM-1 } else { resetHere = search_ind.x[1] } search_ind = resetVec(resetHere) while (found != 1) { // found variable is 1 when AP is fired at synnum n+1 but not at synnum n found = testSyns(search_ind.x[1],locRange,gaussTime,toggle,seed,l_ind,spMap,sVT,$o10) // Sees if this synapse number works // Inputs: // $1: search_ind is how many synapses to use // $2: locRange is the testing range // $3: gaussTime is the width of the Gaussian for the time distribution // $4: toggle is the usual synapse type ID // $5: seed is for the norm dist for time and the unif dist for space. // $6: l_ind is where the test is starting. // $o7: spMap is the vector containing spine indices. // $8: soma threshold voltage // $o9: the cell //print search_ind.x[1] // Setting an upper limit for # synapses tested if (search_ind.x[1] > UPPERLIM) { found = 1 search_ind.x[1] = -1 } search_ind = binSearch(search_ind,found) // If synapse number doesn't work, changes the search index and upper limit } finMat.x[matInd][0] = search_ind.x[1] + 1 // Saves final synapse number to the matrix jvar = printf("Loc %d: %d\n",l_ind,search_ind.x[1]) } saveSpace(finMat,filename) } /*------------------ MAIN FUNCTIONS ----------------------*/ obfunc makeMap() { local mapInd,nxSp,tsdInd,jnkInd localobj f,brVec // Reads in the nx1000 branch spine index file and puts the right column in a vector. // // Inputs: // $s1: the spine index file name. // $2: the column I want to read. // // Output: // spMap, a vector that's as long as the branch length. brVec = new Vector(1000) sprint(brStr,"%s",$s1) f = new File(brStr) f.ropen() // Gets rid of the unnecessary branches if ($2>1) { for jnkInd = 2,$2 { for tsdInd = 0,999 brVec.x[0] = f.scanvar() } } // Reads in spine indices until a -1 is reached. nxSp = f.scanvar() mapInd = 0 while (nxSp!=-1) { brVec.x[mapInd] = nxSp mapInd = mapInd+1 nxSp = f.scanvar() } // Shortens the vector to the right length. for cutInd = mapInd,999 brVec.remove(mapInd) return brVec } func testSyns() { local sVT,search_ind, locRange, gaussTime, toggle, seed, l_ind, found localobj tempvec,spMap,r2, tlist, tlist2, apc // If an AP fires at search_ind and search_ind+1, returns 2. // If no AP fires at either, returns 0. // If AP fired at search_ind+1 and not search_ind (it's at threshold), returns 1. // // Inputs: // $1: search_ind is how many synapses to use // $2: locRange is the testing range // $3: gaussTime is the width of the Gaussian for the time distribution // $4: toggle is the usual synapse type ID // $5: seed is for the norm dist for time and the unif dist for space. // $6: l_ind is where the test is starting. // $o7: spMap is the vector containing spine indices. // $8: soma threshold voltage // $o9: the cell search_ind = $1 locRange = $2 gaussTime = $3 toggle = $4 seed = $5 l_ind = $6 spMap = $o7 sVT = $8 r2 = new Vector(2,0) tempvec = new Vector(1) tempvec.x[0] = locRange/2 tempvec.floor() // Runs for search_ind and search_ind+1 for ts_ind = 0,1 { tlist = new List() tlist2 = new List() tlist = setSyns(search_ind+ts_ind,locRange,gaussTime,toggle,seed,l_ind,spMap,$o9) // Inputs: // $1: synapse number. // $2: locRange, how widely synapses are distributed. // $3: gaussTime, the width of the Gaussian used in sampling onset times. // $4: toggle is explained above; slightly different for this function since it does one at a time. // $5: seed // $6: l_ind is the spine this test is starting on. // $o7: spMap // $o8: the cell if (toggle==0) { tlist2 = setSyns(search_ind+ts_ind,locRange,gaussTime,2,seed,l_ind,spMap,$o9) } init() // Puts an APCount object at the spine in the middle of the input. $o9.soma { apc = new APCount(0.5) apc.thresh = sVT apc.n = 0 } //Takes tlist to adjust tstop. runTest(tlist) //if (apc.n>0) printf("time was %d\n",apc.time) // Sees if an 'AP' fired if (apc.n > 0) { if (ts_ind==0) { return 2 } else { r2.x[ts_ind] = 1 } } } return r2.sum() } obfunc binSearch() { // Adjusts the searchVec based on results from testSyns. // // Inputs: // $o1: search_ind is a vector; the first element is the number of synapses being tested // $2: found tells what to do with the search vector. 0 is none, 1 is threshold, 2 is both. // If too low if ($2 == 0) { $o1.x[0] = $o1.x[1] if ($o1.x[2] == $o1.x[1]) { $o1.x[1] = $o1.x[1]*2 $o1.x[2] = $o1.x[1] } else { $o1.x[1] = (($o1.x[2]-$o1.x[1])/2)+$o1.x[1] $o1.floor() } } // If too high if ($2 == 2) { $o1.x[2] = $o1.x[1] $o1.x[1] = (($o1.x[1]-$o1.x[0])/2)+$o1.x[0] $o1.floor() } return $o1 } proc saveSpace() { localobj mat, f // Takes a matrix and saves it. // // Inputs: // $o1: the matrix to be saved (rows are location, columns are trial) // $s2: filename with the full directory mat = $o1 f = new File() f.wopen($s2) mat.fprint(f, " %g") f.close() } obfunc resetVec() { localobj vec // Gives the index vector given some general starting point. It's a 3-element vector where the // first element is the lower bound, middle is current index, last is upper bound. The function // starts the upper bound at the current index value, since the search pattern works by doubling. // // Input: // $1: the number of synapses to start out with. vec = new Vector(3,0) vec.x[1] = $1 vec.x[2] = $1 return vec } /*------------------ SUB FUNCTIONS -----------------------*/ // In testSyns() obfunc setSyns() { local s_ind localobj tlist,r,normr,svec,tvec // Creates a list of placed and timed synapses. Does not deal with BOTH case (creates AMPA for // 0 and 1 toggle and NMDA for 2) because that's taken care of in testSyns(). // // Inputs: // $1: synapse number. // $2: locRange, how widely synapses are distributed. // $3: gaussTime, the width of the Gaussian used in sampling onset times. // $4: toggle is explained above; slightly different for this function since it does one at a time. // $5: seed // $6: l_ind is the spine this test is starting on. // $o7: spMap // $o8: the cell // Output: // A single list of one kind of synapse; preset locations and firing times. tlist = makeSyns($4,$1) r = new Random($5) r.uniform($6,$6+$2) normr = new Random($5*10) normr.normal(0,$3) svec = new Vector($1) tvec = new Vector($1) svec.setrand(r) svec.floor() tvec.setrand(normr) tvec.add((-1)*tvec.min()+2) for s_ind = 0, $1-1 { $o8.spine_head[$o7.x[svec.x[s_ind]]] { tlist.o(s_ind).loc(.5) tlist.o(s_ind).onset() = tvec.x[s_ind] } } return tlist } // In testSyns() proc runTest() { local i localobj vec // Initializes cell and runs to tstop, which is 100 + last firing time. // Input: // $o1: tlist. vec = giveTimes($o1) init() tstop = vec.max() + 100 while (t