Cell morphology

A cell’s morphology describes both its geometry and branching structure. Morphologies in Arbor are modelled as a set of one dimensional cables of variable radius, joined together to form a tree.

The building blocks of morphology tree are points and segments. A point is a three-dimensional location and a radius, used to mark the centre and radius of the cable.

Field

Type

Description

x

real

x coordinate of centre of cable (μm).

y

real

y coordinate of centre of cable (μm).

z

real

z coordinate of centre of cable (μm).

radius

real

cross sectional radius of cable (μm).

A segment is a frustum (cylinder or truncated cone), with the centre and radius at each end defined by a pair of points. In other words, in Arbor the radius between two points is interpolated linearly, resulting in either a cylinder (equal radii) or truncated cone (differing radii), centred at the line through the pair of points.

Field

Type

Description

prox

point

the center and radius of the proximal end.

dist

point

the center and radius of the distal end.

tag

integer

tag meta-data.

A tag is an integer label on every segment, which can be used to define disjoint regions on cells. The meaning of tag values are not fixed in Arbor, however we typically use tag values that correspond to SWC structure identifiers.

Segment trees

A segment tree describes a morphology as a set of segments and their connections, designed to support both the diverse descriptions of cell morphologies (e.g. SWC, NeuroLicida, NeuroML), and tools that iteratively construct cell morphologies (e.g. L-system generators, interactive cell-builders).

Segment trees comprise a sequence of segments starting from at lease one root segment, together with a parent-child adjacency relationship where a child segment is distal to its parent. Branches in the tree occur where a segment has more than one child. Furthermore, a segment can not have more than one parent. In this manner, neuron morphologies are modelled as a tree, where cables that represent dendrites and axons can branch, but branches can not rejoin.

The following definitions are used to refer to segments in a segment tree:

  • root: segments at the root or start of the tree. A non-empty tree must have at least one root segment, and the first segment will always be a root.

  • parent: Each segment has one parent, except for root segments which have mnpos as their parent.

    • The id of a segment is always greater than the id of its parent.

    • The ids of segments on the same unbranched sequence of segments do not need to be contiguous.

  • child: A segment’s children are the segments that have the segment as their parent.

  • terminal: A segment with no children. Terminals lie at the end of dendritic trees or axons.

  • fork: A segment with more than one child. The distal end of a fork segment are fork points, where a cable splits into two or more branches.

    • Arbor allows more than two branches at a fork point.

The following segment tree models a soma as a cylinder, a branching dendritic tree and an axon with an axonal hillock. The segments are coloured according to their tag, which in this case are SWC structure identifiers: tag 1 coloured pink for soma; tag 2 coloured grey for axon; tag 3 coloured blue for basal dendrites.

../_images/label_seg.svg

Example Python code to generate this morphology is in the segment_tree documentation below.

We can apply the following labels to the segments:

  • The tree is composed of 11 segments (1 soma, 2 axon, 8 dendrite).

  • The proximal ends of segments 0 and 9 (the soma and axon hillock respectively) are attached to the root of the tree.

  • Segment 2 is a fork, with segments 3 and 5 as children.

  • Segment 5 is a fork, with segments 6 and 7 as children.

  • There is also a fork at the root, with segments 0 and 9 as children.

  • Segments 4, 6, 8 and 10 are terminal segments.

In the example above there are no gaps between segments, however it is possible for segments to be detached, where the proximal end of a segment is not coincident with the distal end of its parent. The following morphology has gaps between the start of the axon and dendritic tree and the soma segment to which they attach.

../_images/detached_seg.svg

Note

In Arbor, segments are always treated as though they are connected directly to their parents, regardless of whether ends where they attached are collocated.

Gaps are frequently the result of simplifying the soma, whereby the complex geometry of a soma is represented using a cylinder or sphere (spheres are represented by a cylinder with length and diameter equal to that of the sphere in simulation tools like Arbor and NEURON).

A gap between a cylindrical soma and segments attached to it does not mean that the segmentation is invalid. To illustrate why this can occur, consider a potato-shaped soma modelled with a cylinder of the same surface area. If the cell description places the first segment of a dendritic tree where it attaches to the “potato soma”, it is unlikely to be collocated with an end of the simplified soma. The cell model will correctly represent the location and dimension of the dendritic tree, while preserving the soma surface area with a simplified cylindrical model.

