Impedance methods change the location

Anything that doesn't fit elsewhere.
Post Reply
rbdewell
Posts: 5
Joined: Wed Sep 09, 2015 2:47 pm

Impedance methods change the location

Post by rbdewell » Tue Dec 04, 2018 2:29 pm

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.

rbdewell
Posts: 5
Joined: Wed Sep 09, 2015 2:47 pm

Re: Impedance methods change the location

Post by rbdewell » Thu Dec 06, 2018 3:33 pm

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.

hines
Site Admin
Posts: 1569
Joined: Wed May 18, 2005 3:32 pm

Re: Impedance methods change the location

Post by hines » Tue Dec 11, 2018 8:40 am

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.

hines
Site Admin
Posts: 1569
Joined: Wed May 18, 2005 3:32 pm

Re: Impedance methods change the location

Post by hines » Fri Dec 14, 2018 10:53 am

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

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

Re: Impedance methods change the location

Post by ted » Tue Dec 18, 2018 7:40 pm

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)
    }
  }
}

rbdewell
Posts: 5
Joined: Wed Sep 09, 2015 2:47 pm

Re: Impedance methods change the location

Post by rbdewell » Fri Dec 21, 2018 8:35 pm

Thanks for the help. It works well and speeds up my code dramatically.

Post Reply