Skip to main content

A neuron morphology IO library

Project description

MorphIO Build Status

Table of content

Installation

Dependencies

To build MorphIO from sources, the following dependencies are required:

  • cmake >= 3.2
  • libhdf5-dev
  • A C++11 compiler

Debian:

sudo apt install cmake libhdf5-dev

Red Hat:

sudo yum install cmake3.x86_64 hdf5-devel.x86_64

Max OS:

brew install hdf5 cmake

BB5

source /opt/rh/rh-python36/enable
module load gcc/5.4.0 nix/cmake/3.9.6

Installation instructions

Install as a C++ library

For manual installation:

git clone git@github.com:bluebrain/morphio.git --recursive
cd morphio
mkdir build && cd build
cmake ..
make install

To use the installed library:

find_package(MorphIO REQUIRED)

target_link_libraries(mylib MorphIO::morphio)

Install as a Python package

The python binding can directly be installed using pip:

pip install morphio

Introduction

MorphIO is a library for reading and writing neuron morphology files. It supports the following formats:

  • SWC
  • ASC (aka. neurolucida)
  • H5 v1
  • H5 v2

It provides 3 C++ classes that are the starting point of every morphology analysis:

  • Soma: contains the information related to the soma.

  • Section: a section is the succession of points between two bifurcations. To the bare minimum the Section object will contain the section type, the position and diameter of each point.

  • Morphology: the morphology object contains general information about the loaded cell but also provides accessors to the different sections.

One important concept is that MorphIO is split into a read-only part and a read/write one.

Quick summary

C++ vs Python:

  • C++ accessors become Python properties.
  • style: C++ functions are camel case while Python ones are snake case.

Include/imports

  • C++ mutable
#include <morphio/morphology.h>
#include <morphio/section.h>
#include <morphio/soma.h>
  • Python mutable
from morphio import Morphology, Section, Soma
  • C++ immutable
#include <morphio/mut/morphology.h>
#include <morphio/mut/section.h>
#include <morphio/mut/soma.h>
  • Python immutable
from morphio.mut import Morphology, Section, Soma

Read-only API

The read-only API aims at providing better performances as its internal data representation is contiguous in memory. All accessors return immutable objects.

Internally, in this API the morphology object is in fact where all data are stored. The Soma and Section classes are lightweight classes that provide views on the Morphology data.

For more convenience, all section data are accessed through properties, such as:

points = section.points
diameters = section.diameters

C++

In C++ the API is available under the morphio/mut namespace:

#include <morphio/mut/morphology.h>
#include <morphio/mut/section.h>
#include <morphio/mut/soma.h>

Python

In Python the API is available under the morphio.mut module:

from morphio.mut import Morphology, Section, Soma

Mutable Read/Write API

C++

#include <morphio/morphology.h>
#include <morphio/section.h>

int main()
{
    auto m = morphio::Morphology("sample.asc");

    auto roots = m.rootSections();

    auto first_root = roots[0];

    // iterate on sections starting at first_root
    for (auto it = first_root.depth_begin(); it != first_root.depth_end(); ++it) {
        const morphio::Section &section = *it;

        std::cout << "Section type: " << section.type()
                  << "\nSection id: " << section.id()
                  << "\nParent section id: " << section.parent().id()
                  << "\nNumber of child sections: " << section.children().size()
                  << "\nX - Y - Z - Diameter";
        for (auto i = 0u; i < section.points().size(); ++i) {
            const auto& point = section.points()[i];
            std::copy(point.begin(), point.end(), std::ostream_iterator<float>(std::cout, " "));
            std::cout << '\n' << section.diameters()[i] << '\n';
        }
        std::cout << '\n';
    }
}

Python

from morphio import Morphology

m = Morphology("sample.asc")
roots = m.root_sections
first_root = roots[0]

# iterate on sections starting at first_root
for section in first_root.iter():
    print("Section type: {}".format(section.type))
    print("Section id: {}".format(section.id))
    if not section.is_root:
       print("Parent section id: {}".format(section.parent.id))
    print("Number of child sections: {}".format(len(section.children)))
    print("X - Y - Z - Diameter")

    for point, diameter in zip(section.points, section.diameters):
        print('{} - {}'.format(point, diameter))

Creating morphologies with the mutable API

Here is a simple example to create a morphology from scratch and write it to disk

#include <morphio/mut/morphology.h>

