If your model gives exactly the same result each time it is run, there is a strategy by which you could save storage at the cost of increased code complexity and simulation time. The strategy is
1. run a simulation that determines peak spike amplitude in each compartment.
2. run a second simulation that uses the prevously measured spike peak amplitudes to determine spike width.
Slightly clever programming is required to make this happen. Here is the rough outline of such a program:
1. code that specifies properties of model cell
2. code that specifies stimulator and tstop (tstop must be long enough for spike to propagate throughout entire model)
3. into all sections of interest, insert a density mechanism that captures maximum depolarization
4. run a "calibration" simulation
5. in all internal nodes of all sections of interest, find spike amplitude by subtracting resting potential from the maximum depolarization
6. into all sections of interest, insert a density mechanism that will capture the times t1 and t2 at which v will cross the voltage vx at which you want to measure spike width
7. in all internal nodes of all sections of interest, use spike amplitude to set the value of vx
8. run a "spike width measurement" simulation
9. in all internal nodes of all sections of interest, calculate spike width as t2-t1
10. report results
This will work only if the model cell produces exactly the same voltage trajectories during the "calibration" and "spike width measurement" simulations. If the cell produces multiple spikes, the reported spike widths will be those of the last spikes that happened during the simulation.
You already have NMODL code for a density mechanism that captures maximum depolarization (but the RANGE statement needs a comma after vmax, i.e. RANGE vmax, tmax). Here is the code for a density mechanism that uses a user-specified "threshold" to determine t1, t2, and tw (spike width):
Code: Select all
NEURON {
SUFFIX ftx
RANGE vx, t1, t2, tw
}
ASSIGNED {
v (millivolt)
vx (millivolt) : "threshold" for time measurements
t1 (ms) : when v rises above vx
t2 (ms) : when v falls back below vx
tw (ms) : spike width
prespike (1) : 1 if spike hasn't started
postspike (1) : 1 if spike has finished
}
INITIAL {
prespike = 1
postspike = 0
t1 = -1
t2 = -2 : so tx > 0 only if a spike has finished
}
BREAKPOINT {
VERBATIM
if (prespike==1) {
if (v>vx) {
t1 = t;
prespike = 0;
}
} else {
if (postspike==0) {
if (v<vx) {
t2 = t;
postspike = 1;
}
}
}
ENDVERBATIM
tw = t2 - t1 : < 0 means spike hasn't finished
}
Here is the hoc code for a program that does what the code outline specifies, and finds spike "half widths" (width halfway between resting potential and spike peak).
Code: Select all
load_file("nrngui.hoc")
load_file("cell.ses")
load_file("rig.ses") // RunControl, graph, point process manager as IClamp
forall insert fmax
run() // capture spike peak depolarization
forall insert ftx
forall for (x,0) { // omit nodes at 0 and 1
// to find half width,
// put vx_ftx halfway between spike peak
// and hh resting potential (-65)
vx_ftx(x) = 0.5*(vmax_fmax(x) - 65)
}
run()
forall for (x,0) print secname(), " ", x, tw_ftx(x)