Accessing fields and functions of a NMODL object in NMODL

NMODL and the Channel Builder.
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Accessing fields and functions of a NMODL object in NMODL

Post by mctavish »

As a follow-up to this post, viewtopic.php?f=16&t=969, I'm working on multicompartment LIF neurons.

I am communicating between compartments with NetCons, but I am running into problems with using net_event for some communication because the parameters are passed by reference and I negate some of what I need when two events are simultaneous. I also have to jump through hoops to make it so that the event does not propagate back onto itself, which I can do, but I'm generating events that only get ignored, which is rather wasteful....

I can avoid all of my issues if I can talk directly to my ARTIFICIAL_CELL objects that a given ARTIFICIAL_CELL of mine needs to talk to and keep net_event for those cases where I fire action potentials. What I cannot figure out is how to properly get a reference to an object (I'm confused on Objects, Symbols, and Props and the associated fields). What I want in my NMODL code is something like:

Code: Select all

NET_RECEIVE(w) {
      .
      .
VERBATIM {
    Point_process* target;
    double* pweight;
    double* pthresh;
    double* pdel;

    int pscount, cnt;
    if (_pnt->presyn_) { // _pnt is an implicit parameter of this MyArtCell
        pscount = nrn_presyn_count(_pnt->presyn_);
//	printf("   This point process is %.0f and sources %d NetCons\n", (double)((long)_pnt), pscount);
        for (i=0; i < pscount; ++i) {
            cnt = nrn_netcon_info(nrn_presyn_netcon(_pnt->presyn_, i),
                &pweight, &target, &pthresh, &pdel);

           // These two lines is what is unavailable and I need to know how to code for correctly in NMODL.
            MyArtCell* myArtCellP = (MyArtCell*)(target);
            myArtCellP->myFunction(some, vars);
        }
    }
}
ENDVERBATIM
}
hines
Site Admin
Posts: 1710
Joined: Wed May 18, 2005 3:32 pm

Re: Accessing fields and functions of a NMODL object in NMODL

Post by hines »

Code: Select all

            myArtCellP->myFunction(some, vars);
After an nrnivmodl, look at the c code that is generated by nocmodl, in an i686, or x86_64, or umac subdirectory, and observe the prototype for
myFunction (I presume, because there are VERBATIM blocks and you are not
forcing THREADSAFE, that the code emitted will have a second line that reads
/*NOT VECTORIZED*/ )
Feel free to add printf statements to the code and do another nrnivmodl to observe things. The c code is not re-translated unless the mod
file changes. Anyway, I have the feeling that in your case the statement

Code: Select all

    myFunction(some, vars);
is sufficient since the _p and _ppvar arrrays have been set up at the beginning of the net_receive function.
If you are forcing THREADSAFE, then the function call arglist is prefixed by explicit references to
double* p, Datum* _ppvar, Datum* _thread, _NrnThread* _nt, some, vars)
and call it using the values defined near the beginning of the _net_receive function.
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Re: Accessing fields and functions of a NMODL object in NMODL

Post by mctavish »

Thanks, Michael.

I was not clear enough. I wanted the title of this post to be "Accessing fields and functions of one NMODL object from another NMODL object", but I did not have the space in the Title field to make it so.

Yes, I'm using heavy use of printf statements to get a clearer picture of what is going on.

What I want to do in my instance of my artificial cell (which is a not really a cell, but is a segment of cable) is communicate with adjacent segments when it receives an external event. My thought was that I could find adjacent segments because they are connected via NetCons. The target field from the nrn_netcon_info() function contains pointers to Point_process objects, which are, in fact, the ARTIFICIAL_CELL objects I want to call into.

Because these are ARTIFICIAL_CELLs, they have a NET_RECEIVE() function, which I imagine I can call directly with my own set of parameters, bypassing how it would be called when calling net_send() or I could call MyFunction(), which I know is also part of these objects, and keep NET_RECEIVE() for more explicit network/spiking activity. Either way, I don't know how to call into NET_RECEIVE() or MyFunction() given these objects in the target field. How can I do that?
hines
Site Admin
Posts: 1710
Joined: Wed May 18, 2005 3:32 pm

Re: Accessing fields and functions of a NMODL object in NMODL

Post by hines »

