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

BlueBrain / MorphIO / 5679884058

pending completion
5679884058

push

github

mgeplf
cleanup

8 of 8 new or added lines in 1 file covered. (100.0%)

1968 of 2587 relevant lines covered (76.07%)

905.27 hits per line

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

37.93
/src/errorMessages.cpp
1
#include <iostream>  // std::cerr
2
#include <sstream>   // std::ostringstream
3
#include <string>
4
#include <vector>
5

6
#include <morphio/errorMessages.h>
7

8
namespace morphio {
9
static int MORPHIO_MAX_N_WARNINGS = 100;
10
static bool MORPHIO_RAISE_WARNINGS = false;
11

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

21
/*
22
 *   Whether to raise warning as errors
23
 */
24
void set_raise_warnings(bool is_raise) {
×
25
    MORPHIO_RAISE_WARNINGS = is_raise;
×
26
}
×
27

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

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

48
void printError(Warning warning, const std::string& msg) {
42✔
49
    static int error = 0;
50

51
    if (readers::ErrorMessages::isIgnored(warning) || MORPHIO_MAX_N_WARNINGS == 0) {
42✔
52
        return;
×
53
    }
54

55
    if (MORPHIO_RAISE_WARNINGS) {
42✔
56
        throw MorphioError(msg);
×
57
    }
58

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

73
namespace readers {
74
bool ErrorMessages::isIgnored(Warning warning) {
510✔
75
    return _ignoredWarnings.find(warning) != _ignoredWarnings.end();
510✔
76
}
77

78
std::string ErrorMessages::errorMsg(long unsigned int lineNumber,
60✔
79
                                    ErrorLevel errorLevel,
80
                                    std::string msg) const {
81
    return "\n" + (_uri.empty() ? "" : errorLink(lineNumber, errorLevel) + "\n") + msg;
120✔
82
}
83

84
// LCOV_EXCL_START {  all the error messages are excluded from coverage
85

86
////////////////////////////////////////////////////////////////////////////////
87
//              ERRORS
88
////////////////////////////////////////////////////////////////////////////////
89

90
std::string ErrorMessages::ERROR_OPENING_FILE() const {
91
    return "Error opening morphology file:\n" + errorMsg(0, ErrorLevel::ERROR);
92
}
93

94
std::string ErrorMessages::ERROR_LINE_NON_PARSABLE(long unsigned int lineNumber) const {
95
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Unable to parse this line");
96
}
97

98
std::string ErrorMessages::ERROR_UNSUPPORTED_SECTION_TYPE(long unsigned int lineNumber,
99
                                                          const SectionType& type) const {
100
    return errorMsg(lineNumber,
101
                    ErrorLevel::ERROR,
102
                    "Unsupported section type: " + std::to_string(type));
103
}
104

105
std::string ErrorMessages::ERROR_UNSUPPORTED_VASCULATURE_SECTION_TYPE(
106
    long unsigned int lineNumber, const VascularSectionType& type) const {
107
    return errorMsg(lineNumber,
108
                    ErrorLevel::ERROR,
109
                    "Unsupported section type: " + std::to_string(type));
110
}
111

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

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

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

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

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

151
std::string ErrorMessages::ERROR_SELF_PARENT(const Sample& sample) const {
152
    return errorMsg(sample.lineNumber, ErrorLevel::ERROR, "Parent ID can not be itself");
153
}
154

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

161

162
std::string ErrorMessages::ERROR_NOT_IMPLEMENTED_UNDEFINED_SOMA(const std::string& method) const {
163
    return "Cannot call: " + method + " on soma of type UNDEFINED";
164
}
165

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

172
std::string ErrorMessages::ERROR_NEGATIVE_ID(long unsigned int lineNumber) const {
173
    return errorMsg(lineNumber, ErrorLevel::WARNING, "The ID assigned to this line is negative");
174
}
175

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

187
////////////////////////////////////////////////////////////////////////////////
188
//             NEUROLUCIDA
189
////////////////////////////////////////////////////////////////////////////////
190
std::string ErrorMessages::ERROR_SOMA_ALREADY_DEFINED(long unsigned int lineNumber) const {
191
    return errorMsg(lineNumber, ErrorLevel::ERROR, "A soma is already defined");
192
}
193

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

201
std::string ErrorMessages::ERROR_UNKNOWN_TOKEN(long unsigned int lineNumber,
202
                                               const std::string& token) const {
203
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Unexpected token: " + token);
204
}
205

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

215
std::string ErrorMessages::ERROR_EOF_REACHED(long unsigned int lineNumber) const {
216
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Can't iterate past the end");
217
}
218

219
std::string ErrorMessages::ERROR_EOF_IN_NEURITE(long unsigned int lineNumber) const {
220
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Hit end of file while consuming a neurite");
221
}
222

223
std::string ErrorMessages::ERROR_EOF_UNBALANCED_PARENS(long unsigned int lineNumber) const {
224
    return errorMsg(lineNumber, ErrorLevel::ERROR, "Hit end of file before balanced parens");
225
}
226

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

235
////////////////////////////////////////////////////////////////////////////////
236
//              WRITERS
237
////////////////////////////////////////////////////////////////////////////////
238

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

245
std::string ErrorMessages::ERROR_WRONG_EXTENSION(const std::string& filename) const {
246
    return "Filename: " + filename + " must have one of the following extensions: swc, asc or h5";
247
}
248

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

259
    return msg;
260
}
261

262
std::string ErrorMessages::ERROR_PERIMETER_DATA_NOT_WRITABLE() {
263
    return "Cannot write a file with perimeter data to ASC or SWC format";
264
}
265

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

274
std::string ErrorMessages::ERROR_SOMA_INVALID_SINGLE_POINT() const {
275
    return "Single point soma must have one point";
276
}
277

278
std::string ErrorMessages::ERROR_SOMA_INVALID_THREE_POINT_CYLINDER() const {
279
    return "Multiple points for single point soma";
280
}
281

282
std::string ErrorMessages::ERROR_SOMA_INVALID_CONTOUR() const {
283
    return "Contour soma must have at least 3 points.";
284
}
285

286

287
////////////////////////////////////////////////////////////////////////////////
288
//              WARNINGS
289
////////////////////////////////////////////////////////////////////////////////
290
std::string ErrorMessages::WARNING_WRITE_NO_SOMA() const {
291
    return errorMsg(0, ErrorLevel::WARNING, "Warning: writing file without a soma");
292
}
293

294
std::string ErrorMessages::WARNING_WRITE_EMPTY_MORPHOLOGY() const {
295
    return errorMsg(0,
296
                    ErrorLevel::WARNING,
297
                    "Warning: Skipping an attempt to write an empty morphology.");
298
}
299

300
std::string ErrorMessages::WARNING_NO_SOMA_FOUND() const {
301
    return errorMsg(0, ErrorLevel::WARNING, "Warning: no soma found in file");
302
}
303

304
std::string ErrorMessages::WARNING_ZERO_DIAMETER(const Sample& sample) const {
305
    return errorMsg(sample.lineNumber, ErrorLevel::WARNING, "Warning: zero diameter in file");
306
}
307

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

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

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

329
    if (parent->points().empty()) {
330
        return errorMsg(0, ErrorLevel::WARNING, msg + "\nThe parent section is empty.");
331
    }
332

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

342
    auto p0 = parent->points()[parent->points().size() - 1];
343
    auto p1 = current->points()[0];
344
    auto d0 = parent->diameters()[parent->diameters().size() - 1];
345
    auto d1 = current->diameters()[0];
346

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

359
std::string ErrorMessages::WARNING_ONLY_CHILD(const DebugInfo& info,
360
                                              unsigned int parentId,
361
                                              unsigned int childId) const {
362
    int parentLine = info.getLineNumber(parentId);
363
    int childLine = info.getLineNumber(childId);
364
    std::string parentMsg;
365
    std::string childMsg;
366

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

374
    std::ostringstream oss;
375
    oss << "Warning: section " << childId << childMsg << " is the only child of "
376
        << "section: " << std::to_string(parentId) << parentMsg
377
        << "\nIt will be merged with the parent section";
378

379
    return errorMsg(0, ErrorLevel::WARNING, oss.str());
380
}
381

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

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

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

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

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

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

438
// LCOV_EXCL_STOP }
439

440
}  // namespace readers
441

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