overlaid range variable plots

Anything that doesn't fit elsewhere.
Post Reply
ramcdougal
Posts: 270
Joined: Fri Nov 28, 2008 3:38 pm
Location: Yale School of Public Health

overlaid range variable plots

Post by ramcdougal »

I want to plot the concentrations cai and ip3i versus position every plotEvery milliseconds, all on the same graph.

I have some code that works, but it draws the lines manually and is not particularly elegant:

Code: Select all

w=h.Graph()
w.size(0, totalLength, 0, 2)
w.color(1)
w.label('cai')
w.color(2)
w.label('ip3i')

for i in range(1, numPlots+1):
    # advance to next time point to plot
    h.cvode.solve(i*plotEvery)

    # calcium curve
    w.color(1)                     # black
    w.beginline()
    for seg in stick:
        w.line(seg.x*totalLength, 1000*seg.cai)
        
    # IP3 curve
    w.color(2)                     # red
    w.beginline()
    for seg in stick:
        w.line(seg.x*totalLength, 1000*seg.ip3i)

    # update display
    w.flush()

I tried to be clever and use addexpr and plot to make more readable code:

Code: Select all

w=h.Graph()
w.size(0, totalLength, 0, 2)
w.color(1)
w.addexpr('cai','cai(x)*1000')
w.color(2)
w.addexpr('ip3i','ip3i(x)*1000')
stick.push()
w.family(1)

for i in range(1, numPlots+1):
    # advance to next time point to plot
    h.cvode.solve(i*plotEvery)

    # plot the curves
    for seg in stick:
        h('x=%f' % (seg.x))
        w.plot(seg.x*totalLength)
    w.begin()
The above almost works, but it messes up the colors. Everything gets drawn in red, except for the first cai curve. The specs for graph.family say using .family(1) causes the colors to stay fixed, which is what happens. How can I keep lines and keep distinct colors? I'd also like to get rid of the hack for setting x.

A related question: when I'm done, I want to save the graph. I use w.printfile('output.ps'). Problem: It cuts off the bottom labels. How do I get it to not do that?

Thanks.
ted
Site Admin
Posts: 6394
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: overlaid range variable plots

Post by ted »

