// $Id: snscode.hoc,v 1.28 1995/11/20 02:24:07 billl Exp $ // handles coding, syn assignment and syn graphics //* CODE GENERATION AND RECOVERY //** Declarations 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 } } //* LISTS //** Declarations objref prelist // list of all presynaptic mechanisms prelist = new List("PRESYN") objref tmplist tmplist = new List() objref sfunc sfunc = new StringFunctions() strdef mechnames //** sublist() places a sublist in LIST0 from LIST1 index BEGIN to END inclusive proc sublist () { local ii $o1.remove_all for ii=$3,$4 { $o1.append($o2.object(ii)) } } //** catlist() concats LIST1 on end of LIST2 proc catlist () { local ii for ii=0,$o2.count-1 { $o1.append($o2.object(ii)) } } //** mechlist() creates a LIST of all this CELL type's TEMPLATE type // list, cell, template // make a list of mechanisms belonging to a certain template proc mechlist () { local num,ii // mechnames = "" // not a good storage since runs out of room if (numarg()==0) { print "mechlist(list, cell, template)" return} $o1 = new List($s2) num = $o1.count for ii=0,num-1 { sprint(temp_string_,"%s.append(%s.%s)",$o1,$o1.object(ii),$s3) execute(temp_string_) // sprint(mechnames,"%s/%d/%s.%s",mechnames,ii,$o1.object(ii),$s3) } for (ii=num-1;ii>=0;ii=ii-1) { $o1.remove(ii) } } //** lp() loop through a list running command in object's context // list($o), obj_elem($s), comm($s) // with 2 args run $o1.object().obj_elem // with 3 args run comm($o1.object().obj_elem) proc lp () { for ii=0,$o1.count-1 { printf("%s ",$o1.object(ii)) if (numarg()==3) { sprint(temp_string_,"%s(%s.%s)",$s3,$o1.object(ii),$s2) } else { sprint(temp_string_,"%s.%s",$o1.object(ii),$s2) } execute(temp_string_) } } //** prlp() loop through a list printing object name and result of command proc prlp () { for ii=0,$o1.count-1 { printf("%s ",$o1.object(ii)) if (numarg()==2) { sprint(temp_string_,"print %s.%s",$o1.object(ii),$s2) execute(temp_string_) } else { print "" } } } //* 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(POSTSYN_MECH,TEMP_PRELIST,MAXDIV) // like newpre() except that in addition to insuring no repeats // also tries to even out divergence // may want to create TEMP_PRELIST from PRELIST using sublist() // maxdiv == -1 means to ignore divergence func pickpre () { local ran, maxdiv, maxpre, cnt, ii maxdiv = $3 maxpre = $o2.count-1 cnt = 0 while (1) { cnt = cnt+1 ran = fran(0,maxpre) // all possible synapses if (chkpre($o1,$o2.object(ran).pre)) { // don't allow 2 connects from same place continue } // chance of adding another reduces depending on how close to maxdiv if ((maxdiv == -1) || ($o2.object(ran).check <= maxdiv && \ fran(0,maxdiv) < (maxdiv - $o2.object(ran).check))) { break } if (cnt > 3*maxpre) { // enough fruitless searching for ii=0,$o2.count-1 { if ($o2.object(ii).check <= maxdiv) { return ii } } print "ERROR in pickpre(): no more room (maxdiv reached)" return -1 } } return ran // return the index into the cell array } //* 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, conv, maxdiv, [delay, gmax]) // maxdiv == -1 means to ignore divergence proc 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[0],$o1,maxdiv) if (rannum==-1) { return } } 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) } } } } endtemplate POSTSYN