proc with new Vector and arrays as argument in hoc

Anything that doesn't fit elsewhere.
Post Reply
peterahl
Posts: 1
Joined: Mon Oct 07, 2013 8:48 am
Location: Stockholm, Sweden
Contact:

proc with new Vector and arrays as argument in hoc

Post by peterahl »

Hi!

I have a model of a neuron, and I'm writing code to diffrent test on this model. To make my code more compact, I'm creating a library of functions that i load in the en the experiment hoc file.

Code: Select all

load_file("hocsrc/record-APs.hoc")

objectvar fiber
fiber = new fiberTemplate()

nSeg = fiber.axon[1].nseg
objref spTimes[nSeg]
objref apTimes[nSeg]

connectAPcounters(fiber, spTimes, apTimes)
contents of record-APs.hoc

Code: Select all

/*
## record-aciton-potentials.hoc
These funktion sets up the recording of action potentials and saves them to file.

**Parameters**
axon[x]
*/

proc connectAPcounters() { local i
    // $o1 is an template
    // $o2 is an array
    // $o3 is an array
    i = 0
    $o1.axon[1] {
	for (x,0) {
	    $o2[i] = new Vector()
	    $o3[i] = new APCount(x)
	    $o3[i].thresh = -10
	    $o3[i].record($o2[i])
	    i += 1
	}
    }
}

proc saveAPcounters(){ local ii, i
    // $o1 is a wopen file
    // $o2 is an arrayy
    nElements = $o2.size()
    nAPs = $o2[0].size()
    veclast = nAPs - 1
    vecloop = nAPs - 2
    
    $o1.printf("\"aps\":[\n")
    for (ii = 0; ii < nElements; ii += 1) {
        $o1.printf("[")
    	for i=0, vecloop $o1.printf("%g, ", $o2[ii].x(i))
    	$o1.printf("%g]", $o2[ii].x(veclast))
    	if (ii < nElements - 1) $o1.printf(",")
    	$o1.printf("\n")
    }
    $o1.printf("],\n")
}
I get the following error messege
1
1
1
100
100
1
1
1
1
/home/peter/neuron/nrn/x86_64/bin/nrniv: syntax error
in record-APs.hoc near line 16
$o2 = new Vector()
^
xopen("record-APs.hoc")
execute1("{xopen("re...")
load_file("hocsrc/rec...")
0
1
1
1

/home/peter/neuron/nrn/x86_64/bin/nrniv: connectAPcounters undefined function
in record-APs.hoc near line 150
connectAPcounters(fiber, spTimes, apTimes)
^
connectAPcounters(fiberTemplate[0], Vector[8], NULLobject)


I have two questions.

1) how do I pass fiber.axon[1] to the proc()?

2) Why cant I add new Vectors to the array which I pass to the proc()?
ted
Site Admin
Posts: 6299
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: proc with new Vector and arrays as argument in hoc

Post by ted »

Good idea, you're on the right track, but of course there are always "gotchas". Let's start with your second question, which I'll paraphrase as "why does proc connectAPcounters() fail?"

The error message is

Code: Select all

/home/peter/neuron/nrn/x86_64/bin/nrniv: syntax error
 in record-APs.hoc near line 16
 	    $o2[i] = new Vector()
          ^
        xopen("record-APs.hoc")
Syntax errors usually provide useful clues because they typically happen right at the place in the code that contains the mistake. The carat ^ points at the opening square bracket because it doesn't know what to do with an expression of the form $o2

And that begs the question "why doesn't it?"

An objref is just a name that points to an instance of an object class. An instance of an object class may contain many things, and those things may be accessible from outside the object (like the elements of a Vector or the members of a List), but there is no way to declare that an objref is an "array of objrefs".

For example, the declaration
oc>objref foo[3]
creates three separate objrefs whose names are foo[0]..foo[2]. Yes, you can write
oc>for i=0,2 foo = new Vector()
oc>for i=0,2 print foo
Vector[3]
Vector[4]
Vector[5]
but what does hoc do when it encounters a statement that refers to foo without an index?
oc>print foo
Vector[3]
So foo is not some kind of "array of Vectors"--not even if you pass it as an argument to a procedure. It's merely a shortcut or nickname for foo[0].

"Wait, are you sure?" you ask.
Define this simple procedure
oc>proc po1() { print $o1 }
and see what it does when you call it with foo or foo[0] as its argument
oc>po1(foo)
Vector[3]
oc>po1(foo[0])
Vector[3]

OK so far. Now try to treat foo as an array of objrefs

Code: Select all

oc>proc poa() { for i=0,2 print $o1[i] }
/home/ted/bin/nrn/i686/bin/nrniv: syntax error
 near line 7
 proc poa() { for i=0,2 print $o1[i] }
                                 ^
and it fails, as expected.

And that's why

Code: Select all

proc connectAPcounters() { local i
  i = 0
  . . .
  for (x,0) {
     $o2[i] = new Vector()
produces a syntax error. $o2 is NOT an array of anything. Neither is $o3. They are merely objrefs that point to NULLobject.

So how can one write code that builds a collection of Vectors, APCounts, or other object instances? Collections of objects are best managed with Lists--see my post "Re: array of point processes" viewtopic.php?f=2&t=2815&p=11340 We'll return to this very shortly.

But first, your first question:
"how do I pass fiber.axon[1] to the proc()?"
The answer is: don't. Use the section stack instead; see https://www.neuron.yale.edu/neuron/stat ... cspec.html

With all this in mind, here's a revision of connectAPcounters

Code: Select all

// record spike times from each segment
// in currently accessed section (CAS)
// $o1 and $o2 become Lists that hold the APCount and Vector instances
// used to detect and record the CAS's spike times

proc connectAPcounters() { local i  localobj tmpapc, tmpstv
  $o1 = new List() // start with a clean slate
  $o2 = new List()
  i = 0
  for (x,0) { // m‌onitor internal nodes only
    tmpapc = new APCount(x)
    tmpapc.thresh = -10
    tmpstv = new Vector()
    tmpapc.record(tmpstv)
    $o1.append(tmpapc)
    $o2.append(tmpstv)
  }
}
and an example of how to use it

Code: Select all

objref apclist, stvlist // will contain all APCounts and spike time Vectors
apclist = new List() // so any other code can treat these as Lists
stvlist = new List() // without generating an error message

fiber.axon[1] connectAPcounters(apclist, stvlist)

run()

for i=0,stvlist.count()-1 {
  print "spike times at internal node ", i
  stvlist.o(i).printf
}
Post Reply