In the netreceive, save the _p and _ppvar pointers and assign them to the proper values
from your Point_process structure. After you call the myfunction, restore the original and
use the return value.
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Re: Accessing fields and functions of a NMODL object in NMODL

Post by mctavish »

Thanks again, Michael.

In the c code, I see

Code: Select all

#define _p_aPointerP  _ppvar[2].pval
And I can access the target's aPointerP variable via

Code: Select all

target->_prop->dparam[2].pval
What remains unclear is how to call target's myFunction(), not this object's myFunction().

Since target is a pointer to a Point_process, it does not have myFunction(), but I do not see how to access an index in the object's member function list.

Tom
hines
Site Admin
Posts: 1710
Joined: Wed May 18, 2005 3:32 pm

Re: Accessing fields and functions of a NMODL object in NMODL

Post by hines »

First, check the c translation to see if the method you want to call is extern and if not,
you need to declare the method EXTERNAL in the NEURON block of the mod file that defines the method.
This will make it global scope instead of static file scope (take a look at the c code) so you can call it.
Second, if the c code containing the method is vectorized, then you can call the method directly from the
other model by filling in the proper arguments that you can get from the Point_process* through the
Prop structure, and from the
memb_list[type] structure (Memb_list[type]._thread but which is probably nil anyway).
I presume you are using only one thread so that it is safe for one mod to call any other with the _nt
arg. If the c code containing the method is not vectorized, then it will be difficult to set the _p and _ppvar
properly since those are static file scope. If so, force the vectorization with THREADSAFE and you will likely
be able to safely use a single thread even with arbitary VERBATIM stuff.
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Re: Accessing fields and functions of a NMODL object in NMODL

Post by mctavish »

Thanks again, Michael.

In trying to circumnavigate the NetCon way of handling events, I'm thinking it is best to try and stay within that way of doing things, especially since I want to be able to operate across multiple threads. That being said, what I really would like to do is call net_event(), but specify a subset of postsynaptic targets instead of broadcasting to all of them. In my particular case, I have dendritic sections that pass messages to adjacent sections, but I also have synapses that get activated by the dendrites when action potentials are in the dendrites (the mitral-granule circuit). I want to specify my targets when I send a net_event so that I can discriminate subthreshold events from those that cross threshold. Since adjacent sections form NetCons with each other, one thing I need is to not send the net_event() to the adjacent compartment that sent the event. (Right now, I'm putting the event on the queue and have a flag to ignore it). Additionally, if it is a subthreshold event, I only want to send it down the cable, and not to any attached postsynaptic objects.
hines
Site Admin
Posts: 1710
Joined: Wed May 18, 2005 3:32 pm

Re: Accessing fields and functions of a NMODL object in NMODL

Post by hines »

I'm afraid that in the absence of VERBATIM blocks or changing NEURON's event api you would need to
have a separate POINT_PROCESS at each location that needs to send events to a specific set of POINT_PROCESSes
in other compartments
and perhaps make use of the WATCH statement to watch various threshold variables changed by other
POINT_PROCESSes at the same location. If v is sufficient then great. Otherwise you need to make
use of POINTER to look at threshold variables in other POINT_PROCESS instances.
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Re: Accessing fields and functions of a NMODL object in NMODL

Post by mctavish »

I am using VERBATIM blocks. I have some functions that are completely encased in VERBATIM blocks, but they do not need to be, but I at least need VERBATIM within my NET_RECEIVE function. Is that a problem for multithreading?

Right now, I am modeling each dendritic section as an ARTIFICIAL_CELL, so each section is a POINT_PROCESS. Adjacent dendritic sections have two NetCons between them (A->B and B->A). I am encapsulating in the "weight" vector the process that sent the last event and the event before that so that I can avoid feedback. I can do something similar with the synaptic objects, but I'd rather not place events on the queue in the first place. I'll send the code in a separate email.
hines
Site Admin
Posts: 1710
Joined: Wed May 18, 2005 3:32 pm

Re: Accessing fields and functions of a NMODL object in NMODL

Post by hines »

I use the word, "ARTIFICIAL_CELL", to refer to mechanisms that have no BREAKPOINT or SOLVE block and therefore do no computation except when an event arrives. The only way it can affect the rest of the system is by sending an event using net_event(...). Of course all bets are off when one adds VERBATIM into the mix.

