NeuroML importer

This is a short overview of the nmlimport package, providing functionality to import a morphology – including some associated information about biophysical properties and ion channels – from an .nml file.

NeuroML is a XML-based description that provides a common data format for defining and exchanging descriptions of neuronal cell and network models (NeuroML project website).

Working example

As a demonstration, we will use the nmlimport library to generate a morphology and extract other related information from the pyr_4_sym.cell.nml nml file. You can download it from OpenSourceBrain’s ACnet2 project.

from brian2tools.nmlimport.nml import NMLMorphology
nml_object = NMLMorphology('pyr_4_sym.cell.nml', name_heuristic=True)

This call provides the nml_object that contains all the information extracted from .nml file. When name_heuristic is set to True, morphology sections will be determined based on the segment names. In this case Section names will be created by combining names of the inner segments of the section. When set to False, all linearly connected segments combine to form a section with the name sec{unique_integer}.


  • To obtain a Morphology object:
>>> morphology = nml_object.morphology

|

With this

With this Morphology object, you can use all of Brian’s functions to get information about the cell:

>>> print(morphology.topology())
-|  [root]
   `-|  .apical0
      `---|  .apical0.apical2_3_4
      `-|  .apical0.apical1
   `-|  .basal0
      `-|  .basal0.basal1
      `-|  .basal0.basal2

>>> print(morphology.area)
[ 1228.36272755] um^2

>>> print(morphology.coordinates)
[[  0.   0.   0.]
[  0.  17.   0.]] um

>>> print(morphology.length)
[ 17.] um

>>> print(morphology.distance)
[ 8.5] um

  • You can plot the morphology using brian2tool’s plot_morphology function:
from brian2tools.plotting.morphology import plot_morphology
plot_morphology(morphology)
Pyramidal cell's morphology plot.

Pyramidal cell’s Morphology plot.

Handling SegmentGroup

In NeuroML, a SegmentGroup groups multiple segments into a single object, e.g. to represent a specific dendrite of a cell. This can later be used to apply operations on all segments of a group. The segment groups are stored in a dictionary, mapping the name of the group to the indices within the Morphology. Note that these indices are often identical to the id values used in the NeuroML file, but they do not have to be.

>>> from pprint import pprint
>>> pprint(nml_object.segment_groups)
{'all': [0, 1, 2, 3, 4, 5, 6, 7, 8],
 'apical0': [1],
 'apical1': [5],
 'apical2': [2],
 'apical3': [3],
 'apical4': [4],
 'apical_dends': [1, 2, 3, 4, 5],
 'background_input': [7],
 'basal0': [6],
 'basal1': [7],
 'basal2': [8],
 'basal_dends': [8, 6, 7],
 'basal_gaba_input': [6],
 'dendrite_group': [1, 2, 3, 4, 5, 6, 7, 8],
 'middle_apical_dendrite': [3],
 'soma': [0],
 'soma_group': [0],
 'thalamic_input': [5]}

The file pyr_4_sym.cell.nml will look something like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<cell id="pyr_4_sym">
    <morphology id="morphology_pyr_4_sym">
        <segment id="0" name="soma">
            <proximal x="0.0" y="0.0" z="0.0" diameter="23.0"/>
            <distal x="0.0" y="17.0" z="0.0" diameter="23.0"/>
        </segment>
        ..........
        ..........
        ..........

        <segment id="6" name="basal0">
            <parent segment="0" fractionAlong="0.0"/>
            <proximal x="0.0" y="17.0" z="0.0" diameter="4.0"/>
            <distal x="0.0" y="-50.0" z="0.0" diameter="4.0"/>
        </segment>
        ..........
        ..........
        ..........

        <segmentGroup id="apical_dends">
            <include segmentGroup="apical0"/>
            <include segmentGroup="apical2"/>
            <include segmentGroup="apical3"/>
            <include segmentGroup="apical4"/>
            <include segmentGroup="apical1"/>
        </segmentGroup>

        <segmentGroup id="middle_apical_dendrite">
            <include segmentGroup="apical3"/>
        </segmentGroup>
        ........
        ........
        ........
    </morphology>
</cell>

Handling sections not connected at the distal end

