Creating NetCon with null source in NEURON+Python

When Python is the interpreter, what is a good
design for the interface to the basic NEURON
concepts.

Moderator: hines

Post Reply
pascal
Posts: 62
Joined: Thu Apr 26, 2012 11:51 am

Creating NetCon with null source in NEURON+Python

Post by pascal » Wed Feb 01, 2017 9:52 am

I am trying to translate the following hoc code into Python (where nil is an unassigned objref, and syn is some generic synapse):

Code: Select all

nc=new NetCon(nil, syn)
I initially tried

Code: Select all

nc=h.NetCon(None,syn)
but I received a "hoc error". Then, after reading viewtopic.php?f=2&t=1333, I tried

Code: Select all

h("nc = new NetCon(nil,syn)")
nc=h.nc
However this gave the error "hoc.HocObject' object has no attribute 'nc'. I've googled around and read the NetCon documentation, but I still haven't manged to figure it out. Thanks for the help.

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

Re: Creating NetCon with null source in NEURON+Python

Post by ted » Wed Feb 01, 2017 10:37 am

error "hoc.HocObject' object has no attribute 'nc'"
because you forgot
h("objref nc")
(been there, done that).

Here's an entire sequence that works:
h("create soma")
h("objref syn")
h("soma syn = new ExpSyn(0.5)")
h("objref nil, nc")
h("nc = new NetCon(nil,syn)")

There must be a more pythonic way to do this. Maybe there's something useful in
Scripting NEURON with Python
which you'll find on the Documentation page http://www.neuron.yale.edu/neuron/docs
Also check out
Lytton et al.
Simulation Neurotechnologies for Advancing Brain Research: Parallelizing Large Networks in NEURON
Neural Comput. 28:2063-90, 2016

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

Re: Creating NetCon with null source in NEURON+Python

Post by ted » Wed Feb 01, 2017 11:11 am

This works although it does have just a bit of hoc--

from neuron import h
soma = h.Section()
syn = h.ExpSyn(soma(0.5))
h("objref nil") # the tainted statement
nil = h.nil
nc = h.NetCon(nil,syn)

pascal
Posts: 62
Joined: Thu Apr 26, 2012 11:51 am

Re: Creating NetCon with null source in NEURON+Python

Post by pascal » Fri Feb 03, 2017 11:12 am

That is really helpful--thank you! One more question, though. I am having trouble getting this newly-crated NetCon to actually do anything. Using the following code

Code: Select all

from neuron import h, gui
soma=h.Section()
soma.insert('pas')
syn=h.ExpSyn(soma(0.5))

#create netcon
h("objref nil")
nil=h.nil
nc=h.NetCon(nil,syn)
nc.weight[0]=1.0

#prescribe synaptic event to occur
nc.event(30)

h.tstop = 60 #ms
h.run()

#(code for plotting omitted)
I get the following result, no matter how large I set nc.weight to be:

Image

I read in the NetCon documentation that "NetCon can currently only be used if a CVode object exists," but I couldn't find any more details. So do I need to somehow create a cvode object and get that to enable the NetCon?

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

Re: Creating NetCon with null source in NEURON+Python

Post by ted » Fri Feb 03, 2017 12:30 pm

h.allobjects("CVode")
will tell you how many instances of CVode exist.
Examples:

Code: Select all

$ nrniv -python -
NEURON -- VERSION 7.5 (1512:e0bd0137f04c) 2017-01-30
Duke, Yale, and the BlueBrain Project -- Copyright 1984-2016
See http://neuron.yale.edu/neuron/credits

>>> from neuron import h
>>> h.allobjects("CVode")
0.0
so none exist. Ignore the "0.0"--that's a numerical value that allobjects() returns regardless of how many instances of the quoted class exist.
However

Code: Select all

$ nrngui -python
 . . .
>>> from neuron import h
>>> h.allobjects("CVode")
CVode[0] with 2 refs
so starting NEURON by calling nrngui ensures there will be a single instance of CVode.
You'll get the same result if you start NEURON by calling nrniv, then import not only h but also gui

Code: Select all

$ nrniv -python
 . . .
>>> from neuron import h, gui
>>> h.allobjects("CVode")
CVode[0] with 2 refs
You'll get the same result without import gui if you just
h('load_file("stdgui.hoc")')
right after importing h. Don't worry about the "gui" in the file name--it will work even on a machine running NEURON without a gui, and you'll have the benefit of NEURON's complete standard run library.

Now, assuming that you are doing things in such a way that there is at least one CVode instance, here's why no events are happening:
You're probably executing nc.event during or after model setup, then initializing and running a simulation. nc.event is indeed putting an event into the delivery queue, but initialization clears the queue before the simulation even starts! That's a feature not a bug--if the run system didn't work that way, leftover events from previous runs would corrupt the current run.

You need a custom initialization that, after all other initialization is complete, puts your desired events into the queue. Do that with an FInitializeHandler. Here's an example in hoc

Code: Select all

objref fih
fih = new FInitializeHandler("nc.event(1)")
and an example in Python that does exactly the same thing but uses nrnpython to call hoc from Python:

Code: Select all

fih = h.FInitializeHandler('nrnpython("nc.event(1)")')
In the latter, note which quotes are double " and which are single '.

