localobj acts strangely

The basics of how to develop, test, and use models.
Post Reply
tedballou

localobj acts strangely

Post by tedballou »

I am working on a recursive function that requires local copies of section references, and I am having trouble getting it to behave.

In the first example, the SectionRef variable is declared both globally and in the localobj statement. When i run the function, changes in the variable "s" seem to appear only in the global version, as reported in the "psection" output after the oc> prompt.

In the second example (after the ~~~~'s) I omit the global declaration; now the function fails, behaving as if the objref was not declared.

I'm running MS windows XP pro.

Thanks for the help -- TedB


with objref declared in my global file and this for foobar1:

Code: Select all

proc foobar1(){ localobj s
    strdef mystr, mysec
    mysec=$s1
    sprint(mystr, "access %s", mysec)
    execute(mystr)
    soma s = new SectionRef()
    s.sec {psection()}
    sprint(mystr, "%s s = new SectionRef()", mysec)
    execute(mystr)
    s.sec {psection()}
}
the function causes changes in the global version of s, not the local one.


NEURON -- Release 7.0 (281:80827e3cd201) 2009-01-16
Duke, Yale, and the BlueBrain Project -- Copyright 1984-2008
See http://www.neuron.yale.edu/credits.html

1
1
1
1
oc>access soma
oc>psection()
soma { nseg=1 L=30 Ra=35.4
/*location 0 attached to cell 0*/
/* First segment only */
insert morphology { diam=30}
insert capacitance { cm=1}
insert IClamp { del=1 dur=9 amp=10}
insert pas { g_pas=0.001 e_pas=-70}
}
1
oc>foobar1("dend")
soma { nseg=1 L=30 Ra=35.4
/*location 0 attached to cell 0*/
/* First segment only */
insert morphology { diam=30}
insert capacitance { cm=1}
insert IClamp { del=1 dur=9 amp=10}
insert pas { g_pas=0.001 e_pas=-70}
}
soma { nseg=1 L=30 Ra=35.4
/*location 0 attached to cell 0*/
/* First segment only */
insert morphology { diam=30}
insert capacitance { cm=1}
insert IClamp { del=1 dur=9 amp=10}
insert pas { g_pas=0.001 e_pas=-70}
}
oc> s.sec {psection()}
dend[0] { nseg=1 L=100 Ra=35.4
soma connect dend[0] (0), 1
/* First segment only */
insert morphology { diam=1}
insert capacitance { cm=1}
insert pas { g_pas=0.001 e_pas=-70}
}
oc>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If I omit the global declaration of

Code: Select all

objref s
and restart NEURON, function execution fails:

oc>foobar1("dend")
soma { nseg=1 L=30 Ra=35.4
/*location 0 attached to cell 0*/
/* First segment only */
insert morphology { diam=30}
insert capacitance { cm=1}
insert IClamp { del=1 dur=9 amp=10}
insert pas { g_pas=0.001 e_pas=-70}
}
nrniv: syntax error
near line 18
{dend s = new SectionRef()}
^
execute("dend s = new SectionRef()" )
foobar1("dend" )
nrniv: execute error: dend s = new SectionRef()
near line 18
^
tedballou

Re: localobj acts strangely

Post by tedballou »

This code seems to work OK:

Code: Select all

proc foobar1(){ localobj s
    strdef mystr, mysec
    mysec=$s1
    sprint(mystr, "access %s", mysec)
    execute(mystr)
    psection()
    s = new SectionRef()
    //sprint(mystr, "%s s = new SectionRef()", mysec)
    //execute(mystr)
    s.sec {psection()}
}
I guess I don't need the explicit section identifier to precede the object, as I supposed from the man page syntax,
  • section sref = new SectionRef()
Is that correct?
later, TedB
tedballou

Re: localobj acts strangely

Post by tedballou »

AND I read on the man page for "access" that
The access statement should not be used within a procedure or function.
which of course is violated by my code that works. What's the right way?

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

Re: localobj acts strangely

Post by ted »

The access statement pushes the specified section onto the section stack, making that the default section until the next access statement comes along. When code calls access multiple times, it is very easy to become confused about which section is being referred to. Code tends to be easier to understand, debug, and maintain if it executes access only once, defining a section that is of particular interest as the default section. The "section stack" syntax
sectionname statement
or
sectionname { compound statement }
should be used in all situations in which it becomes necessary to treat some other section as the currently accessed section. It pushes the named section onto the section stack, does whatever the statement(s) specify but with the named section as the default section, and then pops the section back off of the stack, thereby restoring the original default section. You can read more about the concept "currently accessed section" in 5.3.1 Which section do we mean? in The NEURON Book (pages 98-100), or, If you do not have The NEURON Book, in http://www.neuron.yale.edu/ftp/ted/book ... xedref.pdf
ted
Site Admin
Posts: 5810
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: localobj acts strangely

Post by ted »

tedballou wrote:AND I read on the man page for "access" that
The access statement should not be used within a procedure or function.
which of course is violated by my code that works.
OK, you found that out for yourself. Good. Try to use sprint to construct a string of the form
sectionname statement
or
sectionname { statement }
and then execute that.
tedballou

Re: localobj acts strangely

Post by tedballou »

Yes, but: how do I handle the problem that localobj acts strangely? This code

Code: Select all

proc foobar(){ localobj s
    strdef mystr, mysec
    mysec=$s1
    sprint(mystr, "%s s = new SectionRef()", mysec)
    execute(mystr)
    s.sec {psection()}
}
is trying to set up a section reference using the localobj mechanism, so that I can use the same name in recursively called levels of the function to refer to different sections without losing track of the section referenced in the calling function level. BUT the code complains as if the objvar had not been declared:

Code: Select all

oc>foobar("dend")
nrniv: syntax error
 near line 16
 {dend s = new SectionRef()}
             ^
execute("dend s = new SectionRef()"        )
foobar("dend"      )
nrniv: execute error: dend s = new SectionRef()
 near line 16
 ^
oc>
Weirdly, if I insert an "access" command containing a reference to the same objvar, the localobj declaration seems to work fine:

Code: Select all

proc foobar1(){ localobj s
    strdef mystr, mysec
    mysec=$s1
    sprint(mystr, "access %s", mysec)
    execute(mystr)
    s = new SectionRef()
    s.sec {psection()}
}
Any idea what is going on, or how I can get the original version to work?

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

Re: localobj acts strangely

Post by ted »

Going back to your first post
the function causes changes in the global version of s, not the local one.
because the string is executed at the top level of the interpreter (see
http://www.neuron.yale.edu/neuron/stati ... ml#execute
). Execution at the top level means "outside the context of any func, proc, or object", but s is treated as an objref only inside the proc or func that declares localobj s.

A potential workaround might be to declare
objref tobj
at the top level
then use tobj inside your proc. If you need to keep track of the sections that have been traversed, you could make your own stack by declaring
objref tlist
tlist = new List()
before starting a recursive call sequence, then inside the proc
tlist.append(tobj) // after making tobj into a new SectionRef
every time you descend another level of recursion. And you'd want to remove the last objref from tlist every time you back out a level. If you are concerned about persistence of a top-level (therefore global) tobj leading to problems if the referenced object is ever accidentally touched by other code, you could
objref tobj
just before exiting the proc. Then the only reference to the object is in tlist, so a more cumbersome syntax is necessary to mangle it. And you're going to be removing that reference from tlist when you back out.
tedballou

Re: localobj acts strangely

Post by tedballou »

OK, I see that I need to consider the context in which "execute" occurs. I need it to run in the context of my function. The point of the localobj declaration is to preserve the reference in this calling function during recursive calls, so I don't understand what is meant by
use tobj inside your proc
since then it would be global and the local values would be lost. I don't care in this case about keeping track of the sections that have been traversed, I just need to know the section I am working on within each instance of the function.

So maybe my question is, does the localobj mechanism support SectionRef objects?
ted
Site Admin
Posts: 5810
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: localobj acts strangely

Post by ted »

localobj isn't a mechanism. It is a keyword that is used to declare that specified tokens are to be treated as objrefs, but only within the proc or func where the declaration is made. Any token so declared can be used to refer to an instance of any class.

I suspect that what you're trying to do can be accomplished in a more direct way that does not require construction and execution of strings within procs or funcs. However, although your immediate tactics are evident, the underlying motivation (what you are trying to use them to accomplish) is not, at least to me.
ted
Site Admin
Posts: 5810
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: localobj acts strangely

Post by ted »

tedballou wrote:The point of the localobj declaration is to preserve the reference in this calling function during recursive calls, so I don't understand what is meant by
use tobj inside your proc
since then it would be global and the local values would be lost.
Not so.

Code: Select all

objref tobj
strdef tstr
proc foobar(){
  sprint(tstr, "%s tobj = new SectionRef()", $1)
  execute(tstr)
  tobj.sec psection()
  // whatever else you want to do with tobj
  objref tobj // throw the SectionRef away so it won't be stepped on by other code
}
Post Reply