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

BlueBrain / MorphIO / 6545228678

17 Oct 2023 08:31AM UTC coverage: 76.668% (+0.6%) from 76.104%
6545228678

Pull #476

github

mgeplf
fix missing data
Pull Request #476: Efficient swc build

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

1988 of 2593 relevant lines covered (76.67%)

914.88 hits per line

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

37.93
/src/errorMessages.cpp
1
/* Copyright (c) 2013-2023, EPFL/Blue Brain Project
2
 *
3
 * SPDX-License-Identifier: Apache-2.0
4
 */
5
#include <iostream>  // std::cerr
6
#include <sstream>   // std::ostringstream
7
#include <string>
8
#include <vector>
9

10
#include <morphio/errorMessages.h>
11

12
namespace morphio {
13
static int MORPHIO_MAX_N_WARNINGS = 100;
14
static bool MORPHIO_RAISE_WARNINGS = false;
15

16
/**
17
 * Controls the maximum number of warning to be printed on screen.
18
 * 0 will print no warning
19
 * -1 will print them all
20
 */
21
void set_maximum_warnings(int n_warnings) {
×
22
    MORPHIO_MAX_N_WARNINGS = n_warnings;
×
23
}
×
24

25
/*
26
 *   Whether to raise warning as errors
27
 */
28
void set_raise_warnings(bool is_raise) {
×
29
    MORPHIO_RAISE_WARNINGS = is_raise;
×
30
}
×
31

32
/**
33
 *   Ignore/Unignore a specific warning message
34
 */
35
void set_ignored_warning(Warning warning, bool ignore) {
×
36
    if (ignore) {
×
37
        readers::_ignoredWarnings.insert(warning);
×
38
    } else {
39
        readers::_ignoredWarnings.erase(warning);
×
40
    }
41
}
×
42

43
/**
44
 *   Ignore/Unignore a specific warning message
45
 */
46
void set_ignored_warning(const std::vector<Warning>& warnings, bool ignore) {
×
47
    for (auto warning : warnings) {
×
48
        set_ignored_warning(warning, ignore);
×
49
    }
50
}
×
51

52
void printError(Warning warning, const std::string& msg) {
46✔
53
    static int error = 0;
54

55
    if (readers::ErrorMessages::isIgnored(warning) || MORPHIO_MAX_N_WARNINGS == 0) {
46✔
56
        return;
×
57
    }
58

59
    if (MORPHIO_RAISE_WARNINGS) {
46✔
60
        throw MorphioError(msg);
×
61
    }
62

63
    if (MORPHIO_MAX_N_WARNINGS < 0 || error <= MORPHIO_MAX_N_WARNINGS) {
46✔
64
        std::cerr << msg << '\n';
46✔
65
        if (error == MORPHIO_MAX_N_WARNINGS) {
46✔
66
            std::cerr << "Maximum number of warning reached. Next warnings "
67
                         "won't be displayed.\n"
68
                         "You can change this number by calling:\n"
69
                         "\t- C++: set_maximum_warnings(int)\n"
70
                         "\t- Python: morphio.set_maximum_warnings(int)\n"
71
                         "0 will print no warning. -1 will print them all\n";
×
72
        }
73
        ++error;
46✔
74
    }
75
}
76

77
namespace readers {
78
bool ErrorMessages::isIgnored(Warning warning) {
516✔
79
    return _ignoredWarnings.find(warning) != _ignoredWarnings.end();
516✔
80
}
81

82
std::string ErrorMessages::errorMsg(long unsigned int lineNumber,
74✔
83
                                    ErrorLevel errorLevel,
84
                                    std::string msg) const {
85
    return "\n" + (_uri.empty() ? "" : errorLink(lineNumber, errorLevel) + "\n") + msg;
148✔
86
}
87

88
// LCOV_EXCL_START {  all the error messages are excluded from coverage
89

90
////////////////////////////////////////////////////////////////////////////////
91
//              ERRORS
92
////////////////////////////////////////////////////////////////////////////////
93

94
std::string ErrorMessages::ERROR_OPENING_FILE() const {
95
    return "Error opening morphology file:\n" + errorMsg(0, ErrorLevel::ERROR);
96
}
97

98
std::string ErrorMessages::ERROR_LINE_NON_PARSABLE(long unsigned int lineNumber) const {
99
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Unable to parse this line");
100
}
101

102
std::string ErrorMessages::ERROR_UNSUPPORTED_SECTION_TYPE(long unsigned int lineNumber,
103
                                                          const SectionType& type) const {
104
    return errorMsg(lineNumber,
105
                    ErrorLevel::ERROR,
106
                    "Unsupported section type: " + std::to_string(type));
107
}
108

109
std::string ErrorMessages::ERROR_UNSUPPORTED_VASCULATURE_SECTION_TYPE(
110
    long unsigned int lineNumber, const VascularSectionType& type) const {
111
    return errorMsg(lineNumber,
112
                    ErrorLevel::ERROR,
113
                    "Unsupported section type: " + std::to_string(type));
114
}
115

116
std::string ErrorMessages::ERROR_MULTIPLE_SOMATA(const std::vector<Sample>& somata) const {
117
    std::string msg("Multiple somata found: ");
118
    for (auto soma : somata) {
119
        msg += "\n" + errorMsg(soma.lineNumber, ErrorLevel::ERROR);
120
    }
121
    return msg;
122
}
123

124
std::string ErrorMessages::ERROR_MISSING_PARENT(const Sample& sample) const {
125
    return errorMsg(sample.lineNumber,
126
                    ErrorLevel::ERROR,
127
                    "Sample id: " + std::to_string(sample.id) +
128
                        " refers to non-existant parent ID: " + std::to_string(sample.parentId));
129
}
130

131
std::string ErrorMessages::ERROR_SOMA_BIFURCATION(const Sample& sample,
132
                                                  const std::vector<Sample>& children) const {
133
    std::string msg = errorMsg(sample.lineNumber, ErrorLevel::ERROR, "Found soma bifurcation\n");
134
    msg += "The following children have been found:";
135
    for (auto child : children) {
136
        msg += errorMsg(child.lineNumber, ErrorLevel::WARNING, "");
137
    }
138
    return msg;
139
}
140

141
std::string ErrorMessages::ERROR_SOMA_WITH_NEURITE_PARENT(const Sample& sample) const {
142
    return errorMsg(sample.lineNumber,
143
                    ErrorLevel::ERROR,
144
                    "Found a soma point with a neurite as parent");
145
}
146

147
std::string ErrorMessages::ERROR_REPEATED_ID(const Sample& originalSample,
148
                                             const Sample& newSample) const {
149
    return errorMsg(newSample.lineNumber,
150
                    ErrorLevel::WARNING,
151
                    "Repeated ID: " + std::to_string(originalSample.id)) +
152
           "\nID already appears here: \n" + errorLink(originalSample.lineNumber, ErrorLevel::INFO);
153
}
154

155
std::string ErrorMessages::ERROR_SELF_PARENT(const Sample& sample) const {
156
    return errorMsg(sample.lineNumber, ErrorLevel::ERROR, "Parent ID can not be itself");
157
}
158

159
std::string ErrorMessages::EARLY_END_OF_FILE(long unsigned int lineNumber) const {
160
    return errorMsg(lineNumber,
161
                    ErrorLevel::ERROR,
162
                    "The end of the file was reached before parsing finshed");
163
}
164

165

166
std::string ErrorMessages::ERROR_NOT_IMPLEMENTED_UNDEFINED_SOMA(const std::string& method) const {
167
    return "Cannot call: " + method + " on soma of type UNDEFINED";
168
}
169

170
std::string ErrorMessages::ERROR_MISSING_MITO_PARENT(int mitoParentId) const {
171
    return "While trying to append new mitochondria section.\n"
172
           "Mitochondrial parent section: " +
173
           std::to_string(mitoParentId) + " does not exist.";
174
}
175

176
std::string ErrorMessages::ERROR_NEGATIVE_ID(long unsigned int lineNumber) const {
177
    return errorMsg(lineNumber, ErrorLevel::WARNING, "The ID assigned to this line is negative");
178
}
179

180
/**
181
   Return val1 and highlight it with some color if val1 != val2
182
**/
183
static std::string _col(morphio::floatType val1, morphio::floatType val2) {
184
    bool is_ok = std::fabs(val1 - val2) < morphio::epsilon;
185
    if (is_ok) {
186
        return std::to_string(val1);
187
    }
188
    return "\033[1;33m" + std::to_string(val1) + " (exp. " + std::to_string(val2) + ")\033[0m";
189
}
190

191
////////////////////////////////////////////////////////////////////////////////
192
//             NEUROLUCIDA
193
////////////////////////////////////////////////////////////////////////////////
194
std::string ErrorMessages::ERROR_SOMA_ALREADY_DEFINED(long unsigned int lineNumber) const {
195
    return errorMsg(lineNumber, ErrorLevel::ERROR, "A soma is already defined");
196
}
197

198
std::string ErrorMessages::ERROR_PARSING_POINT(long unsigned int lineNumber,
199
                                               const std::string& point) const {
200
    return errorMsg(lineNumber,
201
                    ErrorLevel::ERROR,
202
                    "Error converting: \"" + point + "\" to floatType");
203
}
204

205
std::string ErrorMessages::ERROR_UNKNOWN_TOKEN(long unsigned int lineNumber,
206
                                               const std::string& token) const {
207
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Unexpected token: " + token);
208
}
209

210
std::string ErrorMessages::ERROR_UNEXPECTED_TOKEN(long unsigned int lineNumber,
211
                                                  const std::string& expected,
212
                                                  const std::string& got,
213
                                                  const std::string& msg) const {
214
    return errorMsg(lineNumber,
215
                    ErrorLevel::ERROR,
216
                    "Unexpected token\nExpected: " + expected + " but got " + got + " " + msg);
217
}
218

219
std::string ErrorMessages::ERROR_EOF_REACHED(long unsigned int lineNumber) const {
220
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Can't iterate past the end");
221
}
222

223
std::string ErrorMessages::ERROR_EOF_IN_NEURITE(long unsigned int lineNumber) const {
224
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Hit end of file while consuming a neurite");
225
}
226

227
std::string ErrorMessages::ERROR_EOF_UNBALANCED_PARENS(long unsigned int lineNumber) const {
228
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Hit end of file before balanced parens");
229
}
230

231
std::string ErrorMessages::ERROR_UNCOMPATIBLE_FLAGS(morphio::Option flag1,
232
                                                    morphio::Option flag2) const {
233
    return errorMsg(0,
234
                    ErrorLevel::ERROR,
235
                    "Modifiers: " + std::to_string(flag1) + " and : " + std::to_string(flag2) +
236
                        " are incompatible");
237
}
238

239
////////////////////////////////////////////////////////////////////////////////
240
//              WRITERS
241
////////////////////////////////////////////////////////////////////////////////
242

243
std::string ErrorMessages::ERROR_UNSUPPORTED_SECTION_TYPE(const SectionType& type) const {
244
    return ("Attempted to write unsupported section type: " + std::to_string(type) +
245
            ".\n"
246
            "Please try writing to a different format that supports the section type.");
247
}
248

249
std::string ErrorMessages::ERROR_WRONG_EXTENSION(const std::string& filename) const {
250
    return "Filename: " + filename + " must have one of the following extensions: swc, asc or h5";
251
}
252

253
std::string ErrorMessages::ERROR_VECTOR_LENGTH_MISMATCH(const std::string& vec1,
254
                                                        size_t length1,
255
                                                        const std::string& vec2,
256
                                                        size_t length2) const {
257
    std::string msg("Vector length mismatch: \nLength " + vec1 + ": " + std::to_string(length1) +
258
                    "\nLength " + vec2 + ": " + std::to_string(length2));
259
    if (length1 == 0 || length2 == 0) {
260
        msg += "\nTip: Did you forget to fill vector: " + (length1 == 0 ? vec1 : vec2) + " ?";
261
    }
262

263
    return msg;
264
}
265

266
std::string ErrorMessages::ERROR_PERIMETER_DATA_NOT_WRITABLE() {
267
    return "Cannot write a file with perimeter data to ASC or SWC format";
268
}
269

270
std::string ErrorMessages::ERROR_ONLY_CHILD_SWC_WRITER(unsigned int parentId) const {
271
    return ("Section " + std::to_string(parentId) +
272
            " has a single child section. "
273
            "Single child section are not allowed when writing to SWC format. "
274
            "Please sanitize the morphology first.\n"
275
            "Tip: you can use 'removeUnifurcations() (C++) / remove_unifurcations() (python)'");
276
}
277

278
std::string ErrorMessages::ERROR_SOMA_INVALID_SINGLE_POINT() const {
279
    return "Single point soma must have one point";
280
}
281

282
std::string ErrorMessages::ERROR_SOMA_INVALID_THREE_POINT_CYLINDER() const {
283
    return "Multiple points for single point soma";
284
}
285

286
std::string ErrorMessages::ERROR_SOMA_INVALID_CONTOUR() const {
287
    return "Contour soma must have at least 3 points.";
288
}
289

290

291
////////////////////////////////////////////////////////////////////////////////
292
//              WARNINGS
293
////////////////////////////////////////////////////////////////////////////////
294
std::string ErrorMessages::WARNING_WRITE_NO_SOMA() const {
295
    return errorMsg(0, ErrorLevel::WARNING, "Warning: writing file without a soma");
296
}
297

298
std::string ErrorMessages::WARNING_WRITE_EMPTY_MORPHOLOGY() const {
299
    return errorMsg(0,
300
                    ErrorLevel::WARNING,
301
                    "Warning: Skipping an attempt to write an empty morphology.");
302
}
303

304
std::string ErrorMessages::WARNING_NO_SOMA_FOUND() const {
305
    return errorMsg(0, ErrorLevel::WARNING, "Warning: no soma found in file");
306
}
307

308
std::string ErrorMessages::WARNING_ZERO_DIAMETER(const Sample& sample) const {
309
    return errorMsg(sample.lineNumber, ErrorLevel::WARNING, "Warning: zero diameter in file");
310
}
311

312
std::string ErrorMessages::WARNING_DISCONNECTED_NEURITE(const Sample& sample) const {
313
    return errorMsg(sample.lineNumber,
314
                    ErrorLevel::WARNING,
315
                    "Warning: found a disconnected neurite.\n"
316
                    "Neurites are not supposed to have parentId: -1\n"
317
                    "(although this is normal if this neuron has no soma)");
318
}
319

320
std::string ErrorMessages::WARNING_APPENDING_EMPTY_SECTION(
321
    std::shared_ptr<morphio::mut::Section> section) {
322
    return errorMsg(0,
323
                    ErrorLevel::WARNING,
324
                    "Warning: appending empty section with id: " + std::to_string(section->id()));
325
}
326

327
std::string ErrorMessages::WARNING_WRONG_DUPLICATE(
328
    const std::shared_ptr<morphio::mut::Section>& current,
329
    const std::shared_ptr<morphio::mut::Section>& parent) const {
330
    std::string msg("Warning: while appending section: " + std::to_string(current->id()) +
331
                    " to parent: " + std::to_string(parent->id()));
332

333
    if (parent->points().empty()) {
334
        return errorMsg(0, ErrorLevel::WARNING, msg + "\nThe parent section is empty.");
335
    }
336

337
    if (current->points().empty()) {
338
        return errorMsg(0,
339
                        ErrorLevel::WARNING,
340
                        msg +
341
                            "\nThe current section has no points. It should at "
342
                            "least contains "
343
                            "parent section last point");
344
    }
345

346
    auto p0 = parent->points()[parent->points().size() - 1];
347
    auto p1 = current->points()[0];
348
    auto d0 = parent->diameters()[parent->diameters().size() - 1];
349
    auto d1 = current->diameters()[0];
350

351
    std::ostringstream oss;
352
    oss << msg
353
        << "\nThe section first point should be parent section last point: "
354
           "\n        : X Y Z Diameter"
355
           "\nparent last point :["
356
        << std::to_string(p0[0]) << ", " << std::to_string(p0[1]) << ", " << std::to_string(p0[2])
357
        << ", " << std::to_string(d0) << "]\nchild first point :[" << std::to_string(p1[0]) << ", "
358
        << std::to_string(p1[1]) << ", " << std::to_string(p1[2]) << ", " << std::to_string(d1)
359
        << "]\n";
360
    return errorMsg(0, ErrorLevel::WARNING, oss.str());
361
}
362

363
std::string ErrorMessages::WARNING_ONLY_CHILD(const DebugInfo& info,
364
                                              unsigned int parentId,
365
                                              unsigned int childId) const {
366
    int parentLine = info.getLineNumber(parentId);
367
    int childLine = info.getLineNumber(childId);
368
    std::string parentMsg;
369
    std::string childMsg;
370

371
    if (parentLine > -1 && childLine > -1) {
372
        parentMsg = " starting at:\n" +
373
                    errorLink(static_cast<size_t>(parentLine), ErrorLevel::INFO) + "\n";
374
        childMsg = " starting at:\n" +
375
                   errorLink(static_cast<size_t>(childLine), ErrorLevel::WARNING) + "\n";
376
    }
377

378
    std::ostringstream oss;
379
    oss << "Warning: section " << childId << childMsg << " is the only child of "
380
        << "section: " << std::to_string(parentId) << parentMsg
381
        << "\nIt will be merged with the parent section";
382

383
    return errorMsg(0, ErrorLevel::WARNING, oss.str());
384
}
385

386
std::string ErrorMessages::WARNING_NEUROMORPHO_SOMA_NON_CONFORM(const Sample& root,
387
                                                                const Sample& child1,
388
                                                                const Sample& child2) {
389
    floatType x = root.point[0], y = root.point[1], z = root.point[2], r = root.diameter / 2;
390
    std::stringstream ss;
391
    ss << "Warning: the soma does not conform the three point soma spec\n"
392
          "The only valid neuro-morpho soma is:\n"
393
          "1 1 x   y   z r -1\n"
394
          "2 1 x (y-r) z r  1\n"
395
          "3 1 x (y+r) z r  1\n\n"
396

397
          "Got:\n"
398
          "1 1 "
399
       << x << ' ' << y << ' ' << z << ' ' << r
400
       << " -1\n"
401
          "2 1 "
402
       << _col(child1.point[0], x) << ' ' << _col(child1.point[1], y - r) << ' '
403
       << _col(child1.point[2], z) << ' ' << _col(child1.diameter / 2, r)
404
       << " 1\n"
405
          "3 1 "
406
       << _col(child2.point[0], x) << ' ' << _col(child2.point[1], y + r) << ' '
407
       << _col(child2.point[2], z) << ' ' << _col(child2.diameter / 2, r) << " 1\n";
408
    return errorMsg(0, ErrorLevel::WARNING, ss.str());
409
}
410

411
std::string ErrorMessages::WARNING_MITOCHONDRIA_WRITE_NOT_SUPPORTED() const {
412
    return errorMsg(0,
413
                    ErrorLevel::WARNING,
414
                    "Warning: this cell has mitochondria, they cannot be saved in "
415
                    " ASC or SWC format. Please use H5 if you want to save them.");
416
}
417

418
std::string ErrorMessages::WARNING_WRONG_ROOT_POINT(const Sample& child) const {
419
    std::ostringstream oss;
420
    oss << "Warning: with a 3 points soma, neurites must be connected to the first soma "
421
           "point:";
422
    oss << errorMsg(child.lineNumber, ErrorLevel::WARNING, "");
423
    return oss.str();
424
}
425

426
std::string ErrorMessages::WARNING_SOMA_NON_CONTOUR() const {
427
    return errorMsg(0,
428
                    ErrorLevel::WARNING,
429
                    "Soma must be a contour for ASC and H5: see "
430
                    "https://github.com/BlueBrain/MorphIO/issues/457");
431
}
432

433
std::string ErrorMessages::WARNING_SOMA_NON_CYLINDER_OR_POINT() const {
434
    return errorMsg(0,
435
                    ErrorLevel::WARNING,
436
                    "Soma must be stacked cylinders or a point: see "
437
                    "https://github.com/BlueBrain/MorphIO/issues/457");
438
}
439

440
// LCOV_EXCL_STOP }
441

442
}  // namespace readers
443

444
}  // 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