A nicely written program. With just a few changes it should work. There are only two "problems."
1. None of the statements that try to create instances of the IClamp class will work, because there is no currently accessed section. When you execute this code, do error messages appear in NEURON's xterm? If you have any questions about the concept of "currently accessed section," please read
5.3.1 Which section do we mean? in chapter 5 of The NEURON Book (if you don't have the book, get the preprint pdf from
http://www.neuron.yale.edu/ftp/ted/book ... xedref.pdf).
2. The syntax of the Vector record statements is correct, but there is no run() statement, so when the lines
recv.printf(savv)
rect.printf(savt)
are executed, the files will remain empty.
Suggestions:
1. Enclose the last part of the program, starting at
tstop = 500
and ending with
savt.close()
in a pair of comment delimiters /* */ . There's no point in executing any of those statements until you are sure that the rest of the code can run a 10 or 20 ms simulation and produce reasonable results.
2. To fix the "no currently accessed section" problem, insert an
access soma
statement immediately after the close of the soma { . . . } block that defines the properties of soma. This will declare that the soma is the "default section", and that will allow the IClamps to be created--all those error messages will disapper.
3. Use the GUI for interactive program development and debugging. Don't be afraid of the GUI! Bring up a RunControl panel and also a Voltage axis graph. Increase Tstop to 20 or 30 ms, then click on the Init & Run button. If the Voltage axis graph doesn't look reasonable, try to figure out what's wrong.
4. After that seems to work properly, uncomment only the statements that set up vector recording. The stuff that creates and writes ouput files should still be commented out. Add a new procedure
Code: Select all
proc myrun() { local ii
run()
print " "
for ii=0,rect.size()-1 print ii, " ", rect.x[ii], " ", recv.x[ii]
}
to the end of your program. At the xterm's oc> prompt, type the command
myrun()
You might want to make sure that Tstop is not too large, or it may take a long time before all the values are printed.
5. After that works properly, it is time to change proc myrun() to
Code: Select all
objref savv, savt
savv = new File()
savt = new File()
proc myrun() { local ii
run()
// print " "
// for ii=0,rect.size()-1 print ii, " ", rect.x[ii], " ", recv.x[ii]
// statements that open and write the output files
savv.wopen("Nv.dat")
savt.wopen("Nt.dat")
recv.printf(savv)
rect.printf(savt)
savv.close()
savt.close()
}
Here are two more suggestions:
1. It is generally a good idea to let the simulation execute for a brief time without applying any stimulus. This demonstrates that the model has been properly initialized. In the absence of any stimulus, a model of a cell that is not spontaneously active should simply do nothing at all--membrane potential and all other state variables should remain unchanged.
2. Instead of using a separate IClamp for each current step, create just one IClamp. Use the Vector class's play method to force the IClamp's "amp" variable to follow the desired time course. One advantage of doing this: you can do it with just a bit of hoc code that, with a little bit of software design, is easy to debug and also easy to use to create as complex a series of current steps as you might like. Another advantage: you can then use a graph to plot the actual current delivered by the IClamp. Such a graph is direct proof that your stimulus is exactly what you wanted.
In principle, specifying a series of current steps is straightforward: declare a pair of Vectors ivec and tvec, then fill them with a series of values that are the coordinates of the points at which the step function changes abruptly. For example, suppose you want the cell to sit quietly for 10 ms, after which you want to inject -4 nA x 10 ms, followed by 5 nA x 10 ms, followed by 0 nA forever. You could set up tvec and ivec like this:
Code: Select all
tvec.x[0] = 0 // start of step 0
ivec.x[0] = 0
tvec.x[1] = 10 // end of step 0
ivec.x[1] = 0
tvec.x[2] = 10 // start of step 1
ivec.x[2] = -4
tvec.x[3] = 20 // end of step 1
ivec.x[3] = -4
tvec.x[4] = 20 // start of step 2
ivec.x[4] = 5
tvec.x[5] = 30 // end of step 2
ivec.x[5] = 5
tvec.x[6] = 30 // start of remainder of simulation
ivec.x[6] = 0
tvec.x[7] = 1e9 // after returning to 0, stay there forever
ivec.x[7] = 0
But it's easy to get confused and make a mistake. Setting up more than a couple of steps like this is mind-numbing.
It's better to use procs for this kind of stuff. Much easier to have confidence that you're going to get what you want (but always look at the stimulus to be absolutely sure!).
Code: Select all
objref ivec, tvec
ivec = new Vector()
tvec = new Vector()
// creates a step that applies no stimulus at all,
// so we can be sure the model is properly initialized
// just one argument: duration of this first step
proc step0() {
// throw out anything that might have been in ivec and tvec
ivec = new Vector(2) // this contains a pair of 0s, so we don't have to do anything to it
tvec = new Vector(2)
tvec.x[1] = $1
}
// arguments are step amplitude and duration
proc addstep() {
ivec.append($1)
ivec.append($1)
// last element of tvec contains the start time
tvec.append(tvec.x[tvec.size()-1])
// step ends $2 later
tvec.append(tvec.x[tvec.size()-1] + $2)
}
proc set_up_stim() {
step0 // initialize ivec and tvec, and fill them with the "no stimulus" step
// add three steps:
addstep(-4, 10) // -4 nA x 10 ms
addstep(5, 10) // 5 nA x 10 ms
addstep(0, 1e9) // 0 nA forever
}
Then use Vector play with interpolation to force the IClamp's amp to follow the time course specified by the ivec, tvec pair.
I hope I didn't made any typographical errors . . .