.. _include_morphos: ################### Adding morphologies ################### .. note:: This guide is a continuation of the :doc:`Getting Started guide `. Previously, we constructed a stacked double layer topology, with 2 cell types. We then connected these cell type populations in an all-to-all fashion. In this tutorial, we are going to assign :doc:`morphologies ` to our cells, and connects the cells based on the intersection of their morphologies! You will learn how to load morphologies from local files or to fetch from remote sources, like NeuroMorpho, using the BSB. | But first, we need actual morphology files. | Download your 2 favorite morphologies from `NeuroMorpho `_ in the swc file format and save them as ``neuron_A.swc`` and ``neuron2.swc`` in your project folder. Using local files ================= :guilabel:`morphologies` is a list component of the BSB configuration responsible to fetch and load morphology files. Here is the minimal configuration example to add a morphology to the scaffold: .. tab-set-code:: .. literalinclude:: ../configs/include_morphos.yaml :language: yaml :lines: 9-10 .. code-block:: json "morphologies": ["neuron_A.swc"] .. code-block:: python config.morphologies = ["neuron_A.swc"] In this case, a morphology is created from ``neuron_A.swc`` and given the name ``"neuron_A"``. By default the name assigned to the morphology is the file name without its extension (here ``.swc``). Next, we need to associate this morphology to one cell type, here the ``base_type``, by referencing it by name in :guilabel:`cell_types.base_type.spatial.morphologies`: .. tab-set-code:: .. literalinclude:: ../configs/include_morphos.yaml :language: yaml :lines: 28-34 :emphasize-lines: 6-7 .. literalinclude:: ../configs/include_morphos.json :language: json :lines: 35-42 :emphasize-lines: 6 .. literalinclude:: /../examples/tutorials/include_morphos.py :language: python :lines: 27-34 :emphasize-lines: 6 .. note:: If there are multiple morphologies per cell type, they will be assigned randomly, unless you specify a :ref:`MorphologyDistributor `. Let's add the second morphology but this time we will change its name with a morphology node containing the attributes :guilabel:`name` and :guilabel:`file`: .. tab-set-code:: .. literalinclude:: ../configs/include_morphos.yaml :language: yaml :lines: 9-12 :emphasize-lines: 3-4 .. literalinclude:: ../configs/include_morphos.json :language: json :lines: 12-17 :emphasize-lines: 3-6 .. literalinclude:: /../examples/tutorials/include_morphos.py :language: python :lines: 22-25 :emphasize-lines: 3 It is also possible to add a pipeline to perform transformations on the loaded morphology. Pipelines can be added with a :guilabel:`pipeline` list component to the morphology node. Each item in the list may either be a string reference to a method of the :class:`bsb:bsb.morphologies.Morphology` class or an importable function. If the function requires parameters, use a node with the function reference placed in the :guilabel:`func` attribute, and a :guilabel:`parameters` list. Here is an example what that would look like: .. tab-set-code:: .. code-block:: yaml morphologies: - file: my_neuron.swc pipeline: - center - my_module.add_axon - func: rotate rotation: [20, 0, 20] .. code-block:: json "morphologies": [ { "file": "my_neuron.swc", "pipeline": [ "center", "my_module.add_axon", { "func": "rotate", "rotation": [20, 0, 20] }, ], } ] .. code-block:: python config.morphologies = [ dict( file= "my_neuron.swc", pipeline=[ "center", "my_module.add_axon", dict(func="rotate", rotation=[20, 0, 20]) ] ) ] In this case, we created a pipeline of 3 steps: 1. Reset the origin of the morphology, using the :meth:`bsb:bsb.morphologies.SubTree.center` function from the Morphology class. 2. Run the :guilabel:`add_axon` function from the external file `my_module.py` 3. Rotate the morphology by 20 degrees along the x and z axis, using the :meth:`bsb:bsb.morphologies.SubTree.rotate` function from the Morphology class. .. note:: Any additional keys given in a pipeline step, such as :guilabel:`rotation` in the example, are passed to the function as keyword arguments. Morphology intersection ======================= Now that we have assigned morphologies to our cell types, we can use morphology-based connection strategies such as :doc:`VoxelIntersection `: .. tab-set-code:: .. literalinclude:: ../configs/include_morphos.yaml :language: yaml :lines: 55-63 .. literalinclude:: ../configs/include_morphos.json :language: json :lines: 65-75 .. literalinclude:: /../examples/tutorials/include_morphos.py :language: python :lines: 59-64 Note also that with Voxel Intersection, you can specify which parts of the morphologies should create contacts (e.g, dendrites and axons): .. code-block:: json "connectivity": { "A_to_B": { "strategy": "bsb.connectivity.VoxelIntersection", "presynaptic": { "cell_types": ["base_type"], "morphology_labels": ["axon"] }, "postsynaptic": { "cell_types": ["top_type"], "morphology_labels": ["dendrites"] } } } This happens thanks to the labels that are attached to your morphology points. .. tip:: Do not forget to recompile your network if you are modifying the configuration file. Final configuration file ======================== .. tab-set-code:: .. literalinclude:: ../configs/include_morphos.yaml :language: yaml .. literalinclude:: ../configs/include_morphos.json :language: json .. literalinclude:: /../examples/tutorials/include_morphos.py :language: python What is next? ============= Next tutorial is on :doc:`running a simulation ` of your network.