int main()
{
    morphio::mut::Morphology morpho;
    morpho.soma()->points() = {{0, 0, 0}, {1, 1, 1}};
    morpho.soma()->diameters() = {1, 1};

    auto section = morpho.appendRootSection(
        morphio::Property::PointLevel(
            {{2, 2, 2}, {3, 3, 3}}, // x,y,z coordinates of each point
            {4, 4}, // diameter of each point
            {5, 5}),
        morphio::SectionType::SECTION_AXON); // (optional) perimeter of each point

    auto childSection = section->appendSection(
        morphio::Property::PointLevel(
            {{3, 3, 3}, {4, 4, 4}},
            {4, 4},
            {5, 5}),
        morphio::SectionType::SECTION_AXON);

    // Writing the file in the 3 formats
    morpho.write("outfile.asc");
    morpho.write("outfile.swc");
    morpho.write("outfile.h5");
}

Mutable Python

Reading morphologies

from morphio.mut import Morphology

m = Morphology("sample.asc")
roots = m.root_sections
first_root = roots[0]

# iterate on sections starting at first_root
for section in m.iter(first_root):
    print("Section type: {}".format(section.type))
    print("Section id: {}".format(section.id))
    if not m.is_root(section):
        print("Parent section id: {}".format(m.parent(section)))
    print("Number of child sections: {}".format(len(m.children(section))))
    print("X - Y - Z - Diameter")

    for point, diameter in zip(section.points, section.diameters):
        print('{} - {}'.format(point, diameter))

Creating morphologies

Here is a simple example to create a morphology from scratch and writing it to disk

from morphio.mut import Morphology
from morphio import SectionType, PointLevel

morpho = Morphology()
morpho.soma.points = [[0, 0, 0], [1, 1, 1]]
morpho.soma.diameters = [1, 1]

section = morpho.append_root_section(
    PointLevel(
        [[2, 2, 2], [3, 3, 3]],  # x, y, z coordinates of each point
        [4, 4],  # diameter of each point
        [5, 5]),
    SectionType.axon)  # (optional) perimeter of each point

child_section = section.append_section(
    PointLevel(
        [[3, 3, 3], [4, 4, 4]],
        [4, 4],
        [5, 5])) # section type is omitted -> parent section type will be used

morpho.write("outfile.asc")
morpho.write("outfile.swc")
morpho.write("outfile.h5")

Opening flags

When opening the file, modifier flags can be passed to alter the morphology representation. The following flags are supported:

  • morphio::NO_MODIFIER: This is the default flag, it will do nothing.
  • morphio::TWO_POINTS_SECTIONS: Each section gets reduce to a line made of the first and last point.
  • morphio::SOMA_SPHERE: The soma is reduced to a sphere which is the center of gravity of the real soma.
  • morphio::NO_DUPLICATES: The duplicate point are not present. It means the first point of each section is no longer the last point of the parent section.
  • morphio::NRN_ORDER: Neurite are reordered according to the NEURON simulator ordering

Multiple flags can be passed by using the standard bit flag manipulation (works the same way in C++ and Python):

C++:

#include <morphio/Morphology.h>
Morphology("myfile.asc", options=morphio::NO_DUPLICATES|morphio::NRN_ORDER)

Python:

from morphio import Morphology, Option
Morphology("myfile.asc", options=Option.no_duplicates|Option.nrn_order)

Glia

MorphIO also support reading and writing glia (such as astrocytes) from/to disk according to the H5 specification https://bbpteam.epfl.ch/documentation/projects/Morphology%20Documentation/latest/h5v1.html

Python:

import morphio

# Immutable
immutable_glia = morphio.GlialCell("astrocyte.h5")

# Mutable
empty_glia = morphio.mut.GlialCell()
mutable_glia = morphio.mut.GlialCell("astrocyte.h5")

Mitochondria

It is also possible to read and write mitochondria from/to the h5 files (SWC and ASC are not supported). As mitochondria can be represented as trees, one can define the concept of mitochondrial section similar to neuronal section and end up with a similar API. The morphology object has a mitochondria handle method that exposes the basic methods:

  • root_sections: returns the section ID of the starting mitochondrial section of each mitochondrion.
  • section(id): returns a given mitochondrial section
  • append_section: creates a new mitochondrial section _ depth_begin: a depth first iterator _ breadth_begin: a breadth first iterator _ upstream_begin: an upstream iterator
from morphio.mut import Morphology
from morphio import MitochondriaPointLevel, PointLevel, SectionType

morpho = Morphology()

# A neuronal section that will store mitochondria
section = morpho.append_root_section(
    PointLevel([[2, 2, 2], [3, 3, 3]], [4, 4], [5, 5]),
    SectionType.axon)

# Creating a new mitochondrion
mito_id = morpho.mitochondria.append_section(
    -1,
    MitochondriaPointLevel([section.id, section.id], # section id hosting the mitochondria point
                           [0.5, 0.6], # relative distance between the start of the section and the point
                           [10, 20] # mitochondria diameters
                           ))

