plotting variables vs. time
plotting variables vs. time
I needed help executing a state axis instead of a shape plot, one where I can specify what is being graphed instead of voltage. What's the syntax for the state axis?
-
- Site Admin
- Posts: 6305
- Joined: Wed May 18, 2005 4:50 pm
- Location: Yale University School of Medicine
- Contact:
All you need is a Graph, with whatever additional statements are required to specify
--the variables that are to be plotted
--how NEURON will update the plots in the course of a simulation
--position, size, and scaling of the graph
--additional labels, if any
Read about the Graph class here
http://www.neuron.yale.edu/neuron/stati ... graph.html
As far as graph updating is concerned, you will find all kinds of strange looking code in
ModelDB and elsewhere. The best practice is to just let the standard run system take
care of it for you. You can read about this in The NEURON Book--look in the Index for
standard run system / plotting system
especially
standard run system / plotting system / graphLists
and
standard run system / plotting system / incorporating Graphs and objects
But it's even quicker to just steal code from a session file.
Suppose you have a model that has a default section called soma with hh, and you use
the NEURONMainMenu toolbar to create a Voltage axis graph of v(0.5) vs. t, a Current
axis graph of soma.ik(0.5) vs. t, and a State axis graph of soma.m_hh(0.5) vs. t. Also,
you use each Graph's "Change text" to write a label on the graph ("voltage axis",
"current axis", or "state axis" as appropriate). Then use the Print & File Window Manager
(PFWM) to select those three graphs and save them to a session file (read how in the
FAQ list). Finally, open that ses file with a text editor.
Here's what it will look like:
Let's analyze the code for the voltage axis graph to discover its underlying pattern, and
figure out how we might reuse it for our own purposes.
This
is the code that sets up the voltage axis graph, with explanatory comments by me.
Be sure to read the Graph class's documentation for a more detailed description
of the various graph methods that are being called. Also, I'm doing this from memory
and may have made a mistake.
Suppose you wanted to use hoc statements to create a graph that plots membrane
potential at the 0.1 location of apical[3] and the (0.4) location of basilar[21]. You want the
x axis to run from 0 to tstop, and the y axis to run from -10 to +5. Here's how you might
follow this pattern to do that:
This will put the graph on your screen at (200, 200). If you don't like where it is, or want
to change the position of the labels and/or color/linestyle of the traces, just drag it to a
better location and use the graph's own menu to make whatever changes you like.
Then use the PFWM to save it to a session file and steal the new coordinates, line
style args, etc. from that file.
Now you're ready to analyze the original ses file and see the pattern that underlies the
code for the current axis and state axis graphs. graphList[1] is for graphs whose y
values are to be plotted vs. t - 0.5*dt, and graphList[2] is for graphs whose y values are
to be plotted vs. t + 0.5*dt. They are useful only if you are using the Crank-Nicholson
method (secondorder == 2) and want the plots of ionic currents and state variables to
be second order correct. If you are using the adaptive integrators (cvode), all variables
are computed at the same t and plots generated with graphList[1] and graphList[2] are
identical to plots of the same variables that are generated with graphList[0].
An exercise for the reader: write an obfunc that spawns a new graph that plots a
user-specified variable vs. t. It should accept these arguments:
--xy location on screen
--a strdef that is the name of the variable to be plotted
--y axis scaling (i.e. ymin and ymax)
--the variables that are to be plotted
--how NEURON will update the plots in the course of a simulation
--position, size, and scaling of the graph
--additional labels, if any
Read about the Graph class here
http://www.neuron.yale.edu/neuron/stati ... graph.html
As far as graph updating is concerned, you will find all kinds of strange looking code in
ModelDB and elsewhere. The best practice is to just let the standard run system take
care of it for you. You can read about this in The NEURON Book--look in the Index for
standard run system / plotting system
especially
standard run system / plotting system / graphLists
and
standard run system / plotting system / incorporating Graphs and objects
But it's even quicker to just steal code from a session file.
Suppose you have a model that has a default section called soma with hh, and you use
the NEURONMainMenu toolbar to create a Voltage axis graph of v(0.5) vs. t, a Current
axis graph of soma.ik(0.5) vs. t, and a State axis graph of soma.m_hh(0.5) vs. t. Also,
you use each Graph's "Change text" to write a label on the graph ("voltage axis",
"current axis", or "state axis" as appropriate). Then use the Print & File Window Manager
(PFWM) to select those three graphs and save them to a session file (read how in the
FAQ list). Finally, open that ses file with a text editor.
Here's what it will look like:
Code: Select all
objectvar save_window_, rvp_
objectvar scene_vector_[8]
objectvar ocbox_, ocbox_list_, scene_, scene_list_
{ocbox_list_ = new List() scene_list_ = new List()}
{
save_window_ = new Graph(0)
save_window_.size(0,5,-80,40)
scene_vector_[5] = save_window_
{save_window_.view(0, -80, 5, 120, 1071, 66, 300.48, 200.32)}
graphList[0].append(save_window_)
save_window_.save_name("graphList[0].")
save_window_.addexpr("v(.5)", 1, 1, 0.8, 0.9, 2)
save_window_.label(0.629393, 0.392971, "voltage axis", 2, 1, 0, 0, 1)
}
{
save_window_ = new Graph(0)
save_window_.size(0,5,-1,1)
scene_vector_[6] = save_window_
{save_window_.view(0, -1, 5, 2, 1069, 333, 300.48, 200.32)}
graphList[1].append(save_window_)
save_window_.save_name("graphList[1].")
save_window_.addvar("soma.ik( 0.5 )", 1, 1, 0.8, 0.9, 2)
save_window_.label(0.261981, 0.819489, "current axis", 2, 1, 0, 0, 1)
}
{
save_window_ = new Graph(0)
save_window_.size(0,5,0,1)
scene_vector_[7] = save_window_
{save_window_.view(0, 0, 5, 1, 1064, 599, 300.48, 200.32)}
graphList[2].append(save_window_)
save_window_.save_name("graphList[2].")
save_window_.addvar("soma.m_hh( 0.5 )", 1, 1, 0.8, 0.9, 2)
save_window_.label(0.332268, 0.479233, "state axis", 2, 1, 0, 0, 1)
}
objectvar scene_vector_[1]
{doNotify()}
figure out how we might reuse it for our own purposes.
This
Code: Select all
{
save_window_ = new Graph(0) // creates but does not display a new Graph
// that lets us control its size and scaling before it is even drawn to the screen
save_window_.size(0,5,-80,40) // axis scaling
scene_vector_[5] = save_window_
{save_window_.view(0, -80, 5, 120, 1071, 66, 300.48, 200.32)} // draws it on the screen
// at a user-specified location (5th and 6th args) and size (last 2 args)
graphList[0].append(save_window_) // graphList[0] is for all graphs whose y values
// are to be plotted vs. t
save_window_.save_name("graphList[0].")
save_window_.addexpr("v(.5)", 1, 1, 0.8, 0.9, 2) // adds v(0.5) to this graph's pliot list
// also specifies line color and style, locaton on canvas where "v(.5)" will be printed
save_window_.label(0.629393, 0.392971, "voltage axis", 2, 1, 0, 0, 1) // just prints the
// string "voltage axis" on the canvas at specified location, color etc.)
}
Be sure to read the Graph class's documentation for a more detailed description
of the various graph methods that are being called. Also, I'm doing this from memory
and may have made a mistake.
Suppose you wanted to use hoc statements to create a graph that plots membrane
potential at the 0.1 location of apical[3] and the (0.4) location of basilar[21]. You want the
x axis to run from 0 to tstop, and the y axis to run from -10 to +5. Here's how you might
follow this pattern to do that:
Code: Select all
objref vg
vg = new Graph(0) // creates but does not display a new Graph
vg.size(0,tstop,-10,5) // axis scaling
// forget about the scene_vector stuff
vg.view(0, -10, tstop, 15, 200, 200, 300.48, 200.32)} // draws it on the screen
// at a user-specified location (5th and 6th args) and size (last 2 args)
graphList[0].append(vg) // graphList[0] is for all objects that are to be
// updated at integer multiples of dt
// forget about the save_name stuff
vg.addexpr("apical[3].v(.1)", 1, 1, 0.8, 0.9, 2)
vg.addexpr("basliar[21].v(.4)", 1, 1, 0.8, 0.7, 2) // put variable name a bit lower on the canvas
vg.label(0.4, 0.9, "two at once!", 2, 1, 0, 0, 1)
to change the position of the labels and/or color/linestyle of the traces, just drag it to a
better location and use the graph's own menu to make whatever changes you like.
Then use the PFWM to save it to a session file and steal the new coordinates, line
style args, etc. from that file.
Now you're ready to analyze the original ses file and see the pattern that underlies the
code for the current axis and state axis graphs. graphList[1] is for graphs whose y
values are to be plotted vs. t - 0.5*dt, and graphList[2] is for graphs whose y values are
to be plotted vs. t + 0.5*dt. They are useful only if you are using the Crank-Nicholson
method (secondorder == 2) and want the plots of ionic currents and state variables to
be second order correct. If you are using the adaptive integrators (cvode), all variables
are computed at the same t and plots generated with graphList[1] and graphList[2] are
identical to plots of the same variables that are generated with graphList[0].
An exercise for the reader: write an obfunc that spawns a new graph that plots a
user-specified variable vs. t. It should accept these arguments:
--xy location on screen
--a strdef that is the name of the variable to be plotted
--y axis scaling (i.e. ymin and ymax)