• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

BlueBrain / MorphIO / 6533620342

16 Oct 2023 12:32PM UTC coverage: 76.051% (-0.05%) from 76.104%
6533620342

Pull #476

github

mgeplf
should apt-get update first
Pull Request #476: Efficient swc build

278 of 278 new or added lines in 4 files covered. (100.0%)

1972 of 2593 relevant lines covered (76.05%)

903.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.85
/src/mut/section.cpp
1
/* Copyright (c) 2013-2023, EPFL/Blue Brain Project
2
 *
3
 * SPDX-License-Identifier: Apache-2.0
4
 */
5
#include <algorithm>  // any_of
6

7
#include <morphio/errorMessages.h>
8
#include <morphio/mut/morphology.h>
9
#include <morphio/mut/section.h>
10
#include <morphio/tools.h>
11
#include <morphio/vector_types.h>
12

13
#include "../point_utils.h"
14

15
namespace morphio {
16
namespace mut {
17
using morphio::readers::ErrorMessages;
18

19
static inline bool _emptySection(const std::shared_ptr<Section>& section) {
460✔
20
    return section->points().empty();
460✔
21
}
22

23
Section::Section(Morphology* morphology,
770✔
24
                 unsigned int id,
25
                 SectionType type,
26
                 const Property::PointLevel& pointProperties)
770✔
27
    : morphology_(morphology)
28
    , point_properties_(pointProperties)
29
    , id_(id)
30
    , section_type_(type) {}
770✔
31

32
Section::Section(Morphology* morphology, unsigned int id, const morphio::Section& section)
268✔
33
    : Section(morphology,
34
              id,
35
              section.type(),
36
              Property::PointLevel(section.properties_->_pointLevel, section.range_)) {}
268✔
37

38
Section::Section(Morphology* morphology, unsigned int id, const Section& section)
×
39
    : morphology_(morphology)
40
    , point_properties_(section.point_properties_)
×
41
    , id_(id)
42
    , section_type_(section.section_type_) {}
×
43

44
void Section::throwIfNoOwningMorphology() const {
4,788✔
45
    if (!morphology_) {
4,788✔
46
        throw std::runtime_error("Section does not belong to a morphology, impossible operation");
×
47
    }
48
}
4,788✔
49

50
Morphology* Section::getOwningMorphologyOrThrow() const {
4,428✔
51
    throwIfNoOwningMorphology();
4,428✔
52
    return morphology_;
4,428✔
53
}
54

55
const std::shared_ptr<Section>& Section::parent() const {
408✔
56
    const Morphology* morphology = getOwningMorphologyOrThrow();
408✔
57
    return morphology->_sections.at(morphology->_parent.at(id()));
408✔
58
}
59

60
bool Section::isRoot() const {
1,382✔
61
    const Morphology* morphology = getOwningMorphologyOrThrow();
1,382✔
62
    const auto parentId = morphology->_parent.find(id());
1,382✔
63
    if (parentId != morphology->_parent.end()) {
1,382✔
64
        return morphology->_sections.find(parentId->second) == morphology->_sections.end();
828✔
65
    }
66
    return true;
554✔
67
}
68

69
bool Section::hasSameShape(const Section& other) const noexcept {
774✔
70
    return (other.type() == type() && other.diameters() == diameters() &&
1,546✔
71
            other.points() == points() && other.perimeters() == perimeters());
1,546✔
72
}
73

74
bool Section::isHeterogeneous(bool downstream) const {
24✔
75
    auto predicate = [&](const std::shared_ptr<Section>& s) { return type() != s->type(); };
36✔
76

77
    if (downstream) {
24✔
78
        return std::any_of(breadth_begin(), breadth_end(), predicate);
12✔
79
    }
80

81
    return std::any_of(upstream_begin(), upstream_end(), predicate);
12✔
82
}
83

84
const std::vector<std::shared_ptr<Section>>& Section::children() const {
2,178✔
85
    const Morphology* morphology = getOwningMorphologyOrThrow();
2,178✔
86

87
    const auto it = morphology->_children.find(id());
2,178✔
88
    if (it == morphology->_children.end()) {
2,178✔
89
        static std::vector<std::shared_ptr<Section>> empty;
1,470✔
90
        return empty;
1,470✔
91
    }
92
    return it->second;
708✔
93
}
94

95
depth_iterator Section::depth_begin() const {
×
96
    throwIfNoOwningMorphology();
×
97
    return depth_iterator(const_cast<Section*>(this)->shared_from_this());
×
98
}
99

100
depth_iterator Section::depth_end() const {
×
101
    throwIfNoOwningMorphology();
×
102
    return depth_iterator();
×
103
}
104

105
breadth_iterator Section::breadth_begin() const {
324✔
106
    throwIfNoOwningMorphology();
324✔
107
    return breadth_iterator(const_cast<Section*>(this)->shared_from_this());
648✔
108
}
109

110
breadth_iterator Section::breadth_end() const {
12✔
111
    throwIfNoOwningMorphology();
12✔
112
    return breadth_iterator();
12✔
113
}
114

115
upstream_iterator Section::upstream_begin() const {
12✔
116
    throwIfNoOwningMorphology();
12✔
117
    return upstream_iterator(const_cast<Section*>(this)->shared_from_this());
12✔
118
}
119

120
upstream_iterator Section::upstream_end() const {
12✔
121
    throwIfNoOwningMorphology();
12✔
122
    return upstream_iterator();
12✔
123
}
124

125
/*
126
static std::ostream& operator<<(std::ostream& os, const Section& section) {
127
    ::operator<<(os, section);
128
    return os;
129
}
130

131
std::ostream& operator<<(std::ostream& os, const std::shared_ptr<Section>& sectionPtr) {
132
    os << *sectionPtr;
133
    return os;
134
}
135
*/
136

137
std::shared_ptr<Section> Section::appendSection(std::shared_ptr<Section> original_section,
×
138
                                                bool recursive) {
139
    Morphology* morphology = getOwningMorphologyOrThrow();
×
140

141
    const std::shared_ptr<Section> ptr(
142
        new Section(morphology, morphology->_counter, *original_section));
×
143
    unsigned int parentId = id();
×
144
    uint32_t childId = morphology->_register(ptr);
×
145
    auto& _sections = morphology->_sections;
×
146

147
    bool emptySection = _emptySection(_sections[childId]);
×
148
    if (emptySection) {
×
149
        printError(Warning::APPENDING_EMPTY_SECTION,
×
150
                   morphology->_err.WARNING_APPENDING_EMPTY_SECTION(_sections[childId]));
×
151
    }
152

153
    if (!ErrorMessages::isIgnored(Warning::WRONG_DUPLICATE) && !emptySection &&
×
154
        !_checkDuplicatePoint(_sections[parentId], _sections[childId])) {
×
155
        printError(Warning::WRONG_DUPLICATE,
×
156
                   morphology->_err.WARNING_WRONG_DUPLICATE(_sections[childId],
×
157
                                                            _sections.at(parentId)));
×
158
    }
159

160
    morphology->_parent[childId] = parentId;
×
161
    morphology->_children[parentId].push_back(ptr);
×
162

163
    // Careful not to use a reference here or you will face ref invalidation problem with vector
164
    // resize The argument `original_section` of this function could be a reference to the
165
    // `_children` array and that reference might be invalidated by this `push_back` (in case
166
    // `vector` needs to reallocate the array)
167
    if (recursive) {
×
168
        for (auto child : original_section->children()) {
×
169
            ptr->appendSection(child, true);
×
170
        }
171
    }
172

173
    return ptr;
×
174
}
175

176
std::shared_ptr<Section> Section::appendSection(const morphio::Section& section, bool recursive) {
164✔
177
    Morphology* morphology = getOwningMorphologyOrThrow();
164✔
178
    const std::shared_ptr<Section> ptr(new Section(morphology, morphology->_counter, section));
164✔
179
    // const auto ptr = std::make_shared<Section>(morphology, morphology->_counter, section);
180
    unsigned int parentId = id();
164✔
181
    uint32_t childId = morphology->_register(ptr);
164✔
182
    auto& _sections = morphology->_sections;
164✔
183

184
    bool emptySection = _emptySection(_sections[childId]);
164✔
185
    if (emptySection) {
164✔
186
        printError(Warning::APPENDING_EMPTY_SECTION,
×
187
                   morphology->_err.WARNING_APPENDING_EMPTY_SECTION(_sections[childId]));
×
188
    }
189

190
    if (!ErrorMessages::isIgnored(Warning::WRONG_DUPLICATE) && !emptySection &&
328✔
191
        !_checkDuplicatePoint(_sections[parentId], _sections[childId])) {
164✔
192
        printError(Warning::WRONG_DUPLICATE,
8✔
193
                   morphology->_err.WARNING_WRONG_DUPLICATE(_sections[childId],
16✔
194
                                                            _sections.at(parentId)));
8✔
195
    }
196

197
    morphology->_parent[childId] = parentId;
164✔
198
    morphology->_children[parentId].push_back(ptr);
164✔
199

200
    if (recursive) {
164✔
201
        for (auto child : section.children()) {
176✔
202
            ptr->appendSection(child, true);
12✔
203
        }
204
    }
205

206
    return ptr;
328✔
207
}
208

209
std::shared_ptr<Section> Section::appendSection(const Property::PointLevel& pointProperties,
296✔
210
                                                SectionType sectionType) {
211
    Morphology* morphology = getOwningMorphologyOrThrow();
296✔
212
    unsigned int parentId = id();
296✔
213

214
    auto& _sections = morphology->_sections;
296✔
215
    if (sectionType == SectionType::SECTION_UNDEFINED) {
296✔
216
        sectionType = type();
×
217
    }
218

219
    if (sectionType == SECTION_SOMA) {
296✔
220
        throw morphio::SectionBuilderError("Cannot create section with type soma");
×
221
    }
222

223
    std::shared_ptr<Section> ptr(
224
        new Section(morphology, morphology->_counter, sectionType, pointProperties));
296✔
225

226
    uint32_t childId = morphology->_register(ptr);
296✔
227

228
    bool emptySection = _emptySection(_sections[childId]);
296✔
229
    if (emptySection) {
296✔
230
        printError(Warning::APPENDING_EMPTY_SECTION,
×
231
                   morphology->_err.WARNING_APPENDING_EMPTY_SECTION(_sections[childId]));
×
232
    }
233

234
    if (!ErrorMessages::isIgnored(Warning::WRONG_DUPLICATE) && !emptySection &&
592✔
235
        !_checkDuplicatePoint(_sections[parentId], _sections[childId])) {
296✔
236
        printError(Warning::WRONG_DUPLICATE,
×
237
                   morphology->_err.WARNING_WRONG_DUPLICATE(_sections[childId],
×
238
                                                            _sections[parentId]));
×
239
    }
240

241
    morphology->_parent[childId] = parentId;
296✔
242
    morphology->_children[parentId].push_back(ptr);
296✔
243
    return ptr;
592✔
244
}
245

246
}  // end namespace mut
247
}  // end namespace morphio
248

249
std::ostream& operator<<(std::ostream& os, const morphio::mut::Section& section) {
×
250
    const auto& points = section.points();
×
251
    if (points.empty()) {
×
252
        os << "Section(id=" << section.id() << ", points=[])";
×
253
    } else {
254
        os << "Section(id=" << section.id() << ", points=[(" << points[0] << "),..., ("
×
255
           << points[points.size() - 1] << ")])";
×
256
    }
257

258
    return os;
×
259
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc