From 89800b68611d158c7dfee011b481d394410483fd Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Tue, 1 Mar 2022 20:01:47 +0100 Subject: [PATCH 1/5] don't use exceptions when non-exceptional methods are available --- include/morphio/mut/mitochondria.h | 2 +- src/morphology.cpp | 153 +++++++++++++++-------------- src/mut/mito_section.cpp | 7 +- src/mut/mitochondria.cpp | 22 ++--- tests/test_3_h5.py | 2 +- tests/test_morphology_readers.cpp | 4 +- 6 files changed, 90 insertions(+), 100 deletions(-) diff --git a/include/morphio/mut/mitochondria.h b/include/morphio/mut/mitochondria.h index 183eb645c..35db1dd74 100644 --- a/include/morphio/mut/mitochondria.h +++ b/include/morphio/mut/mitochondria.h @@ -77,7 +77,7 @@ class Mitochondria /** Append a new root MitoSection **/ - MitoSectionP appendRootSection(const Property::MitochondriaPointLevel& points); + MitoSectionP appendRootSection(const Property::MitochondriaPointLevel& pointProperties); /** Append a root MitoSection diff --git a/src/morphology.cpp b/src/morphology.cpp index 32800254a..f9f24c385 100644 --- a/src/morphology.cpp +++ b/src/morphology.cpp @@ -13,10 +13,72 @@ #include "readers/morphologyHDF5.h" #include "readers/morphologySWC.h" +namespace { + +void buildChildren(const std::shared_ptr properties) { + { + const auto& sections = properties->get(); + auto& children = properties->_sectionLevel._children; + + for (unsigned int i = 0; i < sections.size(); ++i) { + const int32_t parent = sections[i][1]; + children[parent].push_back(i); + } + } + + { + const auto& sections = properties->get(); + auto& children = properties->_mitochondriaSectionLevel._children; + + for (unsigned int i = 0; i < sections.size(); ++i) { + const int32_t parent = sections[i][1]; + children[parent].push_back(i); + } + } +} + +morphio::SomaType getSomaType(long unsigned int num_soma_points) { + switch (num_soma_points) { + case 0: + return morphio::SOMA_UNDEFINED; + case 1: + return morphio::SOMA_SINGLE_POINT; + case 2: + return morphio::SOMA_UNDEFINED; + default:; + } + return morphio::SOMA_SIMPLE_CONTOUR; +} + +morphio::Property::Properties loadURI(const std::string& source, unsigned int options) { + const size_t pos = source.find_last_of('.'); + if (pos == std::string::npos) { + throw(morphio::UnknownFileType("File has no extension")); + } + + // Cross-platform check of file existance + std::ifstream file(source.c_str()); + if (!file) { + throw(morphio::RawDataError("File: " + source + " does not exist.")); + } + + std::string extension = source.substr(pos); + + if (extension == ".h5" || extension == ".H5") { + return morphio::readers::h5::load(source); + } else if (extension == ".asc" || extension == ".ASC") { + return morphio::readers::asc::load(source, options); + } else if (extension == ".swc" || extension == ".SWC") { + return morphio::readers::swc::load(source, options); + } + + throw(morphio::UnknownFileType("Unhandled file type: only SWC, ASC and H5 are supported")); +} + + +} // namespace + namespace morphio { -void buildChildren(std::shared_ptr properties); -SomaType getSomaType(long unsigned int num_soma_point); -Property::Properties loadURI(const std::string& source, unsigned int options); Morphology::Morphology(const Property::Properties& properties, unsigned int options) : properties_(std::make_shared(properties)) { @@ -74,19 +136,21 @@ Section Morphology::section(uint32_t id) const { } std::vector
Morphology::rootSections() const { + const auto sections = properties_->children(); + + if (sections.empty()) { + return {}; + } + std::vector
result; - try { - const std::vector& children = - properties_->children().at(-1); - result.reserve(children.size()); - for (auto id : children) { - result.push_back(section(id)); - } - return result; - } catch (const std::out_of_range&) { - return result; + const std::vector& children = sections.at(-1); + result.reserve(children.size()); + for (auto id : children) { + result.push_back(section(id)); } + + return result; } std::vector
Morphology::sections() const { @@ -165,67 +229,4 @@ breadth_iterator Morphology::breadth_end() const { return breadth_iterator(); } -SomaType getSomaType(long unsigned int num_soma_points) { - try { - return std::map{{0, SOMA_UNDEFINED}, - {1, SOMA_SINGLE_POINT}, - {2, SOMA_UNDEFINED}} - .at(num_soma_points); - } catch (const std::out_of_range&) { - return SOMA_SIMPLE_CONTOUR; - } -} - -void buildChildren(std::shared_ptr properties) { - { - const auto& sections = properties->get(); - auto& children = properties->_sectionLevel._children; - - for (unsigned int i = 0; i < sections.size(); ++i) { - const int32_t parent = sections[i][1]; - children[parent].push_back(i); - } - } - - { - const auto& sections = properties->get(); - auto& children = properties->_mitochondriaSectionLevel._children; - - for (unsigned int i = 0; i < sections.size(); ++i) { - const int32_t parent = sections[i][1]; - children[parent].push_back(i); - } - } -} - -Property::Properties loadURI(const std::string& source, unsigned int options) { - const size_t pos = source.find_last_of("."); - if (pos == std::string::npos) { - throw(UnknownFileType("File has no extension")); - } - - // Cross-platform check of file existance - std::ifstream file(source.c_str()); - if (!file) { - throw(RawDataError("File: " + source + " does not exist.")); - } - - std::string extension = source.substr(pos); - - auto loader = [&source, &options, &extension]() { - if (extension == ".h5" || extension == ".H5") { - return readers::h5::load(source); - } - if (extension == ".asc" || extension == ".ASC") { - return readers::asc::load(source, options); - } - if (extension == ".swc" || extension == ".SWC") { - return readers::swc::load(source, options); - } - throw(UnknownFileType("Unhandled file type: only SWC, ASC and H5 are supported")); - }; - - return loader(); -} - } // namespace morphio diff --git a/src/mut/mito_section.cpp b/src/mut/mito_section.cpp index e365a297a..e5b09deea 100644 --- a/src/mut/mito_section.cpp +++ b/src/mut/mito_section.cpp @@ -82,12 +82,7 @@ std::shared_ptr MitoSection::parent() const { } bool MitoSection::isRoot() const { - try { - parent(); - return false; - } catch (const std::out_of_range&) { - return true; - } + return mitochondria_->parent_.count(id()) == 0; } bool MitoSection::hasSameShape(const MitoSection& other) const noexcept { diff --git a/src/mut/mitochondria.cpp b/src/mut/mitochondria.cpp index cffeda97f..6ea0898ac 100644 --- a/src/mut/mitochondria.cpp +++ b/src/mut/mitochondria.cpp @@ -10,7 +10,7 @@ namespace mut { Mitochondria::MitoSectionP Mitochondria::appendRootSection(const morphio::MitoSection& section_, bool recursive) { - const auto ptr = std::make_shared(this, _counter, section_); + auto ptr = std::make_shared(this, _counter, section_); _register(ptr); root_sections_.push_back(ptr); @@ -25,7 +25,7 @@ Mitochondria::MitoSectionP Mitochondria::appendRootSection(const morphio::MitoSe Mitochondria::MitoSectionP Mitochondria::appendRootSection(const MitoSectionP& section_, bool recursive) { - const auto section_copy = std::make_shared(this, _counter, *section_); + auto section_copy = std::make_shared(this, _counter, *section_); _register(section_copy); root_sections_.push_back(section_copy); @@ -40,7 +40,7 @@ Mitochondria::MitoSectionP Mitochondria::appendRootSection(const MitoSectionP& s Mitochondria::MitoSectionP Mitochondria::appendRootSection( const Property::MitochondriaPointLevel& pointProperties) { - const auto ptr = std::make_shared(this, _counter, pointProperties); + auto ptr = std::make_shared(this, _counter, pointProperties); _register(ptr); root_sections_.push_back(ptr); @@ -70,12 +70,7 @@ const Mitochondria::MitoSectionP& Mitochondria::parent(const MitoSectionP& paren } bool Mitochondria::isRoot(const MitoSectionP& section_) const { - try { - parent(section_); - return false; - } catch (const std::out_of_range&) { - return true; - } + return parent_.count(section_->id()) == 0; } const Mitochondria::MitoSectionP& Mitochondria::section(uint32_t id) const { @@ -86,14 +81,13 @@ void Mitochondria::_buildMitochondria(Property::Properties& properties) const { int32_t counter = 0; std::map newIds; - for (std::shared_ptr mitoStart : root_sections_) { + for (const std::shared_ptr& mitoStart : root_sections_) { std::queue> q; q.push(mitoStart); while (!q.empty()) { std::shared_ptr section_ = q.front(); q.pop(); - bool root = isRoot(section_); - int32_t parentOnDisk = root ? -1 : newIds[parent(section_)->id()]; + int32_t parentOnDisk = isRoot(section_) ? -1 : newIds[parent(section_)->id()]; properties._mitochondriaSectionLevel._sections.push_back( {static_cast(properties._mitochondriaPointLevel._diameters.size()), @@ -102,7 +96,7 @@ void Mitochondria::_buildMitochondria(Property::Properties& properties) const { newIds[section_->id()] = counter++; - for (auto child : children(section_)) { + for (const auto& child : children(section_)) { q.push(child); } } @@ -138,7 +132,7 @@ mito_upstream_iterator Mitochondria::upstream_end() const { } uint32_t Mitochondria::_register(const MitoSectionP& section) { - if (sections_.count(section->id())) { + if (sections_.count(section->id()) > 0) { throw SectionBuilderError("Section already exists"); } _counter = std::max(_counter, section->id()) + 1; diff --git a/tests/test_3_h5.py b/tests/test_3_h5.py index 044c415d2..47236c4ab 100644 --- a/tests/test_3_h5.py +++ b/tests/test_3_h5.py @@ -68,7 +68,7 @@ def test_soma_no_neurite(): [ 1., 0., 0.], [ 0., 25., 0.]]) assert_array_equal(n.soma.diameters, - [6,6,15]) + [6, 6, 15]) assert len(n.root_sections) == 0 diff --git a/tests/test_morphology_readers.cpp b/tests/test_morphology_readers.cpp index b5408ca11..8d81906dc 100644 --- a/tests/test_morphology_readers.cpp +++ b/tests/test_morphology_readers.cpp @@ -111,8 +111,8 @@ TEST_CASE("LoadH5Glia", "[morphology]") { { const morphio::Morphology m("data/h5/v1/glia_soma_only.h5"); REQUIRE(m.soma().points().size() == 1); - REQUIRE(m.points().size() == 0); - REQUIRE(m.perimeters().size() == 0); + REQUIRE(m.points().empty()); + REQUIRE(m.perimeters().empty()); } { // empty perimeters From 8634bc43eaf234cf6c1481e7776e8403bb9895db Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Fri, 4 Mar 2022 14:47:20 +0100 Subject: [PATCH 2/5] fix catch in section_base.h --- include/morphio/section_base.h | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/include/morphio/section_base.h b/include/morphio/section_base.h index 209f0382f..dccca2e49 100644 --- a/include/morphio/section_base.h +++ b/include/morphio/section_base.h @@ -124,19 +124,25 @@ T SectionBase::parent() const { template std::vector SectionBase::children() const { + const auto section_children = properties_->children(); + + if (section_children.empty()) { + return {}; + } + + const auto it = section_children.find(static_cast(id_)); + if (it == section_children.end()) { + return {}; + } + std::vector result; - try { - const std::vector& _children = properties_->children().at( - static_cast(id_)); - result.reserve(_children.size()); - for (uint32_t id : _children) { - result.push_back(T(id, properties_)); - } - - return result; - } catch (const std::out_of_range&) { - return result; + const std::vector children = it->second; + result.reserve(children.size()); + for (uint32_t id : children) { + result.push_back(T(id, properties_)); } + + return result; } From f0785ab3c5f74a5f91a3e7ed49c014c05058cdd4 Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Fri, 4 Mar 2022 14:49:36 +0100 Subject: [PATCH 3/5] fix catch in errorMessages.h --- include/morphio/errorMessages.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/morphio/errorMessages.h b/include/morphio/errorMessages.h index 71fd46556..696c09dcf 100644 --- a/include/morphio/errorMessages.h +++ b/include/morphio/errorMessages.h @@ -48,11 +48,11 @@ struct DebugInfo { /** Get section's line number within morphology file */ int32_t getLineNumber(uint32_t sectionId) const { - try { - return _lineNumbers.at(sectionId); - } catch (const std::out_of_range&) { + const auto it = _lineNumbers.find(sectionId); + if (it == _lineNumbers.end()) { return -1; } + return it->second; } /** Morphology filename */ std::string _filename; From c65fdffd86db79252c14282cb1130f34b1351d05 Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Wed, 16 Mar 2022 08:23:47 +0100 Subject: [PATCH 4/5] code review feedback, some cleanup --- include/morphio/morphology.h | 4 ++-- include/morphio/section_base.h | 2 +- src/morphology.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/morphio/morphology.h b/include/morphio/morphology.h index 792c27796..b1b2e9fbe 100644 --- a/include/morphio/morphology.h +++ b/include/morphio/morphology.h @@ -43,7 +43,7 @@ class Morphology /** Constructor from an already parsed file */ explicit Morphology(const HighFive::Group& group, unsigned int options = NO_MODIFIER); /** Constructor from an instance of morphio::mut::Morphology */ - explicit Morphology(mut::Morphology); + explicit Morphology(const mut::Morphology&); /** Return the soma object */ Soma soma() const; @@ -52,7 +52,7 @@ class Morphology Mitochondria mitochondria() const; /** Return the endoplasmic reticulum object */ - const EndoplasmicReticulum endoplasmicReticulum() const; + EndoplasmicReticulum endoplasmicReticulum() const; /** Return the annotation object */ const std::vector& annotations() const; diff --git a/include/morphio/section_base.h b/include/morphio/section_base.h index dccca2e49..465cc7583 100644 --- a/include/morphio/section_base.h +++ b/include/morphio/section_base.h @@ -124,7 +124,7 @@ T SectionBase::parent() const { template std::vector SectionBase::children() const { - const auto section_children = properties_->children(); + const auto& section_children = properties_->children(); if (section_children.empty()) { return {}; diff --git a/src/morphology.cpp b/src/morphology.cpp index f9f24c385..df2f02855 100644 --- a/src/morphology.cpp +++ b/src/morphology.cpp @@ -106,7 +106,7 @@ Morphology::Morphology(const HighFive::Group& group, unsigned int options) Morphology::Morphology(const std::string& source, unsigned int options) : Morphology(loadURI(source, options), options) {} -Morphology::Morphology(mut::Morphology morphology) { +Morphology::Morphology(const mut::Morphology& morphology) { properties_ = std::make_shared(morphology.buildReadOnly()); buildChildren(properties_); } @@ -119,7 +119,7 @@ Mitochondria Morphology::mitochondria() const { return Mitochondria(properties_); } -const EndoplasmicReticulum Morphology::endoplasmicReticulum() const { +EndoplasmicReticulum Morphology::endoplasmicReticulum() const { return EndoplasmicReticulum(properties_); } @@ -136,7 +136,7 @@ Section Morphology::section(uint32_t id) const { } std::vector
Morphology::rootSections() const { - const auto sections = properties_->children(); + const auto& sections = properties_->children(); if (sections.empty()) { return {}; From 34bff1a423cb15d855ed707ab341ac6d0533e46f Mon Sep 17 00:00:00 2001 From: Mike Gevaert Date: Wed, 16 Mar 2022 17:47:36 +0100 Subject: [PATCH 5/5] write more tests so we increase the test coverage --- src/morphology.cpp | 3 +- tests/CMakeLists.txt | 3 +- tests/test_helpers.h | 28 +++++++ tests/test_immutable_morphology.cpp | 99 +--------------------- tests/test_mitochondria.cpp | 122 ++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+), 100 deletions(-) create mode 100644 tests/test_helpers.h create mode 100644 tests/test_mitochondria.cpp diff --git a/src/morphology.cpp b/src/morphology.cpp index 33d5d7919..e8b6a2af4 100644 --- a/src/morphology.cpp +++ b/src/morphology.cpp @@ -45,7 +45,8 @@ morphio::SomaType getSomaType(long unsigned int num_soma_points) { return morphio::SOMA_SINGLE_POINT; case 2: return morphio::SOMA_UNDEFINED; - default:; + default: + break; } return morphio::SOMA_SIMPLE_CONTOUR; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 480ff44f4..a4245073e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,8 @@ set(TESTS_SRC main.cpp - test_morphology_readers.cpp test_immutable_morphology.cpp + test_mitochondria.cpp + test_morphology_readers.cpp test_mutable_morphology.cpp test_vasculature_morphology.cpp ) diff --git a/tests/test_helpers.h b/tests/test_helpers.h new file mode 100644 index 000000000..0f66ce657 --- /dev/null +++ b/tests/test_helpers.h @@ -0,0 +1,28 @@ +#include + +static bool almost_equal(morphio::floatType a, double expected, double epsilon) { +#ifdef MORPHIO_USE_DOUBLE + bool res = std::abs(a - expected) < epsilon; +#else + bool res = std::abs(static_cast(a) - expected) < epsilon; +#endif + if (!res) { + std::cerr << "Failed almost equal: " << a << " != " << expected + << " (expected) with epsilon of " << epsilon << '\n'; + } + return res; +} + +static bool array_almost_equal(const std::vector& a, + const std::vector& expected, + double epsilon) { + if (a.size() != expected.size()) { + return false; + } + for (size_t i = 0; i < a.size(); i++) { + if (!almost_equal(a.at(i), expected.at(i), epsilon)) { + return false; + } + } + return true; +} diff --git a/tests/test_immutable_morphology.cpp b/tests/test_immutable_morphology.cpp index 9ea9d34f7..f0a260a95 100644 --- a/tests/test_immutable_morphology.cpp +++ b/tests/test_immutable_morphology.cpp @@ -6,44 +6,15 @@ #include #include -#include -#include #include #include #include #include #include +#include "test_helpers.h" namespace { -bool almost_equal(morphio::floatType a, double expected, double epsilon) { -#ifdef MORPHIO_USE_DOUBLE - bool res = std::abs(a - expected) < epsilon; -#else - bool res = std::abs(static_cast(a) - expected) < epsilon; -#endif - if (!res) { - std::cerr << "Failed almost equal: " << a << " != " << expected - << " (expected) with epsilon of " << epsilon << '\n'; - } - return res; -} - -bool array_almost_equal(const std::vector& a, - const std::vector& expected, - double epsilon) { - if (a.size() != expected.size()) { - return false; - } - for (size_t i = 0; i < a.size(); i++) { - if (!almost_equal(a.at(i), expected.at(i), epsilon)) { - return false; - } - } - return true; -} - - class Files { public: @@ -252,74 +223,6 @@ TEST_CASE("connectivity", "[immutableMorphology]") { } } -TEST_CASE("mitochondria", "[immutableMorphology]") { - morphio::Morphology morph = morphio::Morphology("data/h5/v1/mitochondria.h5"); - morphio::Mitochondria mito = morph.mitochondria(); - REQUIRE(mito.rootSections().size() == 2); - morphio::MitoSection rootSection = mito.rootSections().at(0); - REQUIRE(rootSection.id() == 0); - auto diameters = rootSection.diameters(); - REQUIRE(array_almost_equal(std::vector(diameters.begin(), diameters.end()), - std::vector{10.0, 20.0}, - 0.01)); - auto relativePathLength = rootSection.relativePathLengths(); - auto res = std::vector(relativePathLength.begin(), - relativePathLength.end()); - - REQUIRE(almost_equal(res.at(0), 0.5, 0.001)); - REQUIRE(almost_equal(res.at(1), 0.6000000238, 0.001)); - - auto neuriteSectionIds = rootSection.neuriteSectionIds(); - REQUIRE(array_almost_equal(std::vector(neuriteSectionIds.begin(), - neuriteSectionIds.end()), - std::vector{0.0, 0.0}, - 0.01)); - REQUIRE(rootSection.children().size() == 1); - - auto child = rootSection.children().at(0); - REQUIRE(child.parent().id() == rootSection.id()); - - diameters = child.diameters(); - REQUIRE(array_almost_equal(std::vector(diameters.begin(), diameters.end()), - std::vector{20.0, 30.0, 40.0, 50.0}, - 0.01)); - relativePathLength = child.relativePathLengths(); - - REQUIRE(array_almost_equal(std::vector(relativePathLength.begin(), - relativePathLength.end()), - std::vector{0.6, 0.7, 0.8, 0.9}, - 0.01)); - - neuriteSectionIds = child.neuriteSectionIds(); - REQUIRE(array_almost_equal(std::vector(neuriteSectionIds.begin(), - neuriteSectionIds.end()), - std::vector{3.0, 4.0, 4.0, 5.0}, - 0.01)); - rootSection = mito.rootSections().at(1); - diameters = rootSection.diameters(); - REQUIRE(array_almost_equal(std::vector(diameters.begin(), diameters.end()), - std::vector{5.0, 6.0, 7.0, 8.0}, - 0.01)); - relativePathLength = rootSection.relativePathLengths(); - - REQUIRE(array_almost_equal(std::vector(relativePathLength.begin(), - relativePathLength.end()), - std::vector{0.6, 0.7, 0.8, 0.9}, - 0.01)); - - neuriteSectionIds = rootSection.neuriteSectionIds(); - REQUIRE(array_almost_equal(std::vector(neuriteSectionIds.begin(), - neuriteSectionIds.end()), - std::vector{0.0, 1.0, 1.0, 2.0}, - 0.01)); - REQUIRE(rootSection.children().empty()); - - { - morphio::Morphology morph0 = morphio::Morphology("data/h5/v1/mitochondria.h5"); - morphio::Morphology morph1 = morphio::Morphology("data/h5/v1/mitochondria.h5"); - REQUIRE(morph0.rootSections().at(0).hasSameShape(morph1.rootSections().at(0))); - } -} TEST_CASE("endoplasmic_reticulum", "[immutableMorphology]") { diff --git a/tests/test_mitochondria.cpp b/tests/test_mitochondria.cpp new file mode 100644 index 000000000..82ad03dd5 --- /dev/null +++ b/tests/test_mitochondria.cpp @@ -0,0 +1,122 @@ +#include + +#include +#include +#include + +#include +#include +#include + +#include "test_helpers.h" + + +TEST_CASE("mitochondria", "[mitochondria]") { + const auto mito = morphio::Morphology("data/h5/v1/mitochondria.h5").mitochondria(); + + REQUIRE(mito.rootSections().size() == 2); + + auto rootSection = mito.rootSections().at(0); + REQUIRE(rootSection.id() == 0); + + auto diameters = rootSection.diameters(); + REQUIRE(array_almost_equal(std::vector(diameters.begin(), diameters.end()), + std::vector{10.0, 20.0}, + 0.01)); + auto relativePathLength = rootSection.relativePathLengths(); + auto res = std::vector(relativePathLength.begin(), + relativePathLength.end()); + + REQUIRE(almost_equal(res.at(0), 0.5, 0.001)); + REQUIRE(almost_equal(res.at(1), 0.6000000238, 0.001)); + + auto neuriteSectionIds = rootSection.neuriteSectionIds(); + REQUIRE(array_almost_equal(std::vector(neuriteSectionIds.begin(), + neuriteSectionIds.end()), + std::vector{0.0, 0.0}, + 0.01)); + REQUIRE(rootSection.children().size() == 1); + + auto child = rootSection.children().at(0); + REQUIRE(child.parent().id() == rootSection.id()); + + diameters = child.diameters(); + REQUIRE(array_almost_equal(std::vector(diameters.begin(), diameters.end()), + std::vector{20.0, 30.0, 40.0, 50.0}, + 0.01)); + relativePathLength = child.relativePathLengths(); + + REQUIRE(array_almost_equal(std::vector(relativePathLength.begin(), + relativePathLength.end()), + std::vector{0.6, 0.7, 0.8, 0.9}, + 0.01)); + + neuriteSectionIds = child.neuriteSectionIds(); + REQUIRE(array_almost_equal(std::vector(neuriteSectionIds.begin(), + neuriteSectionIds.end()), + std::vector{3.0, 4.0, 4.0, 5.0}, + 0.01)); + rootSection = mito.rootSections().at(1); + diameters = rootSection.diameters(); + REQUIRE(array_almost_equal(std::vector(diameters.begin(), diameters.end()), + std::vector{5.0, 6.0, 7.0, 8.0}, + 0.01)); + relativePathLength = rootSection.relativePathLengths(); + + REQUIRE(array_almost_equal(std::vector(relativePathLength.begin(), + relativePathLength.end()), + std::vector{0.6, 0.7, 0.8, 0.9}, + 0.01)); + + neuriteSectionIds = rootSection.neuriteSectionIds(); + REQUIRE(array_almost_equal(std::vector(neuriteSectionIds.begin(), + neuriteSectionIds.end()), + std::vector{0.0, 1.0, 1.0, 2.0}, + 0.01)); + REQUIRE(rootSection.children().empty()); +} + +TEST_CASE("mitochondria.sections", "[mitochondria]") { + const auto mito = morphio::Morphology("data/h5/v1/mitochondria.h5").mitochondria(); + auto sections = mito.sections(); + + std::vector res; + std::transform(sections.begin(), + sections.end(), + std::back_inserter(res), + [](const morphio::MitoSection& s) { return s.id(); }); + REQUIRE(res == std::vector{0, 1, 2}); +} + +TEST_CASE("mitochondria.iteration", "[mitochondria]") { + const auto mito = morphio::Morphology("data/h5/v1/mitochondria.h5").mitochondria(); + + const auto rootSection = mito.rootSections().at(0); + + std::vector res; + std::transform(rootSection.depth_begin(), + rootSection.depth_end(), + std::back_inserter(res), + [](const morphio::MitoSection& s) { return s.id(); }); + REQUIRE(res == std::vector{0, 1}); + + res.clear(); + std::transform(rootSection.breadth_begin(), + rootSection.breadth_end(), + std::back_inserter(res), + [](const morphio::MitoSection& s) { return s.id(); }); + REQUIRE(res == std::vector{0, 1}); + + res.clear(); + std::transform(rootSection.upstream_begin(), + rootSection.upstream_end(), + std::back_inserter(res), + [](const morphio::MitoSection& s) { return s.id(); }); + REQUIRE(res == std::vector{0}); +} + +TEST_CASE("mitochondria.hasSameShape", "[mitochondria]") { + morphio::Morphology morph0 = morphio::Morphology("data/h5/v1/mitochondria.h5"); + morphio::Morphology morph1 = morphio::Morphology("data/h5/v1/mitochondria.h5"); + REQUIRE(morph0.rootSections().at(0).hasSameShape(morph1.rootSections().at(0))); +}