Adding morphologies#

Note

This guide is a continuation of the 📚 Getting Started guide.

Hint

To follow along, download 2 morphologies from NeuroMorpho and save them as neuron_A.swc and neuron2.swc locally.

Previously we constructed a stacked double layer topology, with 2 cell types. We then connected them in an all-to-all fashion. The next step assigns morphologies to our cells, and connects the cells based on the intersection of their morphologies!

Morphologies can be loaded from local files or to fetch from remote sources, like NeuroMorpho.

Using local files#

You can declare source morphologies in the root morphologies list:

morphologies:
- neuron_A.swc
"morphologies": [
  "neuron_A"
],
    {"name": "neuron_B", "file": "neuron2.swc"},
]
config.cell_types.base_type.spatial.morphologies = ["neuron_A"]

In this case a morphology is created from neuron_A.swc and given the name "neuron_A". As a second step, we associate this morphology to the base_type by referencing it by name in cell_types.base_type.spatial.morphologies:

cell_types:
  base_type:
    spatial:
      radius: 2
      density: 0.001
      morphologies:
      - neuron_A
  "cell_types": {
    "base_type": {
      "spatial": {
        "radius": 2,
        "density": 1e-3,
        "morphologies": [
          "neuron_A"
        ]
      }
    },
config.morphologies.append(

By default the name assigned to the morphology is the file name without its extension (here .swc). To change the name we can use a node with a name and file:

morphologies:
- neuron_A.swc
- name: neuron_B
  file: neuron2.swc
  "morphologies": [
    "neuron_A.swc",
    {
      "name": "neuron_B",
      "file": "neuron2.swc"
    },
    {"name": "neuron_B", "file": "neuron2.swc"},
]

config.cell_types.base_type.spatial.morphologies = ["neuron_A"]

It is also possible to add a pipeline to perform transformations on the loaded morphology. Pipelines can be added by adding a :guilabel`pipeline` list to the morphology node. Each item in the list may either be a string reference to an importable function or a method of the Morphology class. To pass parameters, use a node with the function reference placed in the guilabel:func attribute, and a parameters list. Here is an example what that would look like:

morphologies:
  - file: my_neuron.swc
    pipeline:
      - center
      - my_module.add_axon
      - func: rotate
        rotation: [20, 0, 20]
"morphologies": [
  {
    "file": "my_neuron.swc",
    "pipeline": [
      "center",
      "my_module.add_axon",
      {
        "func": "rotate",
        "rotation": [20, 0, 20]
      },
    ],
  }
]

Note

Any additional keys given in a pipeline step, such as rotation in the example, are passed to the function as keyword arguments.

Fetching with alternative URI schemes#

The framework uses URI schemes to define the path of the sources that are loaded. By default it tries to load from the project local folder, using the``file`` URI scheme ("file://"). It is possible to fetch morphologies directly from neuromorpho.org using the NeuroMorpho scheme ("nm://"). You can refer to NeuroMorpho morphologies by their morphology name:

../_images/nm_what.png
morphologies:
- neuron_A.swc
- name: neuron_B
  file: neuron2.swc
  "morphologies": [
    "neuron_A.swc",
    {
      "name": "neuron_B",
      "file": "neuron2.swc"
    },
    {
       "name": "neuron_NM",
       "file": "nm://cell005_GroundTruth"
    }
  ],
  "cell_types": {
    "base_type": {
      "spatial": {
        "radius": 2,
        "density": 1e-3,
        "morphologies": [
          "neuron_A"
        ]
      }
    },
    "top_type": {
      "spatial": {
        "radius": 7,
        "count": 10,
        "morphologies": [
          "neuron_B",
          "neuron_NM"
        ]
      }
    }
  },
)

config.cell_types.add(
    "top_type",
    spatial=dict(
        radius=7,
        count=10,
        morphologies=["neuron_B", "neuron_NM"],
    ),
)
config.placement.add(
    "all_placement",

Morphology intersection#

Now that we have assigned morphologies to our cell types, we can use morphology-based connection strategies such as VoxelIntersection:

connectivity:
  A_to_B:
    strategy: bsb.connectivity.VoxelIntersection
    presynaptic:
      cell_types:
      - base_type
    postsynaptic:
      cell_types:
      - top_type
  "connectivity": {
    "A_to_B": {
      "strategy": "bsb.connectivity.VoxelIntersection",
      "presynaptic": {
        "cell_types": ["base_type"]
      },
      "postsynaptic": {
          "cell_types": ["top_type"]
      }
    }
  }
    strategy="bsb.connectivity.VoxelIntersection",
    presynaptic=dict(cell_types=["base_type"]),
    postsynaptic=dict(cell_types=["top_type"]),
)

network = Scaffold(config)

Note

If there’s multiple morphologies per cell type, they’ll be assigned randomly, unless you specify a MorphologyDistributor.

Recap#

name: Starting example
storage:
  engine: hdf5
  root: network.hdf5
network:
  x: 400
  y: 600
  z: 400
morphologies:
- neuron_A.swc
- name: neuron_B
  file: neuron2.swc
- name: neron_NM
  file: nm://cell005_GroundTruth
regions:
  brain_region:
    type: stack
    children:
    - base_layer
    - top_layer
partitions:
  base_layer:
    type: layer
    thickness: 100
    stack_index: 0
  top_layer:
    type: layer
    thickness: 100
    stack_index: 1
cell_types:
  base_type:
    spatial:
      radius: 2
      density: 0.001
      morphologies:
      - neuron_A
  top_type:
    spatial:
      radius: 7
      count: 10
      morphologies:
      - neuron_NM
placement:
  base_placement:
    strategy: bsb.placement.RandomPlacement
    cell_types:
    - base_type
    partitions:
    - base_layer
  top_placement:
    strategy: bsb.placement.RandomPlacement
    cell_types:
    - top_type
    partitions:
    - top_layer
connectivity:
  A_to_B:
    strategy: bsb.connectivity.VoxelIntersection
    presynaptic:
      cell_types:
      - base_type
    postsynaptic:
      cell_types:
      - top_type
{
  "name": "Starting example",
  "storage": {
    "engine": "hdf5",
    "root": "network.hdf5"
  },
  "network": {
    "x": 400.0,
    "y": 600.0,
    "z": 400.0
  },
  "morphologies": [
    "neuron_A.swc",
    {
      "name": "neuron_B",
      "file": "neuron2.swc"
    },
    {
       "name": "neuron_NM",
       "file": "nm://cell005_GroundTruth"
    }
  ],
  "regions": {
    "brain_region": {
      "type": "stack",
      "children": ["base_layer", "top_layer"]
    }
  },
  "partitions": {
    "base_layer": {
      "type": "layer",
      "thickness": 100,
      "stack_index": 0
    },
    "top_layer": {
      "type": "layer",
      "thickness": 100,
      "stack_index": 1
    }
  },
  "cell_types": {
    "base_type": {
      "spatial": {
        "radius": 2,
        "density": 1e-3,
        "morphologies": [
          "neuron_A"
        ]
      }
    },
    "top_type": {
      "spatial": {
        "radius": 7,
        "count": 10,
        "morphologies": [
          "neuron_B",
          "neuron_NM"
        ]
      }
    }
  },
  "placement": {
    "base_placement": {
      "strategy": "bsb.placement.RandomPlacement",
      "cell_types": ["base_type"],
      "partitions": ["base_layer"]
    },
    "top_placement": {
      "strategy": "bsb.placement.RandomPlacement",
      "cell_types": ["top_type"],
      "partitions": ["top_layer"]
    }
  },
  "connectivity": {
    "A_to_B": {
      "strategy": "bsb.connectivity.VoxelIntersection",
      "presynaptic": {
        "cell_types": ["base_type"]
      },
      "postsynaptic": {
          "cell_types": ["top_type"]
      }
    }
  }
}
from bsb_plot import plot_network

import bsb.options
from bsb import Scaffold, Stack, from_json

bsb.options.verbosity = 3
config = from_json("network_configuration.json")

config.partitions.add("top_layer", thickness=100, stack_index=1)
config.regions["brain_region"] = Stack(
    children=[
        "base_layer",
        "top_layer",
    ]
)
config.morphologies = [
    "neuron_A.swc",
    {"name": "neuron_B", "file": "neuron2.swc"},
]

config.cell_types.base_type.spatial.morphologies = ["neuron_A"]

config.morphologies.append(
    {"name": "neuron_NM", "file": "nm://cell005_GroundTruth"},
)

config.cell_types.add(
    "top_type",
    spatial=dict(
        radius=7,
        count=10,
        morphologies=["neuron_B", "neuron_NM"],
    ),
)
config.placement.add(
    "all_placement",
    strategy="bsb.placement.RandomPlacement",
    cell_types=["base_type", "top_type"],
    partitions=["base_layer"],
)
config.connectivity.add(
    "A_to_B",
    strategy="bsb.connectivity.VoxelIntersection",
    presynaptic=dict(cell_types=["base_type"]),
    postsynaptic=dict(cell_types=["top_type"]),
)

network = Scaffold(config)

network.compile()
plot_network(network)