diff --git a/.github/workflows/clang_format_check.yaml b/.github/workflows/clang_format_check.yaml index f7634119b..f39789c0e 100644 --- a/.github/workflows/clang_format_check.yaml +++ b/.github/workflows/clang_format_check.yaml @@ -9,6 +9,8 @@ jobs: steps: - name: Fetch repository uses: actions/checkout@v1 + - name: Install apt + run: sudo apt-get update -y - name: Install packages run: sudo apt-get install python3-venv - name: check_clang_format diff --git a/binds/python/bind_mutable.cpp b/binds/python/bind_mutable.cpp index 5257c65a0..0e0e82937 100644 --- a/binds/python/bind_mutable.cpp +++ b/binds/python/bind_mutable.cpp @@ -127,6 +127,12 @@ void bind_mutable_module(py::module& m) { .def_property_readonly("version", &morphio::mut::Morphology::version, "Returns the version") + .def("sanitize", + static_cast( + &morphio::mut::Morphology::sanitize), + "Fixes the morphology single child sections and issues warnings" + "if the section starts and ends are inconsistent") + .def( "write", [](morphio::mut::Morphology* morph, py::object arg) { morph->write(py::str(arg)); }, @@ -316,6 +322,7 @@ void bind_mutable_module(py::module& m) { "immutable_section"_a, "recursive"_a = false); + py::class_>(m, "Section") .def("__str__", [](const morphio::mut::Section& section) { diff --git a/include/morphio/mut/morphology.h b/include/morphio/mut/morphology.h index 03feec711..cc767fae9 100644 --- a/include/morphio/mut/morphology.h +++ b/include/morphio/mut/morphology.h @@ -201,7 +201,8 @@ class Morphology /** - Check that the neuron is valid, issue warning and fix unifurcations + Fixes the morphology single child sections and issues warnings + if the section starts and ends are inconsistent **/ void sanitize(); void sanitize(const morphio::readers::DebugInfo& debugInfo); diff --git a/tests/test_0_API.py b/tests/test_0_API.py index 42baedbbb..d5eb45b22 100644 --- a/tests/test_0_API.py +++ b/tests/test_0_API.py @@ -32,7 +32,7 @@ def methods(cls): only_in_immut = {'section_types', 'diameters', 'perimeters', 'points', 'section_offsets', 'as_mutable'} - only_in_mut = {'write', 'append_root_section', 'delete_section', 'build_read_only', + only_in_mut = {'sanitize', 'write', 'append_root_section', 'delete_section', 'build_read_only', 'as_immutable'} assert_equal(methods(morphio.Morphology) - only_in_immut, methods(morphio.mut.Morphology) - only_in_mut) diff --git a/tests/test_5_mut.py b/tests/test_5_mut.py index 78c4dbb88..7914db743 100644 --- a/tests/test_5_mut.py +++ b/tests/test_5_mut.py @@ -429,3 +429,36 @@ def test_endoplasmic_reticulum(): assert_equal(reticulum.volumes, [2, 2]) assert_equal(reticulum.surface_areas, [3, 3]) assert_equal(reticulum.filament_counts, [4, 4]) + + +def test_sanitize(): + m = Morphology() + section = m.append_root_section(PointLevel([[1, 0, 0], + [2, 0, 0]], [2, 2], [20, 20]), + SectionType.axon) + section.append_section(PointLevel([[2, 0, 0], + [3, 0, 0]], [2, 2], [20, 20])) + with captured_output() as (_, err): + with ostream_redirect(stdout=True, stderr=True): + m.sanitize() + assert_equal(len(list(m.iter())), 1) + assert_equal(err.getvalue().strip(), + 'Warning: section 1 is the only child of section: 0\nIt will be merged ' + 'with the parent section') + + # Checking that sanitize() issues a warning on missing duplicate + m = Morphology() + section = m.append_root_section(PointLevel([[1, 0, 0], + [2, 0, 0]], [2, 2], [20, 20]), + SectionType.axon) + section.append_section(PointLevel([[2, 0, 0], + [3, 0, 0]], [2, 2], [20, 20])) + with captured_output() as (_, err): + with ostream_redirect(): + section.append_section(PointLevel([[2, 1, 0], + [2, 0, 0]], [2, 2], [20, 20])) + with captured_output() as (_, err): + with ostream_redirect(): + m.sanitize() + assert_equal(err.getvalue().strip(), + 'Warning: while appending section: 2 to parent: 0\nThe section first point should be parent section last point: \n : X Y Z Diameter\nparent last point :[2.000000, 0.000000, 0.000000, 2.000000]\nchild first point :[2.000000, 1.000000, 0.000000, 2.000000]')