Page 1 of 2

Defining a POINTER to be a list

Posted: Tue Mar 17, 2015 9:52 pm
by dabliss
I have the following NEURON block in a MOD file:

NEURON {
POINT_PROCESS NMDASynPost
POINTER s[2047]
RANGE e, i, mg_conc, g, b, g_syn[2047]
NONSPECIFIC_CURRENT i
}

When I run modlunit on the file, I get the following error:

model 1.1.1.1 1994/10/12 17:22:51
Checking units of nmdasynpost.mod
syntax error:
syntax is: USEION ion READ list WRITE list:
Illegal block at line 6 in file nmdasynpost.mod
POINTER s[2047]

In this model, a value for s is received from each of 2,047 afferent neurons. Hence, I'd like s to be a list of length 2,047. (What would be even better would be to have s be a list of variable size, in case I decide to change the size of my network later.) What have I done wrong, and how do I fix it?

EDIT: Now that I think about it, I'm not sure how s would ever work as a list (array is what I mean). How would I set the pointer to 2,047 different variables? I'm using NEURON's Python implementation, and there seems to be no way to make h.setpointer accept a many-variable pointer.

(For a related case, see http://www.neuron.yale.edu/phpbb/viewto ... f=16&t=310.)

Many thanks,
Dan

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 8:49 am
by hines
The concept of array of pointers is not implemented in nmodl. So one needs to implement the necessary functionality in the mod file using VERBATIM blocks. This would be particularly easy if
the hoc PtrVector exposed its public double** pd_ wiht a c accessor function like happens with the hoc Vector class. I should do that. In lieu of that, you have to do it all in VERBATIM blocks.
The relevant mod file fragments are

Code: Select all

$ cat pvec.mod
NEURON {
  POINT_PROCESS Foo
  POINTER pvec
}

ASSIGNED { pvec }

PROCEDURE declare_pvec(n) {
VERBATIM
 {
  double*** pd = (double***)(&(_p_pvec));
  *pd = (double**)hoc_Ecalloc((size_t)_ln, sizeof(double*));
 }
ENDVERBATIM
}

PROCEDURE set_pvec(i) {
VERBATIM
 {
  double** pd = (double**)_p_pvec;
  pd[(int)_li] = hoc_pgetarg(2);
 }
ENDVERBATIM
}

FUNCTION getval(i) {
VERBATIM
 {
  double** pd = (double**)_p_pvec;
  _lgetval = *pd[(int)_li];
 }
ENDVERBATIM
}
and here is a test

Code: Select all

$ cat pvec.hoc
x = 1
y = 2
create soma
objref foo
foo = new Foo(.5)
{
foo.declare_pvec(2)
foo.set_pvec(0, &x)
foo.set_pvec(1, &y)
}

foo.getval(0)
x=5
foo.getval(0)

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 3:14 pm
by dabliss
Many thanks! It appears that range variables cannot be arrays as well.

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 5:22 pm
by ted
dabliss wrote:It appears that range variables cannot be arrays as well.
You're thinking about how to implement an array of parameters. Why not use an array of POINTERs for that too? Store the parameter values in a Vector, and link each parameter POINTER to the corresponding Vector element.

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 5:52 pm
by dabliss
Yep, that worked for me.

Code: Select all

Notice: Use of POINTER is not thread safe.
Notice: VERBATIM blocks are not thread safe
I guess I can't run this model in parallel?

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 6:00 pm
by ted
dabliss wrote:I guess I can't run this model in parallel?
True. POINTERs require confining code to a single address space.

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 6:07 pm
by hines
Strictly speaking, POINTER is threadsafe if it points to an address which is part of the same thread. In practice, modulo multisplit, this means it has to point to some variable that is part of
the same cell. So POINTER can be threadsafe if it points to a another mechanism variable that exists in the same compartment or section. However this cannot be automatically determined
by the nmodl translator, so it is up the the author/user to judge whether the usage of the mod file is, in fact, threadsafe and, if so, it is correct to so declare at the beginning of the NEURON block
using the keyword
THREADSAFE

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 6:08 pm
by hines
Mod file ASSIGNED and STATE variables can be declared as arrays. However the size is determined at compile time and is not dynamically adjustable.

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 8:10 pm
by dabliss
Ah, many thanks for the explanation.

Follow-up question: Is it true that, using the code you supplied above (pvec), I don't need to include in my model a call to setpointer?

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 8:40 pm
by hines
Correct. The replacement call in the test is
foo.set_pvec(...)
Note that my mod file contains no checking. Things that can go wrong are: indices < 0 or >= n, Memory that is pointed to is freed, Not all pointers are set.
Segmentatiion violations might occur if the pointers do not point to valid memory. and worse will occur if invalid pointers try to change what they point to.

Re: Defining a POINTER to be a list

Posted: Wed Mar 18, 2015 8:44 pm
by ted
hines wrote:Mod file ASSIGNED and STATE variables can be declared as arrays.
But PARAMETER variables cannot?

Re: Defining a POINTER to be a list

Posted: Thu Mar 19, 2015 11:39 am
by hines
My mistake, PARAMETER variables can also be fixed length array RANGE variables as well

Re: Defining a POINTER to be a list

Posted: Thu Mar 19, 2015 8:34 pm
by dabliss
How would I make a call to set_pvec in Python?

Code: Select all

from neuron import h
x = 1
foo = h.Foo(0.5)
foo.declare_pvec(2)
foo.set_pvec(0, x)
The last line of the above chunk of code raises the following error:

Code: Select all

bad stack access: expecting (double *); really (double)
NEURON: interpreter stack type error
 near line 0
 create soma
            ^
        Foo[0].set_pvec(0, 1)
oc_restore_code tobj_count=1 should be 0
This is because set_pvec is expecting the address of x (&x), which I'm not sure can be passed in Python.

Re: Defining a POINTER to be a list

Posted: Thu Mar 19, 2015 8:53 pm
by hines
Yes. It is not allowed to take the address of the python x reference.
If you can arrange to use range variable (or hoc variables) in place of x, then you can call
foo.set_vec(0, h._ref_x) #where x is the range variable name. In particular

Code: Select all

v = h.Vector(20)
for i in range(len(v)):
  foo.set_vec(i, v._ref_x[i])
might prove helpful.

Re: Defining a POINTER to be a list

Posted: Tue Aug 11, 2020 2:44 am
by itaru
Hello,
I am facing the same issue, but time is now 2020. Dear experts, is there an easy way to
accomplish to declare an array of POINTERs in a Point Process?