# Surface area of compartmental models

Hi,
I have a question about how the surface area of a compartmental model is computed.
My understanding from the docstring of a Cylinder is that the Length argument specifies its total length, independent of how many compartments (n) it has.
Yet the input resistance of a cylinder appears to change when the number of compartments changes in a way that cannot be explained by the increased accuracy of the spatial discretization.
I suppose I’m getting the concept of the “compartments” wrong - I’m thinking of it as the equivalent of “nseg” in the NEURON simulation environment.

Here is an example to reproduce the issue:

``````import numpy as np
import brian2 as b2  # Sorry I'm obsessed with separating namespaces

gL = 1e-4*b2.siemens/b2.cm**2  # Leak conductance
EL = -80*b2.mV
tbase = 50.0*b2.ms
tpulse = 200.0*b2.ms
duration = 400.0*b2.ms
Iamp = 10e-12*b2.amp  # Current injection amplitude (10 pA)
nseg = 11 # Number of compartments in the dendrite; change this to see the effects on input resistance

# A simple passive membrane
eqs = '''
Im = gL*(EL-v) : amp/meter**2
I : amp (point current)
'''

morpho = b2.Soma(diameter=20*b2.um)
morpho.dendrite = b2.Cylinder(length=1000*b2.um, diameter=10*b2.um, n=nseg)

# Axial resistance is negligibly low - effectively this is a single compartment
neuron = b2.SpatialNeuron(morphology=morpho, model=eqs, Cm=1*b2.uF/b2.cm**2, Ri=1e-3*b2.ohm*b2.cm)

neuron.v = EL
neuron.I = 0*b2.amp

# Monitors
mon = b2.StateMonitor(neuron, 'v', record=True)
b2.run(tbase)
neuron.I = Iamp
b2.run(tpulse)
neuron.I = 0*b2.nA
b2.run(duration-tpulse-tbase)

# Compute input resistance from simulation values
vbase = mon.v[mon.t<tbase][-1]
vmax = mon.v[mon.t<tbase+tpulse][-1]
delta_v = vmax-vbase
rin_sim = delta_v / Iamp

# Compute total membrane area according to brian2, and compare with theory
total_area_sim = np.sum(morpho.area)  + np.sum(morpho.dendrite.area)
total_area_theory = \
4.0*np.pi*(morpho.diameter/2.0)**2 + \
np.pi*morpho.dendrite.diameter*np.sum(morpho.dendrite.length)

# Compute theoretical input resistance
rin_theory = 1.0/(gL * total_area_sim)

print("Total surface area (brian2): ", total_area_sim)
print("Total surface area (theory): ", total_area_theory)
print("Input resistance (brian2): ", rin_sim)
print("Input resistance (theory): ", rin_theory)
``````

Output for nseg=11:
Total surface area (brian2): 0.03267256 mm^2
Total surface area (theory): [0.03267256] mm^2
Input resistance (brian2): 0.36725744 Gohm
Input resistance (theory): 30.60671983 Mohm

I.e. the input resistance is nseg+2 times higher than what I would have expected.

I’m running brian2 v2.4.2 with Python 3.8.

What am I getting wrong here?

Christoph

1 Like

Hi Christoph. Your understanding is correct, the number of compartments is essentially identical to `nseg` in NEURON, except that in Brian it is a fixed property of the morphology, i.e. you cannot change the number of compartments after its creation without creating a new one (in NEURON you can set the `nseg` attribute on any section at any time). And changing it should not change the overall area or resistance.

The problem in your example is that you are injecting a point current via `neuron.I = Iamp`, which means: “inject a point current into each compartment”. Therefore with each additional compartment you also get an additional “electrode” injecting a current. Instead, you can inject it into a single place via something like:

``````neuron.dendrite[500*b2.um:500.1*b2.um].I = Iamp
``````

Which would inject the current into whatever compartment happens to be in the middle of the dendrite. As a side remark: we have some changes in the pipeline that would allow you to simple write `[500*b2.um]` instead of this slightly weird range, but at the moment this is not supported. However, using a concrete integer index will already work:

``````neuron.dendrite[len(neuron.dendrite)//2].I = Iamp
``````

Hope that makes things clear!

Thank you. Yes that clears things up. I have re-run the code and it works as expected.
When the morphology is mapped to the SpatialNeuron, is neuron always guaranteed to be the soma or root compartment? Or is there a less ambiguous way of referring to the root section?

If you start your morphology declaration with `morpho = b2.Soma(...)`, then `neuron` will always correspond to the soma. The mapping from the morphology tree to the flat representation is deterministic, you can get the indices of individual sections by accessing the `indices` attribute, e.g.

``````print(morpho.dendrite.indices[:])
``````

will give you the indices of the dendrite compartment. As for all morphological attributes, you can also get them directly from the `SpatialNeuron` (`neuron.dendrite.indices[:]`). There’s a subtle difference between the two accesses, though:
Accessing through the morphology will always give you the attribute for the respective section, e.g. `morpho.area` will give you the area of the soma. On the other hand, accessing through the `SpatialNeuron` will always work on the whole subtree (i.e. `neuron.area` will give you the area of all the compartments). We should probably make this clearer in the documentation, I now realize that this difference is probably why you expected that `neuron.I = ...` would set the current in the soma.

I now realize that this difference is probably why you expected that `neuron.I = ...` would set the current in the soma.

Yes, that’s why I tripped.