diff --git a/arborio/neurolucida.cpp b/arborio/neurolucida.cpp index 4bccd0dbb16f1c40e3472b89a9899fa00b99b6dc..f4b547d08bf5a4ca0457339dec18c29afc972689 100644 --- a/arborio/neurolucida.cpp +++ b/arborio/neurolucida.cpp @@ -591,39 +591,39 @@ asc_morphology parse_asc_string(const char* input) { arb::segment_tree stree; - // Form a soma composed of two cylinders, extended along the positive and negative - // z axis from the center of the soma. + // Form a soma composed of two cylinders, extended along the negative then positive + // y axis from the center of the soma. // - // -------- soma_b + // -------- soma_2 // | | - // | | - // -------- soma_c - // | | - // | | - // -------- soma_e + // | | y + // -------- soma_0 | z + // | | | / + // | | |/ + // -------- soma_1 o--- x // - arb::mpoint soma_c, soma_b, soma_e; + arb::mpoint soma_0, soma_1, soma_2; if (soma_count==1u) { const auto& st = sub_trees[soma_contours.front()]; const auto& samples = st.root.samples; if (samples.size()==1u) { // The soma is described as a sphere with a single sample. - soma_c = samples.front(); + soma_0 = samples.front(); } else { // The soma is described by a contour. const auto ns = samples.size(); - soma_c.x = std::accumulate(samples.begin(), samples.end(), 0., [](double a, auto& s) {return a+s.x;}) / ns; - soma_c.y = std::accumulate(samples.begin(), samples.end(), 0., [](double a, auto& s) {return a+s.y;}) / ns; - soma_c.z = std::accumulate(samples.begin(), samples.end(), 0., [](double a, auto& s) {return a+s.z;}) / ns; - soma_c.radius = std::accumulate(samples.begin(), samples.end(), 0., - [&soma_c](double a, auto& c) {return a+arb::distance(c, soma_c);}) / ns; + soma_0.x = std::accumulate(samples.begin(), samples.end(), 0., [](double a, auto& s) {return a+s.x;}) / ns; + soma_0.y = std::accumulate(samples.begin(), samples.end(), 0., [](double a, auto& s) {return a+s.y;}) / ns; + soma_0.z = std::accumulate(samples.begin(), samples.end(), 0., [](double a, auto& s) {return a+s.z;}) / ns; + soma_0.radius = std::accumulate(samples.begin(), samples.end(), 0., + [&soma_0](double a, auto& c) {return a+arb::distance(c, soma_0);}) / ns; } - soma_b = {soma_c.x, soma_c.y, soma_c.z-soma_c.radius, soma_c.radius}; - soma_e = {soma_c.x, soma_c.y, soma_c.z+soma_c.radius, soma_c.radius}; - stree.append(arb::mnpos, soma_c, soma_b, 1); - stree.append(arb::mnpos, soma_c, soma_e, 1); + soma_1 = {soma_0.x, soma_0.y-soma_0.radius, soma_0.z, soma_0.radius}; + soma_2 = {soma_0.x, soma_0.y+soma_0.radius, soma_0.z, soma_0.radius}; + stree.append(arb::mnpos, soma_0, soma_1, 1); + stree.append(arb::mnpos, soma_0, soma_2, 1); } // Append the dend, axon and apical dendrites. @@ -633,7 +633,7 @@ asc_morphology parse_asc_string(const char* input) { // Skip soma contours. if (tag==1) continue; - // For now attach everything to the center of the soma at soma_c. + // For now attach everything to the center of the soma at soma_0. // Later we could try to attach to whichever end of the soma is closest. // Also need to push parent id struct binf { @@ -642,7 +642,7 @@ asc_morphology parse_asc_string(const char* input) { arb::mpoint sample; }; - std::vector<binf> tails = {{&st.root, arb::mnpos, soma_c}}; + std::vector<binf> tails = {{&st.root, arb::mnpos, soma_0}}; while (!tails.empty()) { auto head = tails.back(); diff --git a/doc/fileformat/asc.rst b/doc/fileformat/asc.rst index cc1c5ccdd35a3f255e360ae942a041f1b2dc68e8..70d648f1d9475e40259f3404729f63f1897f60e8 100644 --- a/doc/fileformat/asc.rst +++ b/doc/fileformat/asc.rst @@ -36,18 +36,18 @@ and locsets from the meta data. Soma / CellBody """""""""""""""" -The soma, or CellBody, is described in one of three different methods (that we are aware of) in -an ASCII file. +The soma, or CellBody, is described in one of three different methods in an ASCII file: 1. As a CellBody statement containing a single location and radius, which models **a sphere**. 2. As a CellBody statement containing an unbranched sequence of locations that define **a single contour**. 3. As multiple CellBody statements, each defining a contour, that describe the soma as **a stack of contours**. -Arbor supports description methods 1 and 2, and support for method 3 can be added on request -(open an issue). +Arbor supports description methods 1 and 2 following the `neuromporpho policies <http://neuromorpho.org/SomaFormat.html>`_. +Currently multiple contours in method 3 are not supported, and if you need support make +the request with an `issue <https://github.com/arbor-sim/arbor/issues>`_. In each case, the soma is modeled as a cylinder with diameter equal to it's length, centred -at the centre of the soma, and oriented along the z axis. +at the centre of the soma, and oriented along the y axis. For a **spherical** soma, the centre and diameter are that of the sphere. For a **contour**, the centre is the centroid of the locations that define the contour, diff --git a/test/unit/test_asc.cpp b/test/unit/test_asc.cpp index e1ecd098fcda15be0c7249186f5a0332e6b61ee7..daf0eb5f609abe3c250d5fef94af3d2ff4662a45 100644 --- a/test/unit/test_asc.cpp +++ b/test/unit/test_asc.cpp @@ -62,12 +62,12 @@ TEST(asc, only_cell_body) { auto& segs1 = m.morphology.branch_segments(0); EXPECT_EQ(segs1.size(), 1u); EXPECT_EQ(segs1[0].prox, (arb::mpoint{0., 0., 1., 2.})); - EXPECT_EQ(segs1[0].dist, (arb::mpoint{0., 0., -1., 2.})); + EXPECT_EQ(segs1[0].dist, (arb::mpoint{0.,-2., 1., 2.})); auto& segs2 = m.morphology.branch_segments(1); EXPECT_EQ(segs2.size(), 1u); EXPECT_EQ(segs2[0].prox, (arb::mpoint{0., 0., 1., 2.})); - EXPECT_EQ(segs2[0].dist, (arb::mpoint{0., 0., 3., 2.})); + EXPECT_EQ(segs2[0].dist, (arb::mpoint{0., 2., 1., 2.})); } @@ -81,12 +81,12 @@ TEST(asc, only_cell_body) { auto& segs1 = m.morphology.branch_segments(0); EXPECT_EQ(segs1.size(), 1u); EXPECT_EQ(segs1[0].prox, (arb::mpoint{0., 0., 1., 2.})); - EXPECT_EQ(segs1[0].dist, (arb::mpoint{0., 0., -1., 2.})); + EXPECT_EQ(segs1[0].dist, (arb::mpoint{0.,-2., 1., 2.})); auto& segs2 = m.morphology.branch_segments(1); EXPECT_EQ(segs2.size(), 1u); EXPECT_EQ(segs2[0].prox, (arb::mpoint{0., 0., 1., 2.})); - EXPECT_EQ(segs2[0].dist, (arb::mpoint{0., 0., 3., 2.})); + EXPECT_EQ(segs2[0].dist, (arb::mpoint{0., 2., 1., 2.})); } { // Cell with two CellBodys: unsupported feature ATM. @@ -257,9 +257,9 @@ TEST(asc, soma_connection) { EXPECT_EQ(m.num_branches(), 5u); // Test soma EXPECT_EQ(m.branch_segments(0)[0].prox, (arb::mpoint{0, 0, 0, 2})); - EXPECT_EQ(m.branch_segments(0)[0].dist, (arb::mpoint{0, 0,-2, 2})); + EXPECT_EQ(m.branch_segments(0)[0].dist, (arb::mpoint{0,-2, 0, 2})); EXPECT_EQ(m.branch_segments(1)[0].prox, (arb::mpoint{0, 0, 0, 2})); - EXPECT_EQ(m.branch_segments(1)[0].dist, (arb::mpoint{0, 0, 2, 2})); + EXPECT_EQ(m.branch_segments(1)[0].dist, (arb::mpoint{0, 2, 0, 2})); // Test dendrite proximal ends EXPECT_EQ(m.branch_segments(2)[0].prox, (arb::mpoint{0, 2, 0, 1})); EXPECT_EQ(m.branch_segments(3)[0].prox, (arb::mpoint{0, 5, 0, 1})); @@ -271,9 +271,9 @@ TEST(asc, soma_connection) { EXPECT_EQ(m.num_branches(), 7u); // Test soma EXPECT_EQ(m.branch_segments(0)[0].prox, (arb::mpoint{0, 0, 0, 2})); - EXPECT_EQ(m.branch_segments(0)[0].dist, (arb::mpoint{0, 0,-2, 2})); + EXPECT_EQ(m.branch_segments(0)[0].dist, (arb::mpoint{0,-2, 0, 2})); EXPECT_EQ(m.branch_segments(1)[0].prox, (arb::mpoint{0, 0, 0, 2})); - EXPECT_EQ(m.branch_segments(1)[0].dist, (arb::mpoint{0, 0, 2, 2})); + EXPECT_EQ(m.branch_segments(1)[0].dist, (arb::mpoint{0, 2, 0, 2})); // Test dendrite proximal ends EXPECT_EQ(m.branch_segments(2)[0].prox, (arb::mpoint{ 0, 2, 0, 1})); EXPECT_EQ(m.branch_segments(3)[0].prox, (arb::mpoint{ 0, 5, 0, 1})); @@ -287,9 +287,9 @@ TEST(asc, soma_connection) { EXPECT_EQ(m.num_branches(), 8u); // Test soma EXPECT_EQ(m.branch_segments(0)[0].prox, (arb::mpoint{0, 0, 0, 2})); - EXPECT_EQ(m.branch_segments(0)[0].dist, (arb::mpoint{0, 0,-2, 2})); + EXPECT_EQ(m.branch_segments(0)[0].dist, (arb::mpoint{0,-2, 0, 2})); EXPECT_EQ(m.branch_segments(1)[0].prox, (arb::mpoint{0, 0, 0, 2})); - EXPECT_EQ(m.branch_segments(1)[0].dist, (arb::mpoint{0, 0, 2, 2})); + EXPECT_EQ(m.branch_segments(1)[0].dist, (arb::mpoint{0, 2, 0, 2})); // Test dendrite proximal ends EXPECT_EQ(m.branch_segments(2)[0].prox, (arb::mpoint{0, 2, 0, 1})); EXPECT_EQ(m.branch_segments(3)[0].prox, (arb::mpoint{0, 5, 0, 1}));