Because Arbor supports tapered segments (where radius varies linearly along a segment) it is possible to represent more complex soma shapes using multiple segments, for example the segmentation below uses 4 segments to model the soma.

../_images/stacked_seg.svg

Geometry

A morphology describes the geometry of a cell as unbranched cables with variable radius , and their associated tree structure. Every segment tree can be used to generate a unique morphology, which derives and enumerates branches from the segments. The branches of a morphology are unbranched cables, composed of one or more segments, where:

  • the first (proximal) segment of the branch is either a root or the child of fork segment;

  • the last (distal) segment of the branch is either a fork or terminal segment;

  • branches are enumerated in order, following the order of the ids of their proximal segments in the segment tree.

When constructed in this manner, the following statements are true for the branches and their enumeration:

  • Because a branch must have root, fork or terminal ends, a branch can not be sub-divided into two or more branches, and hence there is only one possible set of branches that can be derived from a segment tree.

  • Because branches are enumerated according to the id of their proximal segments, there is only one branch enumeration representation for a segment tree.

  • However, it is possible for two topologically equivalent morphologies to be derived from different segment trees (e.g. two trees with the same segments, however different valid segment enumerations), and potentially have different branch numbers.

  • Every valid segment tree can be used to construct a valid morphology.

Note

Because two topologically-equivalent morphologies may have different segment and branch numbering, it is important that model descriptions should avoid referring to branches or segments by id. This should only be relaxed when the configuration of branches in a particular morphology is known exactly and unambiguously.

To illustrate branch generation, consider the first segment tree example on this page, which is illustrated along with its branches below.

../_images/label_morph.svg

The code used to generate this morphology is in the segment_tree documentation below.

The first branch contains the soma and the first two segments of the dendritic tree. There are four more branches in the dendritic tree, and one representing the two segments of the axon.

Note, that though it is possible to create an unbranched sequence of segments composed of the axon, soma and first two segments in the dendritic tree, this sequence is decomposed as two branches because segments 0 (soma) and 9 (first segment in axon) are at the root of the tree.

Similarly to segments, the branches in a morphology have a parent child relationship. Every branch has one parent, with branches at the root of the tree having the placeholder parent index mnpos. Segments can have any non-negative number of children, however by nature of their construction, no branch can have only one child: a branch has either no children, or two or more children. The parent-child information and segments for the morphology are summarized:

Branch

Parent

Children

Segments

0

mnpos

[1, 2]

[0, 1, 2]

1

0

[]

[3, 4]

2

0

[3, 4]

[5]

3

2

[]

[6]

4

2

[]

[7, 8]

5

mnpos

[]

[9, 10]

Gaps between segments do not influence branch creation, hence branches can contain gaps between segments. Take the example of a morphology with a gap between the soma and the axon and dendritic trees:

../_images/detached_morph.svg

The soma is part of branch 0, despite the gap:

Branch

Parent

Children

Segments

0

mnpos

[1, 2]

[0, 1, 2]

1

0

[]

[3, 4]

2

0

[3, 4]

[5]

3

2

[]

[6]

4

2

[]

[7, 8]

5

mnpos

[]

[9]

Tag information is not used when creating branches, so that a branch can contain segments with different tags, which in our examples gives branches that contain both soma and dendrite segments. For example, when building the soma from multiple segments:

../_images/stacked_morph.svg

The morphology has the same number of branches as the other examples, with multiple soma and dendrite segments in branch 0.

Branch

Parent

Children

Segments

0

mnpos

[1, 2]

[0, 1, 2, 3, 4, 5]

1

0

[]

[6, 7]

2

0

[3, 4]

[8]

3

2

[]

[9]

4

2

[]

[10, 11]

5

mnpos

[]

[12, 13]

Note

Arbor provides a consistent representation of morphologies with no special cases for concepts like magical soma branches, in order to build reproducible and consistent model descriptions.

