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

BlueBrain / MorphIO / 6533524408

16 Oct 2023 12:24PM UTC coverage: 76.051% (-0.02%) from 76.073%
6533524408

push

github

mgeplf
fix test_root_node_split

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

97.2
/src/morphology.cpp
1
/* Copyright (c) 2013-2023, EPFL/Blue Brain Project
2
 *
3
 * SPDX-License-Identifier: Apache-2.0
4
 */
5
#include <cctype>  // std::tolower
6
#include <fstream>
7
#include <iterator>  // std::back_inserter
8
#include <memory>
9

10
#include <morphio/endoplasmic_reticulum.h>
11
#include <morphio/mitochondria.h>
12
#include <morphio/morphology.h>
13
#include <morphio/section.h>
14
#include <morphio/soma.h>
15

16
#include <morphio/mut/morphology.h>
17

18
#include "readers/morphologyASC.h"
19
#include "readers/morphologyHDF5.h"
20
#include "readers/morphologySWC.h"
21

22
namespace {
23

24
std::string readCompleteFile(const std::string& path) {
102✔
25
    std::ifstream ifs(path);
204✔
26

27
    if (!ifs) {
102✔
28
        throw(morphio::RawDataError("File: " + path + " does not exist."));
2✔
29
    }
30

31
    std::ostringstream oss;
200✔
32
    oss << ifs.rdbuf();
100✔
33

34
    return oss.str();
200✔
35
}
36

37
void buildChildren(const std::shared_ptr<morphio::Property::Properties>& properties) {
328✔
38
    {
39
        const auto& sections = properties->get<morphio::Property::Section>();
328✔
40
        auto& children = properties->_sectionLevel._children;
328✔
41

42
        for (unsigned int i = 0; i < sections.size(); ++i) {
7,496✔
43
            const int32_t parent = sections[i][1];
7,168✔
44
            children[parent].push_back(i);
7,168✔
45
        }
46
    }
47

48
    {
49
        const auto& sections = properties->get<morphio::Property::MitoSection>();
328✔
50
        auto& children = properties->_mitochondriaSectionLevel._children;
328✔
51

52
        for (unsigned int i = 0; i < sections.size(); ++i) {
586✔
53
            const int32_t parent = sections[i][1];
258✔
54
            children[parent].push_back(i);
258✔
55
        }
56
    }
57
}
328✔
58

59
morphio::SomaType getSomaType(long unsigned int num_soma_points) {
266✔
60
    switch (num_soma_points) {
266✔
61
    case 0:
36✔
62
        return morphio::SOMA_UNDEFINED;
36✔
63
    case 1:
138✔
64
        return morphio::SOMA_SINGLE_POINT;
138✔
65
    case 2:
82✔
66
        return morphio::SOMA_UNDEFINED;
82✔
67
    default:
10✔
68
        break;
10✔
69
    }
70
    return morphio::SOMA_SIMPLE_CONTOUR;
10✔
71
}
72

73
std::string tolower(const std::string& str) {
298✔
74
    std::string ret;
298✔
75
    std::transform(str.begin(), str.end(), std::back_inserter(ret), [](unsigned char c) {
724✔
76
        return std::tolower(c);
724✔
77
    });
298✔
78
    return ret;
298✔
79
}
80

81
morphio::Property::Properties loadFile(const std::string& path, unsigned int options) {
284✔
82
    const size_t pos = path.find_last_of('.');
284✔
83
    if (pos == std::string::npos || pos == path.length() - 1) {
284✔
84
        throw(morphio::UnknownFileType("File has no extension"));
2✔
85
    }
86

87
    std::string extension = tolower(path.substr(pos + 1));
564✔
88

89
    if (extension == "h5") {
282✔
90
        return morphio::readers::h5::load(path);
178✔
91
    } else if (extension == "asc") {
104✔
92
        std::string contents = readCompleteFile(path);
102✔
93
        return morphio::readers::asc::load(path, contents, options);
50✔
94
    } else if (extension == "swc") {
52✔
95
        std::string contents = readCompleteFile(path);
100✔
96
        return morphio::readers::swc::load(path, contents, options);
50✔
97
    }
98

99
    throw(morphio::UnknownFileType("Unhandled file type: '" + extension +
4✔
100
                                   "' only SWC, ASC and H5 are supported"));
6✔
101
}
102

103

104
morphio::Property::Properties loadString(const std::string& contents,
16✔
105
                                         const std::string& extension,
106
                                         unsigned int options) {
107
    std::string lower_extension = tolower(extension);
32✔
108

109
    if (lower_extension == "asc") {
16✔
110
        return morphio::readers::asc::load("$STRING$", contents, options);
×
111
    } else if (lower_extension == "swc") {
16✔
112
        return morphio::readers::swc::load("$STRING$", contents, options);
48✔
113
    }
114

115
    throw(morphio::UnknownFileType("Unhandled file type: '" + lower_extension +
×
116
                                   "' only SWC, ASC and H5 are supported"));
×
117
}
118

119
}  // namespace
120