# Appending a new mitochondrial section to the previous one
morpho.mitochondria.append_section(
    mito_id, MitochondriaPointLevel([0, 0, 0, 0],
                                    [0.6, 0.7, 0.8, 0.9],
                                    [20, 30, 40, 50]))

# Iteration works the same as iteration on neuronal sections
first_root = morpho.mitochondria.root_sections[0]
for section_id in morpho.mitochondria.depth_begin(first_root):
    section = morpho.mitochondria.section(section_id)
    print('relative_path_length - diameter')
    for relative_path_length, diameter in zip(section.diameters,
                                              section.relative_path_lengths):
        print("{} - {}".format(relative_path_length, diameter))

Reading mithochondria from H5 files:

from morphio import Morphology

morpho = Morphology("file_with_mithochondria.h5")

for mitochondrial_section in morpho.mitochondria.root_sections:
    print('{neurite_id}, {relative_path_lengths}, {diameters}'.format(
          neurite_id=mitochondrial_section.neurite_section_ids,
          relative_path_lengths=mitochondrial_section.relative_path_lengths,
          diameters=mitochondrial_section.diameters))

    print("Number of children: {}".format(len(mitochondrial_section.children)))

Endoplasmic reticulum

Endoplasmic reticulum can also be stored and written to H5 file. The specification is part of the BBP morphology documentation There is one endoplasmic reticulum object per morphology. It contains 4 attributes. Each attribute is an array and each line refers to the value of the attribute for a specific neuronal section.

  • section_index: Each row of this dataset represents the index of a neuronal section. Each row of the other properties (eg. volume) refer to the part of the reticulum present in the corresponding section for each row.

  • volume: One column dataset indexed by section_index. Contains volumes of the reticulum per each corresponding section it lies in.

  • surface_area: Similar to the volume dataset, this dataset represents the surface area of the reticulum in each section in the section_index dataset.

  • filament_count: This 1 column dataset is composed of integers that represent the number of filaments in the segment of the reticulum lying in the section referenced by the corresponding row in the section_index dataset.

Reading endoplasmic reticula from H5 files

from morphio import Morphology

morpho = Morphology('/my/file')
reticulum = morpho.endoplasmic_reticulum
print('{indices}, {volumes}, {areas}, {counts}'.format(
    indices=reticulum.section_indices,
    volumes=reticulum.volumes,
    areas=reticulum.surface_areas,
    counts=reticulum.filament_counts))

Writing endoplasmic reticula from H5 files

neuron = Morphology()

reticulum = neuron.endoplasmic_reticulum
reticulum.section_indices = [1, 1]
reticulum.volumes = [2, 2]
reticulum.surface_areas = [3, 3]
reticulum.filament_counts = [4, 4]
neuron.write('/my/out/file.h5')  # Has to be written to h5

Tips

Maximum number of warnings

On can control the maximum number of warnings using the command:

# Will stop displaying warnings after 100 warnings
morphio.set_maximum_warnings(100)

# Will never stop displaying warnings
morphio.set_maximum_warnings(-1)

# Warnings won't be displayed
morphio.set_maximum_warnings(0)

Specification

See https://github.com/BlueBrain/MorphIO/blob/master/doc/specification.md

H5v2

Starting at version 2.5.2, the file format h5v2 is no longer supported. If you have morphologies in this format, you can convert them with:

pip install morphio==2.5.1 morph-tool==2.3.0

and then:

# single file, OUTPUT must end with `.h5`
morph-tool convert file INPUTFILE OUTPUT

# bulk conversion
morph-tool convert folder -ext h5 INPUTDIR OUTPUTDIR

Contributing

If you want to improve the project or you see any issue, every contribution is welcome. Please check the contribution guidelines for more information.

Acknowledgements

This research was supported by the EBRAINS research infrastructure, funded from the European Union’s Horizon 2020 Framework Programme for Research and Innovation under the Specific Grant Agreement No. 945539 (Human Brain Project SGA3).

License

MorphIO is licensed under the terms of the GNU Lesser General Public License version 3. Refer to COPYING.LESSER and COPYING for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

MorphIO-2.5.2.tar.gz (3.6 MB view details)

Uploaded Source

Built Distributions

MorphIO-2.5.2-cp38-cp38-manylinux2014_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.8

MorphIO-2.5.2-cp38-cp38-macosx_10_13_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.8 macOS 10.13+ x86-64

MorphIO-2.5.2-cp37-cp37m-manylinux2014_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.7m

MorphIO-2.5.2-cp37-cp37m-macosx_10_13_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.7m macOS 10.13+ x86-64

MorphIO-2.5.2-cp36-cp36m-manylinux2014_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.6m