I do not think it is a good idea to avoid the queue since presumably there is a positive delay between the time you initiate an event in artficial cell A and the time you want it delivered to artificial cell B. (0 delay events CANNOT be interthread events. But don't worry about threads for now. You need to get things working in a single thread simulation.) So it makes sense to have your NET_RECEIVE block, instead of calling net_event(...), call the NetCon.send() method directly for the NetCon that connects A to B and just make sure that that NetCon does not appear in the PreSyn list of NetCons that is associated with A.

You can do the latter by using
nc = new NetCon(nil, B)
and passing nc to a method you write for A that stores it. You can do the former by calling (VERBATIM) in your A NET_RECEIVE block a function called
void nrn_netcon_send(void* netcon_pointer, double tdeliver);
The netcon_pointer is nc->u.this_pointer when you get the nc object argument.

Be sure to set ParallelContext.set_maxstep properly so that it is consistent with your minimum A->B delay. Since there is no source for the netcon, the system otherwise might not include it in its minimum delay calculation (I can't remember and don't want to look). If the delay is > 0 then I expect this to work when A and B are in different threads as well. Note that you can use the NetCon weight vector to provide information about what the source is when you send an event that is to arrive at A.
hines
Site Admin
Posts: 1710
Joined: Wed May 18, 2005 3:32 pm

Re: Accessing fields and functions of a NMODL object in NMODL

Post by hines »

Sorry. I made a mistake in my previous message. The name of the c function is
void nrn_netcon_event(void* netcon_pointer, double tdeliver)
Note that we are not using NetCon delay at all. So when you call it use an arg value
of t + delay
and make sure that delay is >= to your arg to ParallelContext.set_maxstep
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Re: Accessing fields and functions of a NMODL object in NMODL

Post by mctavish »

Thanks Michael. I'll have a go at it, but it looks like today I have to update my system....

Anyway, yes, I am using ARTIFICIAL_CELLs precisely because I am only doing events-based processing.

I'll let you know how I go in the next day or two.
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Re: Accessing fields and functions of a NMODL object in NMODL

Post by mctavish »

I'm done updating my system and trying to knock this all out now....

I'm not clear how to make an instance of an ARTIFICIAL_CELL to have a reference or pointer to a NetCon. I can see how objects can be passed in and remain local to PROCEDUREs and FUNCTIONs, or assigned to static and global variables for all instances of my ARTIFICIAL_CELL type, but it only seems RANGE and POINTER (to doubles) are the only member variable types I can have. How can I have member variables?
hines
Site Admin
Posts: 1710
Joined: Wed May 18, 2005 3:32 pm

Re: Accessing fields and functions of a NMODL object in NMODL

Post by hines »

Use the idiom found in
nrn/share/examples/nrniv/netcon/vecevent.mod where a
Vector is given to a POINT_PROCESS (that in fact should now
be ARTIFICIAL_CELL) and stored for use in a NET_RECEIVE block.
The same idiom is used in the built-it nrn/src/nrnoc/pattern.mod .
mctavish
Posts: 74
Joined: Tue Mar 14, 2006 6:10 pm
Location: New Haven, CT

Re: Accessing fields and functions of a NMODL object in NMODL

Post by mctavish »

In my hoc file, I am doing the following:

Code: Select all

objref A, B, nc, nil
A=new MyArtCell()
B=new MyArtCell()
nc=new NetCon(nil,B)
A.setNC(nc)
Regarding my mod file, I assume I should do something like this:

Code: Select all

ASSIGNED {
    netcon
}

PROCEDURE setNC() {
VERBATIM {
	if (ifarg(1)) {  // nc object passed in from hoc
		void** ptr;
		ptr = (void**)(&netcon);
		*ptr = *hoc_objgetarg(1);
	}
}
ENDVERBATIM
}

VERBATIM
extern void nrn_netcon_event(void* netcon_pointer, double tdeliver);
ENDVERBATIM
NET_RECEIVE(w) {
VERBATIM {
    nrn_netcon_event(*(void **)(&netcon), t+del);
}
ENDVERBATIM
}
But when I run, I crash with "NULLobject target is missing". Any ideas?
Last edited by mctavish on Wed Apr 01, 2009 4:49 pm, edited 3 times in total.
Post Reply