warning_handling.h
1 /* Copyright (c) 2013-2023, EPFL/Blue Brain Project
2  *
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #pragma once
6 
7 #include <iostream>
8 #include <memory>
9 #include <set>
10 #include <sstream> // std::ostringstream
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 #include <morphio/enums.h>
16 #include <morphio/types.h>
17 
18 
19 namespace morphio {
20 namespace details {
21 std::string errorLink(const std::string& uri,
22  long unsigned int lineNumber,
23  morphio::readers::ErrorLevel errorLevel);
24 } // namespace details
25 
26 
28  explicit WarningMessage(std::string uri_)
29  : uri(std::move(uri_)) {}
30  WarningMessage(const WarningMessage&) = default;
31  WarningMessage(WarningMessage&&) = delete;
32  WarningMessage& operator=(const WarningMessage&) = default;
33  WarningMessage& operator=(WarningMessage&&) = delete;
34  virtual std::string msg() const = 0;
35  virtual ~WarningMessage() = default;
36  virtual morphio::enums::Warning warning() const = 0;
37 
38  std::string uri;
39 };
40 
41 struct ZeroDiameter: public WarningMessage {
42  ZeroDiameter(std::string uri_, uint64_t lineNumber_)
43  : WarningMessage(std::move(uri_))
44  , lineNumber(lineNumber_) {}
45  morphio::enums::Warning warning() const final {
46  return Warning::ZERO_DIAMETER;
47  }
48  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
49  std::string msg() const final {
50  static const char* description = "Warning: zero diameter in file";
51  return "\n" + details::errorLink(uri, lineNumber, errorLevel) + description;
52  }
53 
54  uint64_t lineNumber;
55 };
56 
58  SectionTypeChanged(std::string uri_, uint64_t lineNumber_)
59  : WarningMessage(std::move(uri_))
60  , lineNumber(lineNumber_) {}
61  morphio::enums::Warning warning() const final {
62  return Warning::SECTION_TYPE_CHANGED;
63  }
64  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
65  std::string msg() const final {
66  static const char* description =
67  "Warning: Type changed within section, without bifurcation";
68  return "\n" + details::errorLink(uri, lineNumber, errorLevel) + description;
69  }
70 
71  uint64_t lineNumber;
72 };
73 
75  DisconnectedNeurite(std::string uri_, uint64_t lineNumber_)
76  : WarningMessage(std::move(uri_))
77  , lineNumber(lineNumber_) {}
78  Warning warning() const final {
79  return Warning::DISCONNECTED_NEURITE;
80  }
81  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
82  std::string msg() const final {
83  static const char* description =
84  "Warning: found a disconnected neurite.\n"
85  "Neurites are not supposed to have parentId: -1\n"
86  "(although this is normal if this neuron has no soma)";
87  return "\n" + details::errorLink(uri, lineNumber, errorLevel) + description;
88  }
89 
90  uint64_t lineNumber;
91 };
92 
93 struct NoSomaFound: public WarningMessage {
94  explicit NoSomaFound(std::string uri_)
95  : WarningMessage(std::move(uri_)) {}
96  Warning warning() const final {
97  return Warning::NO_SOMA_FOUND;
98  }
99  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
100  std::string msg() const final {
101  static const char* description = "Warning: no soma found in file";
102  return "\n" + details::errorLink(uri, 0, errorLevel) + description;
103  }
104 };
105 
107  explicit SomaNonConform(std::string uri_, std::string description_)
108  : WarningMessage(std::move(uri_))
109  , description(std::move(description_)) {}
110  Warning warning() const final {
111  return Warning::SOMA_NON_CONFORM;
112  }
113  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
114  std::string msg() const final {
115  return "\n" + details::errorLink(uri, 0, errorLevel) + description;
116  }
117  std::string description;
118 };
119 
121  explicit WrongRootPoint(std::string uri_, std::vector<unsigned int> lineNumbers_)
122  : WarningMessage(std::move(uri_))
123  , lineNumbers(std::move(lineNumbers_)) {}
124  Warning warning() const final {
125  return Warning::WRONG_ROOT_POINT;
126  }
127  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
128  std::string msg() const final {
129  std::ostringstream oss;
130  oss << "Warning: with a 3 points soma, neurites must be connected to the first soma point:";
131  for (const auto& lineNumber : lineNumbers) {
132  oss << "\n" + details::errorLink(uri, lineNumber, errorLevel);
133  }
134  return oss.str();
135  }
136  std::vector<unsigned int> lineNumbers;
137 };
138 
140  explicit AppendingEmptySection(std::string uri_, uint32_t sectionId_)
141  : WarningMessage(std::move(uri_))
142  , sectionId(sectionId_) {}
143  Warning warning() const final {
144  return Warning::APPENDING_EMPTY_SECTION;
145  }
146  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
147  std::string msg() const final {
148  static const char* description = "Warning: appending empty section with id: ";
149  return "\n" + details::errorLink(uri, 0, errorLevel) + description +
150  std::to_string(sectionId);
151  }
152  uint32_t sectionId;
153 };
154 
156  explicit WrongDuplicate(std::string uri_,
157  std::shared_ptr<morphio::mut::Section> current_,
158  std::shared_ptr<morphio::mut::Section> parent_)
159  : WarningMessage(std::move(uri_))
160  , current(std::move(current_))
161  , parent(std::move(parent_)) {}
162  std::string msg() const final;
163 
164  Warning warning() const final {
165  return Warning::WRONG_DUPLICATE;
166  }
167  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
168  std::shared_ptr<morphio::mut::Section> current;
169  std::shared_ptr<morphio::mut::Section> parent;
170 };
171 
172 struct OnlyChild: public WarningMessage {
173  explicit OnlyChild(std::string uri_, unsigned int parentId_, unsigned int childId_)
174  : WarningMessage(std::move(uri_))
175  , parentId(parentId_)
176  , childId(childId_) {}
177  Warning warning() const final {
178  return Warning::ONLY_CHILD;
179  }
180  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
181  std::string msg() const final {
182  std::ostringstream oss;
183  oss << "Warning: section " << childId << " is the only child of "
184  << "section: " << std::to_string(parentId)
185  << "\nIt will be merged with the parent section";
186 
187  return "\n" + details::errorLink(uri, 0, errorLevel) + oss.str();
188  }
189  unsigned int parentId;
190  unsigned int childId;
191 };
192 
193 struct WriteNoSoma: public WarningMessage {
194  WriteNoSoma()
195  : WarningMessage(std::string()) {}
196  Warning warning() const final {
197  return Warning::WRITE_NO_SOMA;
198  }
199  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
200  std::string msg() const final {
201  static const char* description = "Warning: writing file without a soma";
202  return "\n" + details::errorLink(uri, 0, errorLevel) + description;
203  }
204 };
205 
208  : WarningMessage(std::string()) {}
209  Warning warning() const final {
210  return Warning::WRITE_EMPTY_MORPHOLOGY;
211  }
212  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
213  std::string msg() const final {
214  static const char* description =
215  "Warning: Skipping an attempt to write an empty morphology.";
216  return "\n" + details::errorLink(uri, 0, errorLevel) + description;
217  }
218 };
219 
222  : WarningMessage(std::string()) {}
223  Warning warning() const final {
224  return Warning::WRITE_UNDEFINED_SOMA;
225  }
226  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
227  std::string msg() const final {
228  static const char* description = "Warning: writing soma set to SOMA_UNDEFINED";
229  return "\n" + details::errorLink(uri, 0, errorLevel) + description;
230  }
231 };
232 
235  : WarningMessage(std::string()) {}
236  Warning warning() const final {
237  return Warning::MITOCHONDRIA_WRITE_NOT_SUPPORTED;
238  }
239  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
240  std::string msg() const final {
241  static const char* description =
242  "Warning: this cell has mitochondria, they cannot be saved in "
243  " ASC or SWC format. Please use H5 if you want to save them.";
244  return "\n" + details::errorLink(uri, 0, errorLevel) + description;
245  }
246 };
247 
250  : WarningMessage(std::string()) {}
251  Warning warning() const final {
252  return Warning::SOMA_NON_CONTOUR;
253  }
254  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
255  std::string msg() const final {
256  static const char* description =
257  "Soma must be a contour for ASC and H5: see "
258  "https://github.com/BlueBrain/MorphIO/issues/457";
259  return "\n" + details::errorLink(uri, 0, errorLevel) + description;
260  }
261 };
262 
265  : WarningMessage(std::string()) {}
266  Warning warning() const final {
267  return Warning::SOMA_NON_CYLINDER_OR_POINT;
268  }
269  morphio::readers::ErrorLevel errorLevel = morphio::readers::ErrorLevel::WARNING;
270  std::string msg() const final {
271  static const char* description =
272  "Soma must be stacked cylinders or a point: see "
273  "https://github.com/BlueBrain/MorphIO/issues/457";
274  return "\n" + details::errorLink(uri, 0, errorLevel) + description;
275  }
276 };
277 
279 {
280  public:
281  WarningHandler() = default;
282  WarningHandler(WarningHandler&&) = default;
283  WarningHandler& operator=(const WarningHandler&) = default;
284  WarningHandler& operator=(WarningHandler&&) = default;
285  WarningHandler(WarningHandler&) = default;
286  virtual ~WarningHandler() = default;
287 
288  virtual void emit(std::shared_ptr<WarningMessage>) = 0;
289  void setIgnoredWarning(enums::Warning warning, bool ignore);
290  bool isIgnored(enums::Warning warning);
291 
292  // To maintain backwards compatibility, these exist, eventhough they aren't applicable to things
293  // like the `WarningHandlerCollector` since one can post-process the errors, and raise
294  // exceptions oneself.
295  virtual int getMaxWarningCount() const = 0;
296  virtual void setMaxWarningCount(int warningCount) = 0;
297  virtual bool getRaiseWarnings() const = 0;
298  virtual void setRaiseWarnings(bool raise) = 0;
299 
300  private:
301  std::set<enums::Warning> ignoredWarnings_;
302 };
303 
306 {
307  public:
308  int getMaxWarningCount() const final;
309  void setMaxWarningCount(int warningCount) final;
310  bool getRaiseWarnings() const final;
311  void setRaiseWarnings(bool raise) final;
312  void emit(std::shared_ptr<morphio::WarningMessage> wm) final;
313 
314  private:
315  uint32_t errorCount = 0;
316  int32_t maxWarningCount_ = 100;
317  bool raiseWarnings_ = false;
318 };
319 
322 {
323  public:
324  struct Emission {
325  Emission(bool wasMarkedIgnore_, std::shared_ptr<WarningMessage> warning_)
326  : wasMarkedIgnore(wasMarkedIgnore_)
327  , warning(std::move(warning_)) {}
328  bool wasMarkedIgnore = false;
329  std::shared_ptr<WarningMessage> warning;
330  };
331 
332  int getMaxWarningCount() const final;
333  void setMaxWarningCount(int warningCount) final;
334  bool getRaiseWarnings() const final;
335  void setRaiseWarnings(bool raise) final;
336  void emit(std::shared_ptr<WarningMessage> wm) final;
337  void reset();
338  std::vector<Emission> getAll() const;
339 
340  private:
341  std::vector<Emission> m;
342 };
343 
344 } // namespace morphio
morphio::OnlyChild
Definition: warning_handling.h:172
morphio::WarningHandlerCollector
This warning handler collects the warnings, which can be retrieved with getAll()
Definition: warning_handling.h:321
morphio::WriteUndefinedSoma
Definition: warning_handling.h:220
morphio::WarningHandlerPrinter
This warning handler prints warnings immediately to STDERR.
Definition: warning_handling.h:305
morphio::SomaNonCylinderOrPoint
Definition: warning_handling.h:263
morphio::enums::Warning
Warning
Definition: enums.h:30
morphio::NoSomaFound
Definition: warning_handling.h:93
morphio::SectionTypeChanged
Definition: warning_handling.h:57
morphio::WarningHandlerCollector::Emission
Definition: warning_handling.h:324
morphio::WriteNoSoma
Definition: warning_handling.h:193
morphio::SomaNonConform
Definition: warning_handling.h:106
morphio::ZeroDiameter
Definition: warning_handling.h:41
morphio::SomaNonContour
Definition: warning_handling.h:248
morphio::WriteEmptyMorphology
Definition: warning_handling.h:206
morphio::MitochondriaWriteNotSupported
Definition: warning_handling.h:233
morphio::WarningMessage
Definition: warning_handling.h:27
morphio::WarningHandler
Definition: warning_handling.h:278
morphio::DisconnectedNeurite
Definition: warning_handling.h:74
morphio::AppendingEmptySection
Definition: warning_handling.h:139
morphio::WrongDuplicate
Definition: warning_handling.h:155
morphio::WrongRootPoint
Definition: warning_handling.h:120