-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsnscode.hoc
353 lines (317 loc) · 10.8 KB
/
snscode.hoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
// $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<maxflds;i=i+1) {
printf("%d,",cd(i,$1))
}
printf("%d\n",cd(maxflds,$1))
}
//** prlbls(code) uses cdlbls to print out strings instead of numbers
// when possible
proc prlbls() { local k,cde
for (k=(maxflds-cdflds+1);k<=maxflds;k=k+1) {
cde = cd(k,$1)
if (k < cdflds && cde < 8) {
if (strcmp(cdlbls[k][cde].s,"") == 0) {
printf("%d,",cde)
} else {
printf("%s,",cdlbls[k][cde].s)
}
} else {
printf("%d,",cde)
}
}
print ""
}
//** chkpre(OBJ,CODE) searches through a syn OBJECT for this CODE
// check whether a code to be included has already been used
// 2 arguments: syn obj, comparison
// returns 1 if found, 0 if not
func chkpre () { local i
for(i=0; i<$o1.nsyn; i=i+1) {
if ($o1.pre(i) == $2){
return 1 } }
return 0
}
//** synfind list1 cd2 fld3 val4 cd5 fld6 val7
// print out codes on all the synapses that criteria
// cd2, cd5 are "pre" or "post" or "code"
// fld3, fld6 is the field
// val4, val7 are the values to look for matching
proc synfind () { local cdx,cdy,i,j,start
if ((cdx = connmat_findstr($s2)) == -1) { printf("unknown string %s",$s2) return }
if ((cdy = connmat_findstr($s5)) == -1) { printf("unknown string %s",$s5) return }
for i=0,$o1.count-1 {
for (j=0;j<$o1.object(i).nsyn-1;j=j+chainlen) {
if (synmatch($o1.object(i),j,cdx,$3,$4,cdy,$6,$7)) {
sprint(temp_string_,"pr = %s.pre(%d)",$o1.object(i),j)
execute(temp_string_)
printf("%s syn# %d: pre==",$o1.object(i),j)
prlbls(pr)
sprint(temp_string_,"pr = %s.post(%d)",$o1.object(i),j)
execute(temp_string_)
printf(" post==")
prlbls(pr)
print ""
}
}
}
}
//*** synmatch obj1 ind2 cf3 fld4 val5 cf6 fld7 val8
// check object fields for matches to values given
func synmatch () { local cdd, cde, i, j
cdd = connmat_newpt($o1,$3,$4,$2,0)
cde = connmat_newpt($o1,$6,$7,$2,0)
if (cdd == $5 && cde == $8) { return 1 } else { return 0 }
}
// parse the strings and return a number telling which it is
// 0:code, 1:pre, 2:post, 3:increment
func connmat_findstr () {
if (strcmp($s1,"code") == 0) { return 0
} else if (strcmp($s1,"pre") == 0) { return 1
} else if (strcmp($s1,"post") == 0) { return 2
} else if (strcmp($s1,"inc") == 0) { return 3
} else { return -1 }
}
// look at return the field needed from the correct word
// word indication as returned by connmat_findstr()
// args: object, word, field, synnum, ind
func connmat_newpt () { local code
if ($2==0) { code = $o1.code($4)
} else if ($2==1) { code = $o1.pre($4)
} else if ($2==2) { code = $o1.post($4)
} else if ($2==3) { return $5 }
if (code >= 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