Users of NEURON who are used to creating a separate soma section that is always the first section in a morphology should not worry that the soma is not treated as a special branch in the examples above.

The soma in the examples above can be referred to in later model building phases, for example when describing the distribution of ion channels, by using referring to all parts of the cell with tag 1.

Examples

Here we present a series of morphology examples of increasing complexity. The examples use the Python API are two-dimensional, with the z-dimension set to zero.

Example 1: Spherical cell

A simple model of a cell as a sphere can be modelled using a cylinder with length and diameter equal to the diameter of the sphere, which will have the same surface area (disregarding the area of the cylinder’s circular ends).

Here a cylinder of length and diameter 5 μm is used to represent a spherical cell with a radius of 2 μm, centred at the origin.

tree = arbor.segment_tree()
tree.append(mnpos, mpoint(-2, 0, 0, 2), mpoint(2, 0, 0, 2), tag=1)
morph = arbor.morphology(tree)
../_images/sphere_morph.svg

The morphology is a single cylinder segment (left) that forms branch 0 (right).

Example 2: Unbranched cable

Consider a cable of length 10 μm, with a radius that tapers from 1 μm to 0.5 μm at the proximal and distal ends respectively. This can be described using a single segment.

tree = arbor.segment_tree()
tree.append(mnpos, mpoint(0, 0, 0, 1), mpoint(10, 0, 0, 0.5), tag=3)
morph = arbor.morphology(tree)
../_images/branch_morph1.svg

A tapered cable with one cable segment (left), generates a morphology with one branch (right).

The radius of a cable segment varies linearly between its end points. To define an unbranched cable with irregular radius and “squiggly” shape, use multiple segments to build a piecewise linear reconstruction of the cable geometry. This example starts and ends at the same locations as the previous, however it is constructed from 4 distinct cable segments:

tree = arbor.segment_tree()
tree.append(mnpos, mpoint( 0.0,  0.0,  0.0, 1.0), mpoint( 3.0,  0.2,  0.0, 0.8), tag=1)
tree.append(0,     mpoint( 3.0,  0.2,  0.0, 0.8), mpoint( 5.0, -0.1,  0.0, 0.7), tag=2)
tree.append(1,     mpoint( 5.0, -0.1,  0.0, 0.7), mpoint( 8.0,  0.0,  0.0, 0.6), tag=2)
tree.append(2,     mpoint( 8.0,  0.0,  0.0, 0.6), mpoint(10.0,  0.0,  0.0, 0.5), tag=3)
morph = arbor.morphology(tree)
../_images/branch_morph2.svg

The morphology is an unbranched cable comprised of 4 cable segments, coloured according to their tags: tag 1 red; tag 2 green; tag 3 blue (left). The four segments form one branch (right).

Gaps are possible between two segments. The example below inserts a 1 μm gap between the second and third segments of the previous morphology. Note that Arbor will ignore the gap, effectively joining the segments together, such that the morphology with the gap is the same as that without.

tree = arbor.segment_tree()
tree.append(mnpos, mpoint( 0.0,  0.0,  0.0, 1.0), mpoint(3.0,  0.2,  0.0, 0.8), tag=1)
tree.append(0,     mpoint( 3.0,  0.2,  0.0, 0.8), mpoint(5.0, -0.1,  0.0, 0.7), tag=2)
tree.append(1,     mpoint( 7.0, -0.1,  0.0, 0.7), mpoint(10.0, 0.0,  0.0, 0.6), tag=2)
tree.append(2,     mpoint(10.0,  0.0,  0.0, 0.6), mpoint(12.0, 0.0,  0.0, 0.5), tag=3)
morph = arbor.morphology(tree)
../_images/branch_morph3.svg

There is a gap between segment 1 and segment 2 (left), and there is a single branch (right).

The radius of a cable is piecewise linear, with discontinuities permitted at the interface between segments. The next example adds a discontinuity to the previous example between segments 3 and 4, where the radius changes from 0.5 μm to 0.3 μm:

