Page 1 of 1

Impedance methods change the location

Posted: Tue Dec 04, 2018 2:29 pm
by rbdewell
When using the Impedance methods Impedance.input(x), Impedance.input_phase(x), or Impedance.ratio(x) the Impedance.loc(x) value is changed making any subsequent calls to Impedance.transfer(x) or Impedance.transfer_phase(x) return incorrect values. As illustrated by the following example code with output:

Code: Select all

nrnversion()
NEURON -- VERSION 7.6.1 master (a558837) 2018-08-01

create soma
create dend[5]
soma connect dend[0](0),1
dend[0] connect dend[1](0),1
dend[1] connect dend[2](0),1
dend[2] connect dend[3](0),1
dend[3] connect dend[4](0),1

forall {
	diam=10
	Ra=200
	insert pas
	g_pas=2e-4
        nseg=5
}

access soma

objref Z
Z = new Impedance()
Z.loc(0.5)
        0 
Z.compute(20,1)
	0 

dend[4] { print Z.transfer(0.5) }
20.508135 
dend[4] { print Z.input(0.5) }
25.761481 
dend[4] { print Z.transfer(0.5) }
25.761481
The first time the correct transfer impedance is returned (from soma to dend[4]), the second time the transfer from dend[4] to dend[4] is returned.
I can't find why this happens, so any help on fixing it would be appreciated.

P.S. This only happens with the extended calculation using dv/dt state. If the line "Z.compute(20,1)" is changed to "Z.compute(20,0)", then the transfer impedance is calculated correctly both times.

Re: Impedance methods change the location

Posted: Thu Dec 06, 2018 3:33 pm
by rbdewell
I believe I have located the issue, but cpp programming is not an area of expertise.

The issue seems to arise in "nonlinz.cpp":
The input_amp(), input_phase(), and ratio_amp() methods include the line "solve(curloc)", and within this solve() method the "iloc" parameter is changed to "curloc" which changes the effective Impedance.loc section for subsequent calls to the Impedance measures.

In impedanc.cpp that does the linear (non dV/dt extended) computation, there is no such change in the current injection location with these methods.
Currently I'm running simulations where I measure the input and transfer impedances across hundreds of sections, and using the extended computation requires recalculating the impedance in calls to every segment slowing down the code ~50-fold. If someone better at cpp programming than me could let me know the best way to change this, it would be much appreciated.

Re: Impedance methods change the location

Posted: Tue Dec 11, 2018 8:40 am
by hines
The documentation needs to be updated to reflect this behavior. The default calculation is able to efficiently combine the calculation of
transfer impedance everywhere given a specific current stimulus location and input impedance everywhere. After a compute, it is possible
just read off the values in subsequent evaluations of transfer and input impedance an any location without modifyin input stimulus locaition.
The extended impedance calculation is able to do the former but can only calculate input impedance at the location specified (and the calculation
of input impedance must have
stimulus location and recording location at the same location).
In reviewing the default calculation of impedance everywhere. i suspect, but am not certain, that the extended calculation can be implemented
analogously but at present there is no choice but to explicitly reset loc and do another compute when desiring transfer impedaance after
computing an input impedance.

Re: Impedance methods change the location

Posted: Fri Dec 14, 2018 10:53 am
by hines
The extended impedance behavior is now the same as for the default impedance calculation. That is, interleaved calculations of
transfer and input impedance work properly without having to reset the input stimulus location for transfer. So the behavior now corresponds
to the existing documentation. Note that , given a current injection site, all transfer impedances are calculated at the same time so a series
of requests for transfer impedances merely return the proper element of the solved vector (the transfer impedance at the injection site is the
input impedance). The linear algebra trick for calculating the input impedance everywhere in one solve is not implemented for the extended
impedance.

This change is at https://github.com/neuronsimulator/nrn/ ... cc45067a3c

Re: Impedance methods change the location

Posted: Tue Dec 18, 2018 7:40 pm
by ted
The extended impedance behavior is now the same as for the default impedance calculation.
In other words,

Code: Select all

// specifies "location" and executes compute() just once
// first argument is frequency
// second is 0 to ignore dstate/dt contribution, 1 to include it
proc faster() {
  soma distance(0, 0.5) // distances are relative to middle of soma
  soma zz.loc(0.5)
  zz.compute($1, $2)
  print "x distance(x) input(x)"
  forall {
    print secname()
    for (x) print x, distance(x), zz.input(x)
  }
}
produces the same result as

Code: Select all

// for each node of each section
//   sets location to that node and executes compute()
// first argument is frequency
// second is 0 to ignore dstate/dt contribution, 1 to include it
proc slower() {
  soma distance(0, 0.5) // distances are relative to middle of soma
  print "x distance(x) input(x)"
  forall {
    print secname()
    for (x) {
      zz.loc(x) // location of "stimulus electrode"
      zz.compute(FREQ, $1)
      print x, distance(x), zz.input(x)
    }
  }
}

Re: Impedance methods change the location

Posted: Fri Dec 21, 2018 8:35 pm
by rbdewell
Thanks for the help. It works well and speeds up my code dramatically.