Here's the strategy that I would follow if I had a programming task that required such a graph:
1. Use the GUI to construct two different range variable plots.
2. Save the two graphs to a ses file.
3. Read the ses file to discover the appropriate hoc statements to do what you want.
4. (optional--necessary only if step 3 doesn't produce a big "AHA!") Use hoc to implement a single graph that combines two different range variable plots. Basically this means copying the ses file, then making minor edits to the copy that combine the two plots in one Graph object and assign the desired colors to them.
5. Inspired by step 3 (and possibly step 4), write the necessary python.

A further comment: can you take advantage of the standard run system to deal with updating graphs? For smooth updates of range variable plots one would ordinarily use the GUI's "MovieRun" tool. This is implemented with hoc, so in principle you could exercise the underlying code under direct program control. Check out nrn/lib/hoc/movierun.hoc and see if you can discover how.
ramcdougal
Posts: 270
Joined: Fri Nov 28, 2008 3:38 pm
Location: Yale School of Public Health

Re: overlaid range variable plots

Post by ramcdougal »

I do not want smooth updates of RangeVarPlots. I want to see (effectively) RangeVarPlots for different time values overlapping each other, as in the first two code examples. The problem is that RangeVarPlot seems to ignore the keeplines property; even if you call .family(1), the previous lines disappear whenever you do .flush(). For example, when I run the following bit of code:

Code: Select all

w=h.Graph()                           # create graph window
w.size(0, totalLength, 0, .002)       # set axes
stick.push()
cai_rvp=h.RangeVarPlot('cai')
cai_rvp.begin(0)
cai_rvp.end(1)
ip3i_rvp=h.RangeVarPlot('ip3i')
ip3i_rvp.begin(0)
ip3i_rvp.end(1)
w.addobject(cai_rvp, 1, 1)
w.addobject(ip3i_rvp, 2, 1)
w.family(1)

# run simulation
for i in range(1, numPlots+1):
    # advance to next time point to plot
    h.cvode.solve(i*plotEvery)

    # update display
    w.flush()
    
# save output
w.printfile('output.ps')
I end up with exactly two curves: cai and ip3i at the last time point.

The two bits of code I gave previously both correctly overlay the curves for different times. That is, I can see the curves for both cai and ip3i at times plotEvery, 2*plotEvery, 3*plotEvery, etc... overlaid on the same graph.

How can I get RangeVarPlot to respect keeplines, or plot to respect keeplines without messing up the colors, or what is another more elegant way of expressing the first bit of code?

Also, when I do .printfile, the labels get cutoff. How can I avoid that problem?

Thanks.
ted
Site Admin
Posts: 6394
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: overlaid range variable plots

Post by ted »

In hoc one would
g.exec_menu("Keep Lines")
to toggle it on or off.
How can I get . . . plot to respect keeplines without messing up the colors
Suggestion: run neurondemo, select the "stylized" model, and save the graph that shows the range variable plots to a ses file. Then read the ses file.
when I do .printfile, the labels get cutoff. How can I avoid that problem?
Do you mean variable name labels, or axis labels? For the former, just be careful about where they are placed. Create the graph, move the variable name to where you want it, and save the graph to a ses file. Then read the ses file to discover the coordinates in the addvar or addexpr statement, and use those in your own hoc code.

As far as the axis labels are concerned--the algorithms used by InterViews to automatically select axis scaling and overall graph scaling often map axis labels outside the frame that is printed. If you are handy with PostScript, you might try tinkering with the BoundingBox specs in the printed file. Alternatively you could use the Graph's "Set View" to fiddle with the limits specified in the X size and Y size fields so that axis labels are not clipped and also that InterViews doesn't pick very weird placements for the tick marks. For example, if X size is initially 0 100 and Y size is 0 1000, the bottom of the x axis labels will be clipped and the 1 of the y axis's 1000 will also be clipped. Changing the X size to -4 100 takes care of the Y axis's 1000 label, and changing the Y size to -5 1000 moves the X axis labels up to where they're not clipped. Once you have discovered the proper specs, save the graph to a ses file and steal reusable hoc code from it that will replicate the exact axis specifications (for an example of the latter, see
How to use hoc to plot a variable vs. time viewtopic.php?f=30&t=552
in the NEURON hacks area of the Forum).
ramcdougal
Posts: 270
Joined: Fri Nov 28, 2008 3:38 pm
Location: Yale School of Public Health

Re: overlaid range variable plots

Post by ramcdougal »

RangeVarPlots will respect Keep Lines if you add them to the flush_list and display them using h.flushPlot() (but not w.flush()). My final working code is

Code: Select all

w=h.Graph()                                    # create graph window
w.size(-totalLength*.05, totalLength, -.0001, .002)  # set axes
stick.push()
cai_rvp=h.RangeVarPlot('cai')
cai_rvp.begin(0)
cai_rvp.end(1)
ip3i_rvp=h.RangeVarPlot('ip3i')
ip3i_rvp.begin(0)
ip3i_rvp.end(1)
w.addobject(cai_rvp, 1, 1)
w.addobject(ip3i_rvp, 2, 1)
w.exec_menu('Keep Lines')
h.flush_list.append(w)

#
# run simulation
#

for i in range(1, numPlots+1):
    # advance to next time point to plot
    h.cvode.solve(i*plotEvery)

    # start with a clear window for the first plot
    if i==1:
        w.flush()

    # update display        
    h.flushPlot()
I use a flush when i==1 because the initial condition is plotted before the for loop, and I don't want to display those. I can live with this two line hack to clear the initial condition.

The suggestion about playing with the size to avoid having the axis labels cropped off worked great.

Thanks for all your help.
ted
Site Admin
Posts: 6394
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: overlaid range variable plots

Post by ted »

The suggestion about playing with the size to avoid having the axis labels cropped off worked great.
Yes, but it's fiddly and a pain in the neck. There must be a Python package that, with a bit of effort, can be used for such tasks.
Post Reply