tree = arbor.segment_tree()
tree.append(mnpos, mpoint( 0.0,  0.0,  0.0, 1.0), mpoint( 3.0,  0.2,  0.0, 0.8), tag=1)
tree.append(0,     mpoint( 3.0,  0.2,  0.0, 0.8), mpoint( 5.0, -0.1,  0.0, 0.7), tag=2)
tree.append(1,     mpoint( 5.0, -0.1,  0.0, 0.7), mpoint( 8.0,  0.0,  0.0, 0.5), tag=2)
tree.append(2,     mpoint( 8.0,  0.0,  0.0, 0.3), mpoint(10.0,  0.0,  0.0, 0.5), tag=3)
morph = arbor.morphology(tree)
../_images/branch_morph4.svg

The resulting morphology has a step discontinuity in radius.

Example 3: Y-shaped cell

The simplest branching morphology is a cable that bifurcates into two branches, which we will call a y-shaped cell. In the example below, the first branch of the tree is a cable of length 10 μm with a a radius that tapers from 1 μm to 0.5 μm. The two child branches are attached to the end of the first branch, and taper from from 0.5 μ m to 0.2 μm.

Note that only the distal point is required to describe the child segments, because the proximal end of each child segment has the same location and radius as the distal end of the parent.

tree = arbor.segment_tree()
tree.append(mnpos, mpoint( 0.0, 0.0, 0.0, 1.0), mpoint(10.0, 0.0, 0.0, 0.5), tag= 3)
tree.append(0,     mpoint(15.0, 3.0, 0.0, 0.2), tag= 3)
tree.append(0,     mpoint(15.0,-3.0, 0.0, 0.2), tag= 3)
morph = arbor.morphology(tree)
../_images/yshaped_morph.svg

Example 4: Soma with branches

Now let’s look at cell with a simple dendritic tree attached to a spherical soma. The spherical soma of radius 3 μm is modelled with a cylinder with length and diameter equal to 6 μm, which has the same surface area as the sphere.

tree = arbor.segment_tree()
tree.append(mnpos, mpoint(-3.0, 0.0, 0.0, 3.0), mpoint( 3.0, 0.0, 0.0, 3.0), tag=1)
tree.append(0, mpoint( 4.0, -1.0,  0.0, 0.6), mpoint(10.0,  -2.0,  0.0, 0.5), tag=3)
tree.append(1, mpoint(15.0, -1.0,  0.0, 0.5), tag=3)
tree.append(2, mpoint(18.0, -5.0,  0.0, 0.3), tag=3)
tree.append(2, mpoint(20.0,  2.0,  0.0, 0.3), tag=3)
morph = arbor.morphology(tree)
../_images/ysoma_morph1.svg

Note that branch 0 (right) is composed of segments 0, 1, and 2 (left).

The soma is the first segment, labelled with tag 1. The dendritic tree is a simple y-shaped tree composed of 4 segments, each labelled with tag 3. The first branch is composed of 3 segments: the soma segment and the first two segments in the dendritic tree because the segments have parent child ordering and no fork points.

Note

The first branch is derived directly from the topological relationship between the segments, and no special treatment is given to the soma. There is no need to treat segments with different tags (e.g. tags that we might associate with soma, axon, basal dendrite and apical dendrite) when defining geometric primitives like segments and branches, because they can later be referenced later using region expressions.

Now we can attach another dendrite and an axon to the soma, to make a total of three cables attached to the soma (two dendrites and an axon). The dendrites are attached to the distal end of the soma (segment 0), so they have the 0 as their parent. The axon is attached to the proximal end of the soma, which is at the root of the tree, so it has mnpos as its parent. There are 7 branches generated from 10 segments, and soma segment is its own branch, because it has two children: the dendrites attached to its distal end.

../_images/ysoma_morph2.svg

Note

The discretisation process, which converts segments and branches into compartments, will ignore gaps between segments in the input. The cell below, in which the dendrites and axon have been translated to remove any gaps, is equivalent to the previous example for the back end simulator.

Note that the dendrites are children of the soma segment, so they are coincident with the distal end of the soma, and the axon is translated to the proximal end of the soma segment because both it and the soma have mnpos as a parent. More generally, segments at the root of the tree are connected electrically at their proximal ends.

../_images/ysoma_morph3.svg

API