MorphIO-2.5.2-cp36-cp36m-macosx_10_13_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.6m macOS 10.13+ x86-64

File details

Details for the file MorphIO-2.5.2.tar.gz.

File metadata

  • Download URL: MorphIO-2.5.2.tar.gz
  • Upload date:
  • Size: 3.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7

File hashes

Hashes for MorphIO-2.5.2.tar.gz
Algorithm Hash digest
SHA256 3f749f95700d4021c1eee3bb8bb6571b1e902f134cceef85d3c3cf5ccd4545e2
MD5 3673531c06b843375ecc11d2f7130ef1
BLAKE2b-256 81fd39830e0bce409d337526bb27ee2f09eb881d31e56e2fae54a8aa96f212fe

See more details on using hashes here.

File details

Details for the file MorphIO-2.5.2-cp38-cp38-manylinux2014_x86_64.whl.

File metadata

  • Download URL: MorphIO-2.5.2-cp38-cp38-manylinux2014_x86_64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.8
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7

File hashes

Hashes for MorphIO-2.5.2-cp38-cp38-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c19c006626dc52b9964e3263b9f817bde8027c90a6b7e6a8f68b4fbd41ee3d95
MD5 28b04981e18c667fea7136149353589b
BLAKE2b-256 e5e9845f769c8fab938a294eba785fc54245fdfe106950dbaf77f1979998b1e3

See more details on using hashes here.

File details

Details for the file MorphIO-2.5.2-cp38-cp38-macosx_10_13_x86_64.whl.

File metadata

  • Download URL: MorphIO-2.5.2-cp38-cp38-macosx_10_13_x86_64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.8, macOS 10.13+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7

File hashes

Hashes for MorphIO-2.5.2-cp38-cp38-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 f6318f012edebe53872a8395f1362668a6d73581150efb80d3f15465121ff87e
MD5 01ccdf128a573b6eb8869fb8949955e6
BLAKE2b-256 5e4a6df4939ca4b7b51ca0df07b1a25d70415e7329827cc5be283027ce2c60fb

See more details on using hashes here.

File details

Details for the file MorphIO-2.5.2-cp37-cp37m-manylinux2014_x86_64.whl.

File metadata

  • Download URL: MorphIO-2.5.2-cp37-cp37m-manylinux2014_x86_64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.7m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7

File hashes

Hashes for MorphIO-2.5.2-cp37-cp37m-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3f5a0e0bc08f8d5d8768a4fc7fd7d253754b385f13bbcdde29ce16fb785d2ac3
MD5 5cbbb87042a750636db4de0ebbcbac76
BLAKE2b-256 9a945ec06c6bc282b18ff13a83cf8b77f4c9580a35c2d5bd5cd76b8b6bb5489d

See more details on using hashes here.

File details

Details for the file MorphIO-2.5.2-cp37-cp37m-macosx_10_13_x86_64.whl.

File metadata

  • Download URL: MorphIO-2.5.2-cp37-cp37m-macosx_10_13_x86_64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.7m, macOS 10.13+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7

File hashes

Hashes for MorphIO-2.5.2-cp37-cp37m-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 6232d4a2dcf475b3384df4c79fb95da6a0da99c6708df0f38d20965dfec0080b
MD5 90ba1b178de2e8b72b7ec70497b0da09
BLAKE2b-256 7240035fc260591b2bddbc02ef485230a023a8f927c589da727de9eec81fc4bf

See more details on using hashes here.

File details

Details for the file MorphIO-2.5.2-cp36-cp36m-manylinux2014_x86_64.whl.

File metadata

  • Download URL: MorphIO-2.5.2-cp36-cp36m-manylinux2014_x86_64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.6m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7

File hashes

Hashes for MorphIO-2.5.2-cp36-cp36m-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 549248fb1beaab1add19e0bd87b7309e80ae5fa899d15fa1d84974e12efe5a65
MD5 6637893172ce6ab7c60aef22c124407d
BLAKE2b-256 de3109a3515968b3cffd6884133959ef7777c6a5666e3da0339411fb48c1e020

See more details on using hashes here.

File details

Details for the file MorphIO-2.5.2-cp36-cp36m-macosx_10_13_x86_64.whl.

File metadata

  • Download URL: MorphIO-2.5.2-cp36-cp36m-macosx_10_13_x86_64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.6m, macOS 10.13+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/53.0.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7

File hashes

Hashes for MorphIO-2.5.2-cp36-cp36m-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 ef43cc451643ad407f42d6278fd711ec2d2270f101f34cd374a354902f0fef46
MD5 e0ac740f8667243cdb8569459f50c10a
BLAKE2b-256 e51f260295f4274aaafbe4e0bc327f8fafb8b959de49146056edb6cb19c40df4

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page