pascal
Posts: 62
Joined: Thu Apr 26, 2012 11:51 am

Re: Creating NetCon with null source in NEURON+Python

Post by pascal » Mon Feb 06, 2017 9:48 am

Thanks, this works perfectly now. I really appreciate the help.

I am curious why importing gui automatically creates an instance of CVode. I know CVode implements adaptive time step numerical integration, with a separate "stream" for each neuron in the simulation. Is CVode the default numerical integration technique when gui is imported, and fixed-step-size backward Euler the default when gui is not imported? I have read chapters 4 and 7 from "The NEURON Book," but I still don't understand which integration scheme is the default, or how it may be changed. Thanks.

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

Re: Creating NetCon with null source in NEURON+Python

Post by ted » Mon Feb 06, 2017 11:07 am

pascal wrote:why importing gui automatically creates an instance of CVode.
Among other things, it makes hoc execute the contents of nrn/share/nrn/lib/hoc/stdrun.hoc . Read the first few statements of that file and you'll see the one that creates a CVode instance. That statement is there because some features of NEURON require an instance of CVode to exist (for reasons too complex and irrelevant to go into here).
I know CVode implements adaptive time step numerical integration, with a separate "stream" for each neuron in the simulation.
Part of what you "know" is correct and part appears to be misinterpretation of the documentation (which is often rather opaque). Come to think of it, practically everything that any of us "knows" is a mix of truth, falsehood, approximations, and guesses. The problem is how to discern the "true truths" from the "untrue truths" and the "completely wild *ss guesses." Only in some (often nearly) trivial cases is it possible to be absolutely sure which is which. This is one of those cases.

Summary of NEURON's integration methods (the last section in Chapter 4 of The NEURON Book) spells it out fairly clearly. I should mention the following:
1. When a CVode instance exists, whether or not NEURON uses adaptive integration is controlled by CVode.active() (read about that in the Programmers' Reference documentation of the CVode class). If adaptive integration is NOT being used, then one of the fixed step methods is used.
2. Even if adaptive integration is being used, time is a global variable by default (at any given instant, t has the same value in all cells). Use of local variable time step integration (each cell has its own t) is controlled by a boolean switch--read the Programmers' Reference about the CVode class's use_local_dt().

Now back to the question of whether to
import gui
For your particular situation, you could just as easily have done this instead
from neuron import h
cvode = h.CVode()
However
import gui
brings along many useful things, which is why I prefer
from neuron import h, gui
and it's also easier to type.

pascal
Posts: 62
Joined: Thu Apr 26, 2012 11:51 am

Re: Creating NetCon with null source in NEURON+Python

Post by pascal » Mon Feb 06, 2017 7:48 pm

Great, thanks so much for the thorough explanation. I feel like when it comes to NEURON's integration schemes, I now harbor fewer unknown unknowns, more known unknowns, and maybe even one or two known knowns. :-)

ramcdougal
Posts: 138
Joined: Fri Nov 28, 2008 3:38 pm
Location: Yale School of Medicine

Re: Creating NetCon with null source in NEURON+Python

Post by ramcdougal » Fri Jun 09, 2017 10:49 pm

h.FInitializeHandler normally takes a function that is to be called whenever NEURON initializes; i.e. we would normally say

Code: Select all

def my_initializer():
    # do stuff here...
fih = h.FInitializeHandler(my_initializer)
To handle situations where we want to always send the function an argument or arguments, instead of sending in the function handle, provide a tuple with the function as the first entry and the arguments as the subsequent ones. i.e. to always call nc.event(1) every time NEURON initializes, use:

Code: Select all

fih = h.FInitializeHandler((nc.event, 1))


This works in general in NEURON and is often useful for callbacks from GUI buttons (e.g. to allow one function to handle multiple buttons).

As far as the NetCon goes, if the source is null, use Python's None.

JustasB
Posts: 14
Joined: Tue Dec 08, 2015 8:17 pm

Re: Creating NetCon with null source in NEURON+Python

Post by JustasB » Sat Dec 30, 2017 4:42 pm

To summarize, the following, fully Python, code will stimulate a synapse at 50, 60, and 100 ms:

Code: Select all

from neuron import h, gui

soma=h.Section()
soma.insert('pas')

syn=h.ExpSyn(soma(0.5))
nc=h.NetCon(None,syn)
nc.weight[0]=1.0

def synStim():
	nc.event(50)
	nc.event(60)
	nc.event(100)

fih = h.FInitializeHandler(synStim)

h.tstop = 150
h.run()
Plotting v, should result in the following graph (note the excitatory pulses at 50, 60, and 100 ms):
Image

Notes:
- "import gui" ensures CVode object is present
- When creating the NetCon, Python's None object is interpreted as HOC's NULLobject
- NetCon's event(t) method needs to be executed after NEURON initializes the simulation

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

Re: Creating NetCon with null source in NEURON+Python

Post by ted » Sun Dec 31, 2017 12:16 pm

Nice summary, but wouldn't you like to eliminate the big transient that dominates the first 10 ms of the simulation? The model cell's resting potential is -70 mV ( == e_pas) so simply execute the statement
h.v_init = -70
before calling h.run() (a good place would be right after specification of cellular properties, i.e. right after inserting pas into soma).

Post Reply