121
namespace morphio {
122

123
Morphology::Morphology(const Property::Properties& properties, unsigned int options)
316✔
124
    : properties_(std::make_shared<Property::Properties>(properties)) {
316✔
125
    buildChildren(properties_);
316✔
126

127
    if (properties_->_cellLevel.fileFormat() != "swc") {
316✔
128
        properties_->_cellLevel._somaType = getSomaType(soma().points().size());
266✔
129
    }
130

131
    // For SWC and ASC, sanitization and modifier application are already taken care of by
132
    // their respective loaders
133
    if (properties._cellLevel.fileFormat() == "h5" && options) {
316✔
134
        mut::Morphology mutable_morph(*this);
8✔
135
        mutable_morph.applyModifiers(options);
4✔
136
        properties_ = std::make_shared<Property::Properties>(mutable_morph.buildReadOnly());
4✔
137
        buildChildren(properties_);
4✔
138
    }
139
}
316✔
140

141
Morphology::Morphology(const std::string& path, unsigned int options)
284✔
142
    : Morphology(loadFile(path, options), options) {}
284✔
143

144
Morphology::Morphology(const HighFive::Group& group, unsigned int options)
70✔
145
    : Morphology(readers::h5::load(group), options) {}
70✔
146

147
Morphology::Morphology(const mut::Morphology& morphology) {
8✔
148
    properties_ = std::make_shared<Property::Properties>(morphology.buildReadOnly());
8✔
149
    buildChildren(properties_);
8✔
150
}
8✔
151

152
Morphology::Morphology(const std::string& contents,
16✔
153
                       const std::string& extension,
154
                       unsigned int options)
16✔
155
    : Morphology(loadString(contents, extension, options), options) {}
16✔
156

157
Soma Morphology::soma() const {
416✔
158
    return Soma(properties_);
416✔
159
}
160

161
Mitochondria Morphology::mitochondria() const {
80✔
162
    return Mitochondria(properties_);
80✔
163
}
164

165
EndoplasmicReticulum Morphology::endoplasmicReticulum() const {
72✔
166
    return EndoplasmicReticulum(properties_);
72✔
167
}
168

169
const std::vector<Property::Annotation>& Morphology::annotations() const {
4✔
170
    return properties_->_cellLevel._annotations;
4✔
171
}
172

173
const std::vector<Property::Marker>& Morphology::markers() const {
4✔
174
    return properties_->_cellLevel._markers;
4✔
175
}
176

177
Section Morphology::section(uint32_t id) const {
914✔
178
    return {id, properties_};
914✔
179
}
180

181
std::vector<Section> Morphology::rootSections() const {
150✔
182
    const auto& sections = properties_->children<morphio::Property::Section>();
150✔
183

184
    if (sections.empty()) {
150✔
185
        return {};
×
186
    }
187

188
    std::vector<Section> result;
300✔
189

190
    const std::vector<uint32_t>& children = sections.at(-1);
150✔
191
    result.reserve(children.size());
150✔
192
    for (auto id : children) {
864✔
193
        result.push_back(section(id));
714✔
194
    }
195

196
    return result;
150✔
197
}
198

199
std::vector<Section> Morphology::sections() const {
54✔
200
    // TODO: Make this more performant when needed
201
    std::vector<Section> sections_;
54✔
202
    auto count = properties_->get<morphio::Property::Section>().size();
54✔
203
    sections_.reserve(count);
54✔
204
    for (unsigned int i = 0; i < count; ++i) {
254✔
205
        sections_.emplace_back(section(i));
200✔
206
    }
207
    return sections_;
54✔
208
}
209

210
template <typename Property>
211
const std::vector<typename Property::Type>& Morphology::get() const {
96✔
212
    return properties_->get<Property>();
96✔
213
}
214

215
const Points& Morphology::points() const noexcept {
28✔
216
    return get<Property::Point>();
28✔
217
}
218

219
std::vector<uint32_t> Morphology::sectionOffsets() const {
6✔
220
    const std::vector<Property::Section::Type>& indices_and_parents = get<Property::Section>();
6✔
221
    auto size = indices_and_parents.size();
6✔
222
    std::vector<uint32_t> indices(size + 1);
6✔
223
    std::transform(indices_and_parents.begin(),
224
                   indices_and_parents.end(),
225
                   indices.begin(),
226
                   [](const Property::Section::Type& pair) { return pair[0]; });
42✔
227
    indices[size] = static_cast<uint32_t>(points().size());
6✔
228
    return indices;
6✔
229
}
230

231
const std::vector<morphio::floatType>& Morphology::diameters() const {
16✔
232
    return get<Property::Diameter>();
16✔
233
}
234

235
const std::vector<morphio::floatType>& Morphology::perimeters() const {
26✔
236
    return get<Property::Perimeter>();
26✔
237
}
238

239
const std::vector<SectionType>& Morphology::sectionTypes() const {
20✔
240
    return get<Property::SectionType>();
20✔
241
}
242

243
const CellFamily& Morphology::cellFamily() const {
2✔
244
    return properties_->cellFamily();
2✔
245
}
246

247
const SomaType& Morphology::somaType() const {
26✔
248
    return properties_->somaType();
26✔
249
}
250

251
const std::map<int, std::vector<unsigned int>>& Morphology::connectivity() const {
6✔
252
    return properties_->children<Property::Section>();
6✔
253
}
254

255
const MorphologyVersion& Morphology::version() const {
2✔
256
    return properties_->version();
2✔
257
}
258

259
depth_iterator Morphology::depth_begin() const {
6✔
260
    return depth_iterator(*this);
6✔
261
}
262

263
depth_iterator Morphology::depth_end() const {
42✔
264
    return depth_iterator();
42✔
265
}
266

267
breadth_iterator Morphology::breadth_begin() const {
2✔
268
    return breadth_iterator(*this);
2✔
269
}
270

271
breadth_iterator Morphology::breadth_end() const {
22✔
272
    return breadth_iterator();
22✔
273
}
274

275
}  // namespace morphio
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