|
10 | 10 | #include <morphio/mut/mitochondria.h> |
11 | 11 | #include <morphio/mut/morphology.h> |
12 | 12 | #include <morphio/morphology.h> |
| 13 | +#include <morphio/glial_cell.h> |
13 | 14 |
|
14 | 15 | #include <array> |
15 | 16 |
|
@@ -42,6 +43,7 @@ void bind_mutable_module(py::module& m) { |
42 | 43 | "Additional Ctor that accepts as filename any python " |
43 | 44 | "object that implements __repr__ or __str__") |
44 | 45 |
|
| 46 | + |
45 | 47 | // Cell sub-part accessors |
46 | 48 | .def_property_readonly("sections", |
47 | 49 | &morphio::mut::Morphology::sections, |
@@ -122,10 +124,6 @@ void bind_mutable_module(py::module& m) { |
122 | 124 | "Return the graph connectivity of the morphology " |
123 | 125 | "where each section is seen as a node\nNote: -1 is the soma node") |
124 | 126 |
|
125 | | - // .def_property_readonly("cell_family", |
126 | | - // &morphio::mut::Morphology::cellFamily, |
127 | | - // "Returns the cell family (neuron or glia)") |
128 | | - |
129 | 127 | .def_property_readonly("soma_type", |
130 | 128 | &morphio::mut::Morphology::somaType, |
131 | 129 | "Returns the soma type") |
@@ -178,6 +176,161 @@ void bind_mutable_module(py::module& m) { |
178 | 176 | "If recursive == true, all descendent will be appended as well", |
179 | 177 | "mutable_section"_a, |
180 | 178 | "recursive"_a = false); |
| 179 | + |
| 180 | + py::class_<morphio::mut::GlialCell>(m, "GlialCell") |
| 181 | + .def(py::init<>()) |
| 182 | + .def(py::init<const std::string&, unsigned int>(), |
| 183 | + "filename"_a, |
| 184 | + "options"_a = morphio::enums::Option::NO_MODIFIER) |
| 185 | + .def(py::init<const morphio::GlialCell&, unsigned int>(), |
| 186 | + "morphology"_a, |
| 187 | + "options"_a = morphio::enums::Option::NO_MODIFIER) |
| 188 | + .def(py::init<const morphio::mut::GlialCell&, unsigned int>(), |
| 189 | + "morphology"_a, |
| 190 | + "options"_a = morphio::enums::Option::NO_MODIFIER) |
| 191 | + .def(py::init([](py::object arg, unsigned int options) { |
| 192 | + return std::unique_ptr<morphio::mut::GlialCell>( |
| 193 | + new morphio::mut::GlialCell(py::str(arg), options)); |
| 194 | + }), |
| 195 | + "filename"_a, |
| 196 | + "options"_a = morphio::enums::Option::NO_MODIFIER, |
| 197 | + "Additional Ctor that accepts as filename any python " |
| 198 | + "object that implements __repr__ or __str__") |
| 199 | + |
| 200 | + |
| 201 | + // Cell sub-part accessors |
| 202 | + .def_property_readonly("sections", |
| 203 | + &morphio::mut::GlialCell::sections, |
| 204 | + "Returns a list containing IDs of all sections. " |
| 205 | + "The first section of the vector is the soma section") |
| 206 | + .def_property_readonly("root_sections", |
| 207 | + &morphio::mut::GlialCell::rootSections, |
| 208 | + "Returns a list of all root sections IDs " |
| 209 | + "(sections whose parent ID are -1)", |
| 210 | + py::return_value_policy::reference) |
| 211 | + .def_property_readonly( |
| 212 | + "soma", |
| 213 | + static_cast<std::shared_ptr<morphio::mut::Soma>& (morphio::mut::GlialCell::*) ()>( |
| 214 | + &morphio::mut::GlialCell::soma), |
| 215 | + "Returns a reference to the soma object\n\n" |
| 216 | + "Note: multiple morphologies can share the same Soma " |
| 217 | + "instance") |
| 218 | + .def_property_readonly( |
| 219 | + "mitochondria", |
| 220 | + static_cast<morphio::mut::Mitochondria& (morphio::mut::GlialCell::*) ()>( |
| 221 | + &morphio::mut::GlialCell::mitochondria), |
| 222 | + "Returns a reference to the mitochondria container class") |
| 223 | + .def_property_readonly( |
| 224 | + "endoplasmic_reticulum", |
| 225 | + static_cast<morphio::mut::EndoplasmicReticulum& (morphio::mut::GlialCell::*) ()>( |
| 226 | + &morphio::mut::GlialCell::endoplasmicReticulum), |
| 227 | + "Returns a reference to the endoplasmic reticulum container class") |
| 228 | + .def_property_readonly("annotations", |
| 229 | + &morphio::mut::GlialCell::annotations, |
| 230 | + "Returns a list of annotations") |
| 231 | + .def_property_readonly("markers", |
| 232 | + &morphio::mut::GlialCell::markers, |
| 233 | + "Returns the list of NeuroLucida markers") |
| 234 | + .def("section", |
| 235 | + &morphio::mut::GlialCell::section, |
| 236 | + "Returns the section with the given id\n\n" |
| 237 | + "Note: multiple morphologies can share the same Section " |
| 238 | + "instances", |
| 239 | + "section_id"_a) |
| 240 | + .def("build_read_only", |
| 241 | + &morphio::mut::GlialCell::buildReadOnly, |
| 242 | + "Returns the data structure used to create read-only " |
| 243 | + "morphologies") |
| 244 | + .def("append_root_section", |
| 245 | + static_cast<std::shared_ptr<morphio::mut::GlialSection> (morphio::mut::GlialCell::*)( |
| 246 | + const morphio::Property::PointLevel&, morphio::GlialSectionType)>( |
| 247 | + &morphio::mut::GlialCell::appendRootSection), |
| 248 | + "Append a root Section\n", |
| 249 | + "point_level_properties"_a, |
| 250 | + "section_type"_a) |
| 251 | + .def("append_root_section", |
| 252 | + static_cast<std::shared_ptr<morphio::mut::GlialSection> (morphio::mut::GlialCell::*)( |
| 253 | + const morphio::GlialSection&, bool)>(&morphio::mut::GlialCell::appendRootSection), |
| 254 | + "Append the existing immutable Section as a root section\n" |
| 255 | + "If recursive == true, all descendent will be appended as " |
| 256 | + "well", |
| 257 | + "immutable_section"_a, |
| 258 | + "recursive"_a = false) |
| 259 | + |
| 260 | + .def("delete_section", |
| 261 | + &morphio::mut::GlialCell::deleteSection, |
| 262 | + "Delete the given section\n" |
| 263 | + "\n" |
| 264 | + "Will silently fail if the section is not part of the " |
| 265 | + "tree\n" |
| 266 | + "\n" |
| 267 | + "If recursive == true, all descendent sections will be " |
| 268 | + "deleted as well\n" |
| 269 | + "Else, children will be re-attached to their grand-parent", |
| 270 | + "section"_a, |
| 271 | + "recursive"_a = true) |
| 272 | + |
| 273 | + .def("as_immutable", |
| 274 | + [](const morphio::mut::GlialCell* morph) { return morphio::GlialCell(*morph); }) |
| 275 | + |
| 276 | + .def_property_readonly("connectivity", |
| 277 | + &morphio::mut::GlialCell::connectivity, |
| 278 | + "Return the graph connectivity of the morphology " |
| 279 | + "where each section is seen as a node\nNote: -1 is the soma node") |
| 280 | + |
| 281 | + .def_property_readonly("soma_type", |
| 282 | + &morphio::mut::GlialCell::somaType, |
| 283 | + "Returns the soma type") |
| 284 | + |
| 285 | + .def_property_readonly("version", &morphio::mut::GlialCell::version, "Returns the version") |
| 286 | + |
| 287 | + .def("sanitize", |
| 288 | + static_cast<void (morphio::mut::GlialCell::*) ()>( |
| 289 | + &morphio::mut::GlialCell::sanitize), |
| 290 | + "Fixes the morphology single child sections and issues warnings" |
| 291 | + "if the section starts and ends are inconsistent") |
| 292 | + |
| 293 | + .def( |
| 294 | + "write", |
| 295 | + [](morphio::mut::GlialCell* morph, py::object arg) { morph->write(py::str(arg)); }, |
| 296 | + "Write file to H5, SWC, ASC format depending on filename " |
| 297 | + "extension", |
| 298 | + "filename"_a) |
| 299 | + |
| 300 | + // Iterators |
| 301 | + .def( |
| 302 | + "iter", |
| 303 | + [](morphio::mut::GlialCell* morph, IterType type) { |
| 304 | + switch (type) { |
| 305 | + case IterType::DEPTH_FIRST: |
| 306 | + return py::make_iterator(morph->depth_begin(), morph->depth_end()); |
| 307 | + case IterType::BREADTH_FIRST: |
| 308 | + return py::make_iterator(morph->breadth_begin(), morph->breadth_end()); |
| 309 | + case IterType::UPSTREAM: |
| 310 | + default: |
| 311 | + throw morphio::MorphioError("Only iteration types depth_first and " |
| 312 | + "breadth_first are supported"); |
| 313 | + } |
| 314 | + }, |
| 315 | + py::keep_alive<0, 1>() /* Essential: keep object alive |
| 316 | + while iterator exists */ |
| 317 | + , |
| 318 | + "Section iterator that runs successively on every " |
| 319 | + "neurite\n" |
| 320 | + "iter_type controls the order of iteration on sections of " |
| 321 | + "a given neurite. 2 values can be passed:\n" |
| 322 | + "- morphio.IterType.depth_first (default)\n" |
| 323 | + "- morphio.IterType.breadth_first", |
| 324 | + "iter_type"_a = IterType::DEPTH_FIRST) |
| 325 | + .def("append_root_section", |
| 326 | + static_cast<std::shared_ptr<morphio::mut::GlialSection> ( |
| 327 | + morphio::mut::GlialCell::*)(const std::shared_ptr<morphio::mut::GlialSection>&, bool)>( |
| 328 | + &morphio::mut::GlialCell::appendRootSection), |
| 329 | + "Append the existing mutable Section as a root section\n" |
| 330 | + "If recursive == true, all descendent will be appended as well", |
| 331 | + "mutable_section"_a, |
| 332 | + "recursive"_a = false); |
| 333 | + |
181 | 334 |
|
182 | 335 | py::class_<morphio::mut::Mitochondria>(m, "Mitochondria") |
183 | 336 | .def(py::init<>()) |
@@ -476,6 +629,118 @@ void bind_mutable_module(py::module& m) { |
476 | 629 | "center", |
477 | 630 | [](morphio::mut::Soma* soma) { return py::array(3, soma->center().data()); }, |
478 | 631 | "Returns the center of gravity of the soma points"); |
| 632 | + |
| 633 | + py::class_<morphio::mut::GlialSection, std::shared_ptr<morphio::mut::GlialSection>>(m, "GlialSection") |
| 634 | + .def("__str__", |
| 635 | + [](const morphio::mut::GlialSection& section) { |
| 636 | + std::stringstream ss; |
| 637 | + ss << section; |
| 638 | + return ss.str(); |
| 639 | + }) |
| 640 | + |
| 641 | + .def_property_readonly("id", &morphio::mut::GlialSection::id, "Return the section ID") |
| 642 | + .def_property( |
| 643 | + "type", |
| 644 | + static_cast<const morphio::GlialSectionType& (morphio::mut::GlialSection::*) () const>( |
| 645 | + &morphio::mut::GlialSection::type), |
| 646 | + [](morphio::mut::GlialSection* section, morphio::GlialSectionType _type) { |
| 647 | + section->type() = _type; |
| 648 | + }, |
| 649 | + "Returns the morphological type of this section " |
| 650 | + "(dendrite, axon, ...)") |
| 651 | + .def_property( |
| 652 | + "points", |
| 653 | + [](morphio::mut::GlialSection* section) { |
| 654 | + return py::array(static_cast<py::ssize_t>(section->points().size()), |
| 655 | + section->points().data()); |
| 656 | + }, |
| 657 | + [](morphio::mut::GlialSection* section, py::array_t<morphio::floatType> _points) { |
| 658 | + section->points() = array_to_points(_points); |
| 659 | + }, |
| 660 | + "Returns the coordinates (x,y,z) of all points of this section") |
| 661 | + .def_property( |
| 662 | + "diameters", |
| 663 | + [](morphio::mut::GlialSection* section) { |
| 664 | + return py::array(static_cast<py::ssize_t>(section->diameters().size()), |
| 665 | + section->diameters().data()); |
| 666 | + }, |
| 667 | + [](morphio::mut::GlialSection* section, py::array_t<morphio::floatType> _diameters) { |
| 668 | + section->diameters() = _diameters.cast<std::vector<morphio::floatType>>(); |
| 669 | + }, |
| 670 | + "Returns the diameters of all points of this section") |
| 671 | + .def_property( |
| 672 | + "perimeters", |
| 673 | + [](morphio::mut::GlialSection* section) { |
| 674 | + return py::array(static_cast<py::ssize_t>(section->perimeters().size()), |
| 675 | + section->perimeters().data()); |
| 676 | + }, |
| 677 | + [](morphio::mut::GlialSection* section, py::array_t<morphio::floatType> _perimeters) { |
| 678 | + section->perimeters() = _perimeters.cast<std::vector<morphio::floatType>>(); |
| 679 | + }, |
| 680 | + "Returns the perimeters of all points of this section") |
| 681 | + .def_property_readonly("is_root", |
| 682 | + &morphio::mut::GlialSection::isRoot, |
| 683 | + "Return True if section is a root section") |
| 684 | + .def_property_readonly("parent", |
| 685 | + &morphio::mut::GlialSection::parent, |
| 686 | + "Get the parent ID\n\n" |
| 687 | + "Note: Root sections return -1") |
| 688 | + .def_property_readonly("children", |
| 689 | + &morphio::mut::GlialSection::children, |
| 690 | + "Returns a list of children IDs") |
| 691 | + // Iterators |
| 692 | + .def( |
| 693 | + "iter", |
| 694 | + [](morphio::mut::GlialSection* section, IterType type) { |
| 695 | + switch (type) { |
| 696 | + case IterType::DEPTH_FIRST: |
| 697 | + return py::make_iterator(section->depth_begin(), section->depth_end()); |
| 698 | + case IterType::BREADTH_FIRST: |
| 699 | + return py::make_iterator(section->breadth_begin(), section->breadth_end()); |
| 700 | + case IterType::UPSTREAM: |
| 701 | + return py::make_iterator(section->upstream_begin(), section->upstream_end()); |
| 702 | + default: |
| 703 | + throw morphio::MorphioError("Only iteration types depth_first, breadth_first and " |
| 704 | + "upstream are supported"); |
| 705 | + } |
| 706 | + }, |
| 707 | + py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */, |
| 708 | + "GlialSection iterator\n" |
| 709 | + "\n" |
| 710 | + "iter_type controls the iteration order. 3 values can be passed:\n" |
| 711 | + "- morphio.IterType.depth_first (default)\n" |
| 712 | + "- morphio.IterType.breadth_first\n" |
| 713 | + "- morphio.IterType.upstream\n", |
| 714 | + "iter_type"_a = IterType::DEPTH_FIRST) |
| 715 | + |
| 716 | + // Editing |
| 717 | + .def("append_section", |
| 718 | + static_cast<std::shared_ptr<morphio::mut::GlialSection> (morphio::mut::GlialSection::*)( |
| 719 | + const morphio::GlialSection&, bool)>(&morphio::mut::GlialSection::appendSection), |
| 720 | + "Append the existing immutable GlialSection to this section" |
| 721 | + "If recursive == true, all descendent will be appended as well", |
| 722 | + "immutable_section"_a, |
| 723 | + "recursive"_a = false) |
| 724 | + |
| 725 | + .def("append_section", |
| 726 | + static_cast<std::shared_ptr<morphio::mut::GlialSection> ( |
| 727 | + morphio::mut::GlialSection::*)(const std::shared_ptr<morphio::mut::GlialSection>&, bool)>( |
| 728 | + &morphio::mut::GlialSection::appendSection), |
| 729 | + "Append the existing mutable GlialSection to this section\n" |
| 730 | + "If recursive == true, all descendent will be appended as well", |
| 731 | + "mutable_section"_a, |
| 732 | + "recursive"_a = false) |
| 733 | + |
| 734 | + .def("append_section", |
| 735 | + static_cast<std::shared_ptr<morphio::mut::GlialSection> (morphio::mut::GlialSection::*)( |
| 736 | + const morphio::Property::PointLevel&, morphio::GlialSectionType)>( |
| 737 | + &morphio::mut::GlialSection::appendSection), |
| 738 | + "Append a new GlialSection to this section\n" |
| 739 | + " If section_type is omitted or set to 'undefined'" |
| 740 | + " the type of the parent section will be used", |
| 741 | + "point_level_properties"_a, |
| 742 | + "section_type"_a = morphio::GlialSectionType::UNDEFINED); |
| 743 | + |
479 | 744 |
|
480 | 745 | py::class_<morphio::mut::EndoplasmicReticulum>(m, "EndoplasmicReticulum") |
481 | 746 | .def(py::init<>()) |
|
0 commit comments