brian-team / brian2

Brian is a free, open source simulator for spiking neural networks.
http://briansimulator.org
Other
912 stars 217 forks source link

Getting indices for all axonal compartments not working #1550

Closed NickChernov closed 2 days ago

NickChernov commented 1 month ago

Dear Brian Team, I posted this on Stack Overflow but then saw that this may be a more relevant place to post:

I am trying to create a neuronal model in Brian 2 based on a .swc file which has about 900 compartments. I am importing the model morphology using morpho = Morphology.from_file()

I would like to plot the voltage vs. time for all the axonal compartments as well as all the dendrites but when I use the following:

axon_index = neuron[morpho.axon.indices[:]] dendrite_index=neuron[morpho.apic.indices[:]] I get: dendrite compartments are: <Subgroup 'spatialneuron_subgroup_1' of 'spatialneuron' from 1 to 4> axon compartments are:<Subgroup 'spatialneuron_subgroup' of 'spatialneuron' from 561 to 564>

There's way too few compartments listed. I would expect the answer for the axonal compartments to be something like 388-662. based on the swc file. Why aren't they listed? Thanks, Nick

mstimberg commented 1 month ago

Hi @NickChernov. The best place for general discussions/questions would be the Brian discussion forum, actually: https://brian.discourse.group

Regarding your question: it is impossible for me to say whether this is a problem with Brian or with your morphology file without having access to the file (or at least having more details about it)…

NickChernov commented 1 month ago

Hi Marcel, Thank you for your reply. I used the following file from Neuromorpho.org (github won't let me upload .swc so I changed the extension to txt) 140208_Dbx1RF.txt

mstimberg commented 1 month ago

Hi. So I had a look into the morphology, and I see a bit clearer now. The morphology has indeed many more axon compartments, but these compartments are spread out over several sections, i.e. the axon is branching out. When you access attributes of a Morphology object, you will always get the attributes of a single section only. To get all the indices you'd therefore have to access all the subsections as well:

>>> morpho.axon.indices[:]
array([561, 562, 563])
>>> morpho.axon.axon.indices[:]
array([564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576,
       577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589,
       590, 591, 592, 593, 594, 595, 596])
>>> morpho.axon.axon2.indices[:]
array([597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609,
       610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622,
       623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633])

etc. This is obviously not very convenient. Luckily, the convention is different if you ask for attributes of the SpatialNeuron, instead of the Morphology object: in that case, you get the values for the whole subtree (if you want it only for a given section, you have to append .main):

>>> neuron = SpatialNeuron(morpho, 'Im = 0*nA/cm**2 : amp/meter**2')
>>> neuron.axon.indices[:]
array([561, 562, 563, ..., 833, 834, 835], dtype=int32)
>>> len(neuron.axon.indices[:])
275

This works here because all the axon compartments are in a single subtree – you cannot do the same thing for the apical dendrites, since there are four dendritic subtrees branching off the soma. In this specific example, there are only axon and apical dendritic compartments, so you could deduce the full list by removing all axon compartments from the list of all indices. More generally, you could write a little helper function to recurse through the subtree:

>>> def indices_by_type(morphology, compartment_type, indices=None):
...     if indices is None:
...         indices = []
...     if morphology.type == compartment_type:
...         indices.extend(morphology.indices[:])
...     for child in morphology.children:
...         indices_by_type(child, compartment_type, indices)
...     return indices
... 
>>> len(indices_by_type(morpho, "axon"))
275
>>> len(indices_by_type(morpho, "apic"))
601
>>> len(indices_by_type(morpho, "soma"))
1

Now, there is another little hurdle: you can use these indices to index the neuron object only if they refer to a single subtree (which translates into a contiguous set of indices):

>>> neuron[indices_by_type(morpho, "axon")]
<Subgroup 'spatialneuron_1_subgroup' of 'spatialneuron_1' from 561 to 836>
>>> neuron[indices_by_type(morpho, "apic")]
IndexError: Subgroups can only be constructed using contiguous indices.

(Changing this is actually PR #1229, which has been unfinished way too long…)

There is a simple solution to this, though: instead of indexing the whole group, you can directly index the variable that you are interested in:

>>> neuron.v[indices_by_type(morpho, "apic")]
array([0., 0., 0., ..., 0., 0., 0.]) * volt
>>> neuron.v[indices_by_type(morpho, "axon")]
array([0., 0., 0., ..., 0., 0., 0.]) * volt

Hope that makes sense and clears things a bit up!

NickChernov commented 1 month ago

Thank you Marcel, that is very helpful!

mstimberg commented 2 days ago

I am closing this issue here, since there is nothing "actionable" ATM