// $Id: snscode.hoc,v 1.42 2002/04/22 14:17:48 billl Exp $ // handles coding, syn assignment and syn graphics // load_file("declist.hoc","declist") load_proc("declist") objref prelist // list of all presynaptic mechanisms prelist = new List("PRESYN") //* CODE GENERATION AND RECOVERY objref snsgrlist snsgrlist = new List() chainlen = 1 // allow the user to change this as needed for synfind or connmat maxflds = 4 // maximum number of codefields cdflds = 4 // number of 'code fields' double cdsep[maxflds+1] // code column separators // default values see mkfields() call below // cdsep[0] = 1e9 col 9 - 9 // cdsep[1] = 1e8 col 8 - 7 // cdsep[2] = 1e6 col 6 - 4 // cdsep[3] = 1e3 col 3 - 1 // cdsep[4] = 1e0 // labels can be entered for each of 4 fields, up to 8 labels in each objref cdlbls[cdflds][8] for ii=0,cdflds-1 for jj=0,7 cdlbls[ii][jj]=new String("") //** mkfields() creates up to 4 fields (5 args: # fields, f1,f2,f3,f4) // eg mkfields(4,1,2,3,3) to recreate the defaults proc mkfields() { local sum,i cdflds = $1 cdsep[4] = 1 sum = $5 cdsep[3] = 10 ^ sum sum = sum + $4 cdsep[2] = 10 ^ sum sum = sum + $3 cdsep[1] = 10 ^ sum sum = sum + $2 cdsep[0] = 10 ^ sum } mkfields(4,1,2,3,3) //** mkmkcode(): create the mkcode routine // no arguments, should follow mkfields() // not reliable if used under xopen() proc mkmkcode() { local i printf("!{!\n") printf("func mkcode() { \nreturn ") for (i=1;i<=cdflds;i=i+1) { printf("$%d*cdsep[%d] + ",i,i+maxflds-cdflds) } printf("0 \n}\n") printf("!}!\n") } //** mkcode() creates a code of 9 cols in 4 fields, sized 1,2,3,3 func mkcode() { // standard 9 cols // divide into 4 fields of size 1,2,3,3 //col 8 7,6 5,4,3 2,1,0 return $1*cdsep[1] + $2*cdsep[2] + $3*cdsep[3] + $4*cdsep[4] } //** cd(i,code) returns field i (1-4) from code // $1 field number (from 1), $2 code func cd() { local temp temp = ($2%cdsep[$1+(maxflds-cdflds)-1]) // remove the left side return int(temp/cdsep[$1+(maxflds-cdflds)]) // remove the right side } //** setcd(i,code,new) replaces field i (1-4) from code with new // $1 field number (1 offset), $2 code, $3 new value func setcd() { local temp, old temp = ($2%cdsep[$1+(maxflds-cdflds)-1]) // remove the left side old = cdsep[$1+(maxflds-cdflds)]* int(temp/cdsep[$1+(maxflds-cdflds)]) return $2 - old + $3* cdsep[$1+(maxflds-cdflds)] } //** prcode(code) prints a code in readable form // print a code of 9 cols in 4 fields, sized 1,2,3,3 proc prcode() { local i for (i=(maxflds-cdflds+1);i= 0) { return cd($3,code) } else { return -1 // error } } //* FUNCTIONS OPERATING ACROSS ALL PRESYNS //** checksyns() goes through prelist and prints out divergence value proc checksyns() { local i for i=0, prelist.count()-1 { printf("%d ",prelist.object(i).check()) } } //** cleansyns() goes through prelist and collapses the synapse list proc cleansyns() { local i for i=0, prelist.count()-1 { prelist.object(i).clean() } } //** clearsyns() goes through postsyn list and reinitializes everything proc clearsyns() { local i,j tmplist.remove_all tmplist = new List("POSTSYN") for i=0, tmplist.count()-1 { for j=0, tmplist.object(i).mech_num - 1 { if (tmplist.object(i).mech[j].maxsyn > 0) { tmplist.object(i).mech[j].init_arrays(tmplist.object(i).mech[j].maxsyn) } } } cleansyns() } //* SYNAPSE ASSIGNMENT CODE // con=absolute convergence number, div=absolute div number // con = %con * pre // div * pre = con * post = S (total synapses) // %div = div/post = S/(pre*post) = con/pre = %con // div = %con * post // maxdiv = int((1 + var) * div) //** ranverge() produces randomized convergence // used for convergence, rancon (randomized convergence) is given by // ranverge(%conv,numpre,variance) // returns a convergence number (number of syns onto a cell) // that is randomly chosen from (%conv +/- variance)*pre // if random not wanted just do int(pcon * numpre) instead func ranverge () { local min, max, ran, pcon, numpre, var pcon = $1 numpre = $2 var = $3 if (pcon == 1) { return numpre } // fully connected if (pcon == 0) { return 0 } // no connection if (var != 0) { ran = pcon - var + (u_rand() * 2 * var) } else { ran = pcon } // no variability return int(ran * numpre + u_rand()) // con * pre or div * post rounded up or down } //** pickpre() tries to reduce divergence variance // pickpre(MECH_NUM,TEMP_PRELIST,MAXDIV) // may want to create TEMP_PRELIST from PRELIST using sublist() // maxdiv == -1 means to ignore divergence // MUST do divvec.resize() and divvec.fill(0) before using objref divvec,divvec1 // vectors to count how much div is from each nrn divvec = new Vector(100) divvec1 = new Vector(100) // a scratch vector func pickpre () { local ran, maxdiv, maxpre, min, indx, mechnum mechnum = $1 maxdiv = $3 // max divergence to be allowed maxpre = $o2.count-1 // number of presyn choices if (maxdiv == -1) { // just choose one randomly ran = fran(0,maxpre) // all possible synapses return ran } maxdiv *= mechnum // need space for mult mechs together // if (divvec.size != prelist.size) { // printf("Pickpre full ERROR: divvec not sized properly\n") } min = divvec.min // divvec should start all 0's if (min >= maxdiv) { // all full up printf("Pickpre full WARNING: %d %d\n",min,maxdiv) divvec.printf } divvec1.indvwhere(divvec,"==",min) // look for all the smallest to fill up first ran = fran(0,divvec1.size-1) // pick index of one of these randomly indx = divvec1.x[ran] // index is the randomly chosen entry in vec of ptrs. divvec.x[indx] += mechnum // record that this one has been chosen return indx } // check that divergence in individual divvecs is same as divergence in PRESYN structure // chkdiv(vec,PRELISTmin,PRELISTmax,num_mechs) // vec is specific divergence vector // PRELISTmin,max give the entries in prelist to compare // num gives the number of mechanisms in a single post from this cell proc chkdiv () { local min,max,num min = $2 max = $3 if ($o1.size != max-min+1) { printf("ERROR: divvec size must = # of prelist items: %d %d\n",$o1.size,max-min+1) return } for vtr(&x,$o1) { if (x != prelist.object(min+i1).nsyn) { printf("ERROR: %d in %s != nsyn %d\n",x,$o1,prelist.object(min+i1).nsyn) } } } //* template POSTSYN proc callback () {} begintemplate POSTSYN public mech, mech_num, post public init_arrays, augment_array, conn public up external pickpre, callback objref mech[1],this,up // to be resized later //** init() args are syn objects proc init() { mech_num = numarg() objectvar mech[mech_num] if (mech_num >= 4) { mech[3] = $o4 } if (mech_num >= 3) { mech[2] = $o3 } if (mech_num >= 2) { mech[1] = $o2 } if (mech_num >= 1) { mech[0] = $o1 } } //** augment_array() add $1 to current number of synapses func augment_array() { num = $1 for k=0,mech_num-1 { newmax = mech[k].maxsyn + num mech[k].init_arrays(newmax) } return newmax } //** init_arrays() initialize all mechs to maxsyn = $1 func init_arrays() { num = $1 for k=0,mech_num-1 { mech[k].init_arrays(num) } return num } //** conn() find some places in a list to connect to // (list, con, maxdiv, [delay, gmax]) // maxdiv == -1 means to ignore divergence func conn () { con = $2 maxdiv = $3 numpre = $o1.count if (numarg()>3) {delay = $4 gmax = $5 setall=1 } else { setall = 0 } for j=0,con-1 { if (con == numpre) { // do all of them in order rannum = j } else { rannum = pickpre(mech_num,$o1,maxdiv) if (rannum==-1) { printf(": %d/%d done\n",j,con) return -1 } } for k=0,mech_num-1 { // post, pre, listcnt, syncnt, mechcnt, precnt mech[k].setlink($o1.object(rannum).link, $o1.object(rannum).nsyn, $o1.object(rannum).maxsyn) if (setall) { mech[k].delay(-1,delay) // set most recent (index nsyn-1) mech[k].gmax(-1,gmax) } else { callback(mech[k],k,rannum) } } } return 0 } endtemplate POSTSYN