-
Notifications
You must be signed in to change notification settings - Fork 9
/
netclamp.hoc
549 lines (440 loc) · 18.8 KB
/
netclamp.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
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
/***********************************************************************************************
I. LOAD LIBRARIES
***********************************************************************************************/
{load_file("nrngui.hoc")} // Standard definitions - NEURON library file
{load_file("netparmpi.hoc")} // Contains the template that defines the properties of
// the ParallelNetManager class, which is used to set
// up a network that runs on parallel processors
{load_file("./setupfiles/ranstream.hoc")} // Contains the template that defines a RandomStream
// class used to produce random numbers
// for the cell noise (what type of noise?)
{load_file("./setupfiles/CellCategoryInfo.hoc")} // Contains the template that defines a
// CellCategoryInfo class used to store
// celltype-specific parameters
{load_file("./setupfiles/defaultvar.hoc")} // Contains the proc definition for default_var proc
// that can't be changed at command line
{load_file("./setupfiles/parameters.hoc")} // Loads in operational and model parameters that can
// be changed at command line
{load_file("./setupfiles/set_other_parameters.hoc")}// Loads in operational and model parameters
/**********************/
default_var("BasedOnRunName","ReserveTrestles_01") // Name of simulation run that the netclamp is based on
default_var("CellOI","axoaxoniccell") // type of presynaptic cell
default_var("CellOItype",0) // type of presynaptic cell
default_var("gid",11) // gid of presynaptic cell
strdef cmdstr, cmd, RunName
sprint(RunName,"%s_%d", CellOI, gid)
/***********************************************************************************************
II. SET MODEL SIZE, CELL DEFINITIONS
***********************************************************************************************/
celsius=34
{load_file("./setupfiles/load_cell_category_info.hoc")} // Reads the 'cells2include.hoc' file and
// loads the information into one
// 'CellCategoryInfo' object for each cell
// type (bio or art cells?). Info includes
// number of cells, gid ranges, type name
strdef tempFileStr
sprint(tempFileStr,"./cells/class_%s.hoc",cellType[CellOItype].technicalType) // Concatenate the
// path and file
print "loading ", tempFileStr
load_file(tempFileStr) // Load the file with the template that defines the classs
sprint(tempFileStr,"./cells/class_%s.hoc","ppspont") // Concatenate the
print "loading ", tempFileStr
load_file(tempFileStr) // Load the file with the template that defines the class
totalCells = 1 // totalCells counts the number of 'real' cells
// Create numStims number of NetStims
strdef fn
objref f2
f2 = new File()
sprint(fn, "./netclamp/%s/%s_%d_NetStimConns.dat", BasedOnRunName, CellOI, gid)
f2.ropen(fn)
numStims = f2.scanvar
ncell = 1 + numStims // ncell counts all 'real' and 'artificial' cells
objref TMPcellType[numCellTypes+1]
for i=0,numCellTypes-1 {
if (i==CellOItype) {
cellType[CellOItype].numCells = 1
} else {
cellType[i].numCells = 0
}
if (i>0) {
cellType[i].updateGidRange(cellType[i-1].cellEndGid+1) // Update the gid range for each
} else {
cellType[i].updateGidRange(0) // Update the gid range for each
}
TMPcellType[i] = cellType[i]
}
TMPcellType[numCellTypes] = new CellCategoryInfo(numCellTypes) // Make one object for each cell type to store cell type info
TMPcellType[numCellTypes].setCellTypeParams("PatternStim", "ppspont", 1, numStims, 0, 1) // Set parameters
TMPcellType[numCellTypes].numCons = new Vector(numCellTypes,0)
numCellTypes = numCellTypes+1
objref cellType[numCellTypes]
for i=0,numCellTypes-1{
cellType[i] = TMPcellType[i]
print cellType[i].cellType_string, " ", cellType[i].numCells, "(|", cellType[i].cellStartGid, "| to |", cellType[i].cellEndGid, "|)"
}
objref TMPcellType
/***********************************************************************************************
III.SET UP PARALLEL CAPABILITY AND WRITE OUT RUN RECEIPT
***********************************************************************************************/
objref pnm, pc, nc, nil
proc parallelizer() {
pnm = new ParallelNetManager(ncell) // Set up a parallel net manager for all the cells
pc = pnm.pc
pnm.round_robin() // Incorporate all processors - cells 0 through ncell-1
// are distributed throughout the hosts
// (cell 0 goes to host 0, cell 1 to host 1, etc)
}
parallelizer()
iterator pcitr() {local i2, startgid // Create iterator for use as a standard 'for' loop
// throughout given # cells usage:
// for pcitr(&i1, &i2, &gid, it_start, it_end) {do stuff}
// it_start and it_end let you define range over
// which to iterate
// i1 is the index of the cell on the cell list for that host
// i2 is the index of that cell for that cell type on that host
numcycles = int($4/pc.nhost)
extra = $4%pc.nhost
addcycle=0
if (extra>pc.id) {addcycle=1}
startgid=(numcycles+addcycle)*pc.nhost+pc.id
i1 = numcycles+addcycle // the index into the cell # on this host.
i2 = 0 // the index of the cell in that cell type's list on that host
if (startgid<=$5) {
for (i3=startgid; i3 <= $5; i3 += pc.nhost) { // Just iterate through the cells on
// this host(this simple statement
// iterates through all the cells on
// this host and only these cells because
// the roundrobin call made earlier dealt
// the cells among the processors in an
// orderly manner (like a deck of cards)
$&1 = i1
$&2 = i2
$&3 = i3
iterator_statement
i1 += 1
i2 += 1
}
}
}
// Create one Real Cell
objref cells, ransynlist, ranstimlist
cells = new List()
ransynlist = new List()
ranstimlist = new List()
func xpos_algorithm() { // Arguments: 1-gid, 2-numCells, 3-startGid, 4-binNum, 5- binNum, 6-binSize; Return: x position of cell
return 0
}
func ypos_algorithm() { // Arguments: gid, numCells, startGid, binNum, binNum, binSize; Return: y position of cell
return 0
}
func zpos_algorithm() { // Arguments: 1-gid, 2-numCells, 3-startGid, 4-binNum, 5-binSize, cell layer Zo; Return: z position of cell
return 0
}
{load_file("./setupfiles/create_cells_pos.hoc")} // Creates each cell on its assigned host
// and sets its position using the algorithm
// defined above
objref cell
for r=cellType[numCellTypes-1].cellStartGid, cellType[numCellTypes-1].cellEndGid {
cell = pc.gid2cell(r)
cell.interval=1e9
cell.start=-1
}
// Add a recording to its soma potential and somatic ion channel currents, as well as a few other locations
strdef nickname, secstr
nickname="soma"
myi_flag=1
strdef cmdstr
strdef mname, tmpstr
objref strobj, mt, cell
objref mechstring[9], mechlength
mechlength = new Vector(1)
strobj = new StringFunctions()
objref cell, mt
cell = pc.gid2cell(cellType[CellOItype].cellStartGid)
secstr="soma"
sprint(cmdstr,"objref mytrace%s", nickname)
{execute1(cmdstr)}
{sprint(cmdstr,"mytrace%s = new Vector(tstop/dt)", nickname)}
{execute1(cmdstr)}
//{sprint(cmdstr,"mytrace%s.record(&cell.%s.v(0.5))", nickname, secstr)}
{sprint(cmdstr,"mytrace%s.record(&%s.v(0.5))", nickname, cell.myroot)}
{execute1(cmdstr) }
/* Get mechanisms from soma section "myroot" recorded */
if (myi_flag==1) {
mt = new MechanismType(0)
objref mechstring[mt.count()]
k = 0
for i=0, mt.count()-1 {
mt.select( i )
mt.selected(mname)
if( ismembrane(mname)) {
if (strcmp(mname,"capacitance")!=0 && strcmp(mname,"morphology")!=0 && strcmp(mname,"iconc_Ca")!=0 && strcmp(mname,"iconcCa")!=0 && strcmp(mname,"ccanl")!=0 && strcmp(mname,"cad")!=0 && strcmp(mname,"pas")!=0 && strcmp(mname,"vmax")!=0 ) { //
if (strobj.substr(mname,"_ion")==-1) {
//printf("myi_%s \n", mname)
sprint(tmpstr, "myi_%s", mname) // "cell.soma.%s(0.5)", tmpstr
mechstring[k] = new String()
mechstring[k].s = tmpstr
if (strcmp("myi_ch_Nav", mechstring[k].s)==0) {
print nickname, ": ", tmpstr}
{k = k+1}
}
}
}
}
{mechlength.x[0] = k}
if (strcmp("som", nickname)==0) {
print "num mechs: ", k}
for rt = 0, mechlength.x[0]-1 {
sprint(cmdstr, "{objref %s_%s}", nickname, mechstring[rt].s)
execute1(cmdstr)
sprint(cmdstr, "{%s_%s = new Vector(%g)}", nickname, mechstring[rt].s, (tstop-tstart)/dt)
execute1(cmdstr)
sprint(cmdstr, "{%s_%s.record(&%s.%s(0.5))}", nickname, mechstring[rt].s, cell.myroot, mechstring[rt].s)
execute1(cmdstr)
if (strcmp("myi_ch_Nav", mechstring[rt].s)==0) {
print "record: ", cmdstr}
}
}
// Connect NetStims to all CellOI input synapses
{load_file("./setupfiles/nc_append_functions.hoc")} // Defines nc_append and nc_appendo, which
{load_file("./setupfiles/load_cell_conns.hoc")} // Load in the cell connectivity info
pregid = 1
numConnTypes = f2.scanvar
postcellType = CellOItype
for r=0, numConnTypes-1 {
precellType = f2.scanvar
numSynTypes = f2.scanvar
synWeight = cellType[precellType].wgtConns.x[postcellType]
for SynNumber = 0, numSynTypes-1 {
print "pregid = ", pregid, ", precellType = ", precellType, ", synapse = ", SynNumber, ", weight = ", synWeight
nc_append(pregid, cellType[postcellType].cellStartGid, precellType, SynNumber, synWeight + (pregid+1)*1000, 0.5) // Make the connection
pregid += 1
cellType[postcellType].numCons.x[precellType] += 1
}
}
f2.close()
// Read in firing times of all net stims
strdef fn
objref f2
objref pattern_, tvec_, idvec_
f2 = new File()
sprint(fn, "./netclamp/%s/%s_%d_NetStimTimes.dat", BasedOnRunName, CellOI, gid)
f2.ropen(fn)
numspikes = f2.scanvar
pattern_ = new PatternStim()
tvec_ = new Vector(numspikes)
idvec_ = new Vector(numspikes)
for i=0, numspikes-1 {
tvec_.x[i] = f2.scanvar // spike time in ms
idvec_.x[i] = f2.scanvar // gid of NetStim to make fire
}
f2.close()
pattern_.fake_output = 1
pattern_.play(tvec_, idvec_)
// Run simulation & write out spike raster and recording results
proc init() { local dtsav, temp, secsav, secondordersav // Redefine the proc that initializes the
// simulation (why?)
dtsav = dt // Save the desired dt value to reset it after temporarily
// changing dt to run a quick presimulation to allow the
// network to reach steady state before we start 'recording'
secondordersav = secondorder // Save the desired secondorder value to reset it after
// temporarily changing secondorder to run a quick presimulation
// to allow the network to reach steady state before we start
// 'recording' its results
finitialize(v_init) // Call finitialize from within the custom init proc, just as the default
// init proc does. Note that finitialize will call the INITIAL block for
// all mechanisms and point processes inserted in the sections and set the
// initial voltage to v_init for all sections
t = -200 // Set the start time for (pre) simulation; -500 ms to allow the network to
// reach steady state before t = 0, when the real simulation begins
dt= 10 // Set dt to a large value so that the presimulation runs quickly
secondorder = 0 // Set secondorder to 0 to set the solver to the default fully implicit backward
// euler for numerical integration (see NEURON ref)
temp= cvode.active() // Check whether cvode, a type of solver (?) is on
if (temp!=0) {cvode.active(0)} // If cvode is on, turn it off while running the presimulation
while(t<-100) { fadvance() if (PrintTerminal>1) {print t}} // Run the presimulation from t = -500
// to t = -100 (why not 0?) to let the
// network and all its components reach
// steady state. Integrate all section
// equations over the interval dt,
// increment t by dt, and repeat until
// t at -100
if (temp!=0) {cvode.active(1)} // If cvode was on and then turned off, turn it back on now
t = tstart // Set t to the start time of the simulation
dt = dtsav // Reset dt to the specified value for the simulation
secondorder = secondordersav // Reset secondorder to the specified value for the simulation
if (cvode.active()){
cvode.re_init() // If cvode is active, initialize the integrator
} else {
fcurrent() // If cvode is not active, make all assigned variables
// (currents, conductances, etc) consistent with the
// values of the states
}
}
simnum=0
strdef cmdstr
sprint(cmdstr,"mkdir ./netclamp/%s/%s", BasedOnRunName,RunName)
print cmdstr
system(cmdstr)
proc spikeout() {local i, rank localobj f // Write out a spike raster (cell, spike time)
pc.barrier() // Wait for all ranks to get to this point
sprint(cmd,"./netclamp/%s/%s/spikeraster_%03.0f.dat", BasedOnRunName, RunName, simnum)
f = new File(cmd)
if (pc.id == 0) { // Write header to file 1 time only
f.wopen()
f.close()
}
for rank = 0, pc.nhost-1 { // For each processor, allow processor to append to file the spike times of its cells
if (rank == pc.id) { // Ensure that each processor runs once
f.aopen() // Open for appending to file
for i=0, pnm.idvec.size-1 {
f.printf("%.3f %d\n", pnm.spikevec.x[i], pnm.idvec.x[i]) // Print the spike time and spiking cell gid
}
f.close()
}
pc.barrier()
}
}
// also write out vector recordings
objref f, strobj
strobj = new StringFunctions()
strdef outfile, beforestr, afterstr
objref tgt
proc printtrace() {
{sprint(outfile, "./netclamp/%s/%s/%s__%d_%s_trace_%03.0f.dat", BasedOnRunName, RunName, CellOI, gid, secstr, simnum)}
{f = new File(outfile)}
{f.wopen()}
{f.printf("t\tv")} // write header
if (myi_flag==1) {
mt = new MechanismType(0)
objref mechstring[mt.count()]
k = 0
for i=0, mt.count()-1 {
mt.select( i )
mt.selected(mname)
if( ismembrane(mname)) {
if (strcmp(mname,"capacitance")!=0 && strcmp(mname,"morphology")!=0 && strcmp(mname,"iconc_Ca")!=0 && strcmp(mname,"iconcCa")!=0 && strcmp(mname,"ccanl")!=0 && strcmp(mname,"cad")!=0 && strcmp(mname,"pas")!=0 ) { //
if (strobj.substr(mname,"_ion")==-1) {
//printf("myi_%s \n", mname)
sprint(tmpstr, "myi_%s", mname) // "cell.soma.%s(0.5)", tmpstr
mechstring[k] = new String()
mechstring[k].s = tmpstr
if (strcmp("myi_ch_Nav", mechstring[k].s)==0) {
print nickname, ": ", tmpstr}
{k = k+1}
}
}
}
}
mechlength.x[0]=k
for rt = 0, mechlength.x[0]-1 {
sprint(cmdstr, "%s_%s", nickname, mechstring[rt].s)
if (strcmp("myi_ch_Nav", mechstring[rt].s)==0) {
print "Nav nickname: ", nickname}
if (strcmp("som", nickname)==0) {
print "cmdstr: ", cmdstr, " declared: ", name_declared(cmdstr) }
if (name_declared(cmdstr)>0) {
f.printf("\t%s", mechstring[rt].s)
}
}
}
{f.printf("\n")}
for i=0, (tstop-tstart)/dt-1 {
{sprint(cmdstr, "{f.printf(\"%%g\\t%%g\", i*dt, mytrace%s.x[i])}", nickname)}
{execute1(cmdstr)}
if (myi_flag==1) {
for rt = 0, mechlength.x[0]-1 {
sprint(cmdstr, "%s_%s", nickname, mechstring[rt].s)
if (name_declared(cmdstr)>0) {
sprint(cmdstr, "{f.printf(\"\\t%%g\", %s_%s.x[i])}", nickname, mechstring[rt].s)
execute1(cmdstr)
}
}
}
{f.printf("\n")}
}
{f.close()}
}
use_cache_efficient=1
get_spike_hist=0
use_bin_queue=0
use_spike_compression=0
if (use_spike_compression==1) {
maxstepval = 2.5
} else {
maxstepval = 0.5
}
proc rrun(){ // Run the network simulation and write out the results
pnm.want_all_spikes() // Record all spikes of all cells on this machine into the
// vectors pnm.spikevec (spiketimes) and pnm.idvec (gids)
local_minimum_delay = pc.set_maxstep(maxstepval) // Set every machine's max step size to minimum delay of
// all netcons created on pc using pc.gid_connect, but
// not larger than 10
stdinit() // Call the init fcn (which is redefined in this code) and
// then make other standard calls (to stop watch, etc)
pc.psolve(tstop) // Equivalent to calling cvode.solve(tstop) but for parallel NEURON;
// solve will be broken into steps determined by the result of
// set_maxstep
spikeout() // Write the spike times (in ms) and spiking cells (by gid) into a file called "spikeraster.dat"
printtrace()
}
walltime = startsw()
strdef cmd, cmdo
newtstop = tstop
warningflag=0
{cvode.cache_efficient(use_cache_efficient)} // always double check that this addition does not affect the spikeraster (via pointers in mod files, etc)
if (use_bin_queue==1) {
use_fixed_step_bin_queue = 1 // boolean
use_self_queue = 0 // boolean - this one may not be helpful for me, i think it's best for large numbers of artificial cells that receive large numbers of inputs
{mode = cvode.queue_mode(use_fixed_step_bin_queue, use_self_queue)}
}
if (maxstepval==1) {
nspike = 3 // compress spiketimes or not
gid_compress = 0 //only works if fewer than 256 cells on each proc
{nspike = pc.spike_compress(nspike, gid_compress)}
}
celsius = 34
simnum=0
numsims=10
lowerbound=0 // 5
rrun()
strdef f2n, f3n
objref f2, f3
f2 = new File()
f3 = new File()
sprint(f2n, "./netclamp/%s/%s_%d_NetStimConns.dat", BasedOnRunName, CellOI, gid)
sprint(f3n, "./netclamp/%s/%s_%d_key.dat", BasedOnRunName, CellOI, gid)
f3.wopen(f3n)
for simnum=1, numsims {
//nclist.remove_all
pregid=1
f2.ropen(f2n)
numStims = f2.scanvar
numConnTypes = f2.scanvar
postcellType = CellOItype
f3.printf("%d\t%f\n", simnum, 1 + (simnum-lowerbound)*.1)
for r=0, numConnTypes-1 {
precellType = f2.scanvar
numSynTypes = f2.scanvar
synWeight = cellType[precellType].wgtConns.x[postcellType]
if (strcmp(cellType[precellType].cellType_string,"ca3cell")==0 || strcmp(cellType[precellType].cellType_string,"eccell")==0) {
synWeight = synWeight*(1 + (simnum-lowerbound)*.1)
}
for SynNumber = 0, numSynTypes-1 {
nclist.o(pregid-1).weight = synWeight
print "pregid = ", pregid, ", precellType = ", precellType, ", synapse = ", SynNumber, ", weight = ", synWeight
//nc_append(pregid, cellType[postcellType].cellStartGid, precellType, SynNumber, synWeight + (pregid+1)*1000, 0.5) // Make the connection
pregid += 1
cellType[postcellType].numCons.x[precellType] += 1
}
}
f2.close()
rrun() // Run the network simulation (in proc rrun)
}
f3.close()
///////////////
{pc.runworker()} // Everything after this line is executed only by the host node
// The NEURON website describes this as "The master host returns immediately. Worker hosts
// start an infinite loop of requesting tasks for execution."
{pc.done()} // Sends the quit message to the worker processors, which then quit NEURON
quit() // Sends the quit message to the host processor, which then quits NEURON