Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit f300d9f

Browse files
committed
WIP Template Morphology in order to Create GlialCell with their own Section Type: GlialSectionType
1 parent 8e61eaf commit f300d9f

File tree

16 files changed

+333
-95
lines changed

16 files changed

+333
-95
lines changed

binds/python/bind_immutable.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,6 @@ void bind_immutable_module(py::module& m) {
124124
"Return the graph connectivity of the morphology "
125125
"where each section is seen as a node\nNote: -1 is the soma node")
126126
.def_property_readonly("soma_type", &morphio::Morphology::somaType, "Returns the soma type")
127-
// .def_property_readonly("cell_family",
128-
// &morphio::Morphology::cellFamily,
129-
// "Returns the cell family (neuron or glia)")
130127
.def_property_readonly("version", &morphio::Morphology::version, "Returns the version")
131128

132129
// Iterators
@@ -252,9 +249,6 @@ void bind_immutable_module(py::module& m) {
252249
"Return the graph connectivity of the GlialCell "
253250
"where each section is seen as a node\nNote: -1 is the soma node")
254251
.def_property_readonly("soma_type", &morphio::GlialCell::somaType, "Returns the soma type")
255-
// .def_property_readonly("cell_family",
256-
// &morphio::GlialCell::cellFamily,
257-
// "Returns the cell family (neuron or glia)")
258252
.def_property_readonly("version", &morphio::GlialCell::version, "Returns the version")
259253

260254
// Iterators

binds/python/bind_misc.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,6 @@ void bind_misc(py::module& m) {
200200
"CellLevel",
201201
"Container class for information available at the "
202202
"cell level (cell type, file version, soma type)")
203-
// .def_readwrite("cell_family",
204-
// &morphio::Property::CellLevel::_cellFamily,
205-
// "Returns the cell family (neuron or glia)")
206203
.def_readwrite("soma_type",
207204
&morphio::Property::CellLevel::_somaType,
208205
"Returns the soma type")

binds/python/bind_mutable.cpp

Lines changed: 269 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <morphio/mut/mitochondria.h>
1111
#include <morphio/mut/morphology.h>
1212
#include <morphio/morphology.h>
13+
#include <morphio/glial_cell.h>
1314

1415
#include <array>
1516

@@ -42,6 +43,7 @@ void bind_mutable_module(py::module& m) {
4243
"Additional Ctor that accepts as filename any python "
4344
"object that implements __repr__ or __str__")
4445

46+
4547
// Cell sub-part accessors
4648
.def_property_readonly("sections",
4749
&morphio::mut::Morphology::sections,
@@ -122,10 +124,6 @@ void bind_mutable_module(py::module& m) {
122124
"Return the graph connectivity of the morphology "
123125
"where each section is seen as a node\nNote: -1 is the soma node")
124126

125-
// .def_property_readonly("cell_family",
126-
// &morphio::mut::Morphology::cellFamily,
127-
// "Returns the cell family (neuron or glia)")
128-
129127
.def_property_readonly("soma_type",
130128
&morphio::mut::Morphology::somaType,
131129
"Returns the soma type")
@@ -178,6 +176,161 @@ void bind_mutable_module(py::module& m) {
178176
"If recursive == true, all descendent will be appended as well",
179177
"mutable_section"_a,
180178
"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+
181334

182335
py::class_<morphio::mut::Mitochondria>(m, "Mitochondria")
183336
.def(py::init<>())
@@ -476,6 +629,118 @@ void bind_mutable_module(py::module& m) {
476629
"center",
477630
[](morphio::mut::Soma* soma) { return py::array(3, soma->center().data()); },
478631
"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+
479744

480745
py::class_<morphio::mut::EndoplasmicReticulum>(m, "EndoplasmicReticulum")
481746
.def(py::init<>())

include/morphio/enums.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ enum AnnotationType {
4141
SINGLE_CHILD,
4242
};
4343

44-
/** The cell family represented by morphio::Morphology. */
45-
//enum CellFamily { NEURON = 0, GLIA = 1 };
46-
4744
enum SomaType {
4845
SOMA_UNDEFINED = 0,
4946
SOMA_SINGLE_POINT,

include/morphio/mut/glial_cell.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ bool _checkDuplicatePoint(const std::shared_ptr<GlialSection>& parent,
2626
class GlialCell
2727
{
2828
public:
29-
using Family = CellFamily::GLIA;
29+
using CellType = CellFamily::GLIA;
3030

3131
GlialCell()
3232
: _counter(0)

include/morphio/mut/morphology.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ bool _checkDuplicatePoint(const std::shared_ptr<Section>& parent,
2626
class Morphology
2727
{
2828
public:
29-
using Family = CellFamily::NEURON;
29+
using CellType = CellFamily::NEURON;
3030

3131
Morphology()
3232
: _counter(0)

0 commit comments

Comments
 (0)