Defining a POINTER to be a list

NMODL and the Channel Builder.
dabliss
Posts: 7
Joined: Fri Feb 20, 2015 3:28 pm
Location: UC Berkeley

Defining a POINTER to be a list

Post 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
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: Defining a POINTER to be a list

Post 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)
dabliss
Posts: 7
Joined: Fri Feb 20, 2015 3:28 pm
Location: UC Berkeley

Re: Defining a POINTER to be a list

Post by dabliss »

Many thanks! It appears that range variables cannot be arrays as well.
ted
Site Admin
Posts: 6286
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Defining a POINTER to be a list

Post 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.
dabliss
Posts: 7
Joined: Fri Feb 20, 2015 3:28 pm
Location: UC Berkeley

Re: Defining a POINTER to be a list

Post 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?
ted
Site Admin
Posts: 6286
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Defining a POINTER to be a list

Post by ted »

dabliss wrote:I guess I can't run this model in parallel?
True. POINTERs require confining code to a single address space.
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: Defining a POINTER to be a list

Post 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
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: Defining a POINTER to be a list

Post 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.
dabliss
Posts: 7
Joined: Fri Feb 20, 2015 3:28 pm
Location: UC Berkeley

Re: Defining a POINTER to be a list

Post 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?
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: Defining a POINTER to be a list

Post 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.
ted
Site Admin
Posts: 6286
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Defining a POINTER to be a list

Post by ted »

hines wrote:Mod file ASSIGNED and STATE variables can be declared as arrays.
But PARAMETER variables cannot?
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: Defining a POINTER to be a list

Post by hines »

My mistake, PARAMETER variables can also be fixed length array RANGE variables as well
dabliss
Posts: 7
Joined: Fri Feb 20, 2015 3:28 pm
Location: UC Berkeley

Re: Defining a POINTER to be a list

Post 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.
hines
Site Admin
Posts: 1682
Joined: Wed May 18, 2005 3:32 pm

Re: Defining a POINTER to be a list

Post 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.
itaru
Posts: 27
Joined: Wed Jan 29, 2020 10:15 pm
Contact:

Re: Defining a POINTER to be a list

Post 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?
Post Reply