If you look at the line 12 in above .nml file, you can see fractionAlong=0.0. The fractionAlong value defines the point at which the given segment is connected with its parent segment. So a fractionAlong value of 1 means the segment is connected to bottom (distal) of its parent segment, 0 means it is connected to the top (proximal) of its parent segment. Similarly a value of 0.5 would mean the segment is connected to the middle point of its parent segment. Currently, the nmlimport library supports fractionAlong value to be 0 or 1 only, as there is no predefined way to connect a segment at some intermediate point of its parent segment in Brian.

Extracting channel properties and Equations

The generated nml_object contains several dictionaries with biophysical information about the cell:

properties:
A dictionary with general properties such as the threshold condition or the intracellular resistivity. The names are chosen to be consistent with the argument names in SpatialNeuron, in many cases you should therefore be able to directly pass this dictionary: ``neuron = SpatialNeuron(…, **nml_object.properties)`
channel_properties:
A dictionary of reversal potentials and conductance densities for the different channels in the cell. The dictionary maps the name of segment groups to the name of the respective variable names (e.g. g_Na, E_Na, …)

For the example file, these dictionaries look like this:

>>> pprint(nml_object.properties) # threshold, refractory etc.
{'Cm': 2.84 * ufarad / cmetre2,
 'Ri': 0.2 * kohm * cmetre,
 'refractory': 'v > 0. * volt',
 'threshold': 'v > 0. * volt'}

>>> pprint(nml_object.channel_properties) # reversal potentials and conductance densities
{'all': {'E_LeakConductance_pyr': -66. * mvolt,
         'g_LeakConductance_pyr': 0.1420051 * msiemens / cmetre2},
 'soma_group': {'E_Ca_pyr': 80. * mvolt,
                'E_Kahp_pyr': -75. * mvolt,
                 'E_Kdr_pyr': -75. * mvolt,
                 'E_Na_pyr': 55. * mvolt,
                 'g_Ca_pyr': 10. * msiemens / cmetre2,
                 'g_Kahp_pyr': 2.5 * msiemens / cmetre2,
                 'g_Kdr_pyr': 80. * msiemens / cmetre2,
                 'g_Na_pyr': 120. * msiemens / cmetre2}}

If you have a SpatialNeuron neuron with equations for all the channels in the NML file (e.g. as generated by the get_channel_equations method below), then you can assign the reversal potentials and conductances to the individual compartments by combining the information from the segment_groups and channel_properties dictionaries:

for segment_group, values in nml_object.channel_properties.items():
    indices = nml_object.segment_groups[segment_group]
    for property, value in values.items():
        getattr(neuron, property)[indices] = value

To get the channel equations for a particular channel, e.g. Na_pyr:

>>> print(nml_object.get_channel_equations("Na_pyr"))
alpha_h_Na_pyr = (128. * hertz) * exp((v - (-43. * mvolt))/(-18. * mvolt)) : Hz
beta_h_Na_pyr = (4. * khertz) / (1 + exp(0 - (v - (-20. * mvolt))/(5. * mvolt))) : Hz
I_Na_pyr = g_Na_pyr*m_Na_pyr**2*h_Na_pyr*(E_Na_pyr - v) : A/(m^2)
alpha_m_Na_pyr = (1.28 * khertz) * (v - (-46.9 * mvolt)) / (4. * mvolt) / (1 - exp(- (v - (-46.9 * mvolt)) / (4. * mvolt))) : Hz
beta_m_Na_pyr = (1.4 * khertz) * (v - (-19.9 * mvolt)) / (-5. * mvolt) / (1 - exp(- (v - (-19.9 * mvolt)) / (-5. * mvolt))) : Hz
dh_Na_pyr/dt = alpha_h_Na_pyr*(1-h_Na_pyr) - beta_h_Na_pyr*h_Na_pyr : 1
dm_Na_pyr/dt = alpha_m_Na_pyr*(1-m_Na_pyr) - beta_m_Na_pyr*m_Na_pyr : 1
E_Na_pyr : V (constant)
g_Na_pyr : S/(m^2) (constant)

Note that this mechanism currently only supports passive channels and HH-type channels with sigmoidal, exponential, or exponential linear equations for the gating variables.

Note

If your .nml file includes other .nml files, make sure they are present in the same folder as your main .nml file. If the files are not present, a warning will be thrown and execution will proceed as normal.