From a365e6ef1935335fe068c4790242545f42c54999 Mon Sep 17 00:00:00 2001
From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com>
Date: Wed, 16 Mar 2022 09:43:36 +0100
Subject: [PATCH] Better `paint` errors. (#1846)

Since we have support for ACC loading, the errors thrown by `paint` are no longer
sufficiently informative. Even before that it was already hard to correlate source
and locus of painting errors.

Example
```
$> python3 main.C51A.py
Traceback (most recent call last):
  File "main.C51A.py", line 33, in <module>
    cell = A.cable_cell(morph, labels, decor)
RuntimeError: cable_cell: cable (cable 6 0 1) overpaints
```
This adds more details to the error message
```
$> python3 main.C51A.py
Traceback (most recent call last):
  File "main.C51A.py", line 33, in <module>
    cell = A.cable_cell(morph, labels, decor)
RuntimeError: cable_cell: Setting property 'ion-reversal-potential' on region '(region "soma_group")' overpaints at '(cable 6 0 1)'
```
---
 arbor/cable_cell.cpp | 39 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/arbor/cable_cell.cpp b/arbor/cable_cell.cpp
index 1432b6a1..704b28cc 100644
--- a/arbor/cable_cell.cpp
+++ b/arbor/cable_cell.cpp
@@ -27,6 +27,42 @@ template <typename T> struct constant_type {
     template <typename> using type = T;
 };
 
+// Helper for debugging: print outermost DSL constructor
+std::string show(const paintable& item) {
+    std::stringstream os;
+    std::visit(
+        [&] (const auto& p) {
+            using T = std::decay_t<decltype(p)>;
+            if constexpr (std::is_same_v<init_membrane_potential, T>) {
+                os << "init-membrane-potential";
+            }
+            else if constexpr (std::is_same_v<axial_resistivity, T>) {
+                os << "axial-resistivity";
+            }
+            else if constexpr (std::is_same_v<temperature_K, T>) {
+                os << "temperature-kelvin";
+            }
+            else if constexpr (std::is_same_v<membrane_capacitance, T>) {
+                os << "membrane-capacitance";
+            }
+            else if constexpr (std::is_same_v<init_int_concentration, T>) {
+                os << "ion-internal-concentration";
+            }
+            else if constexpr (std::is_same_v<init_ext_concentration, T>) {
+                os << "ion-external-concentration";
+            }
+            else if constexpr (std::is_same_v<init_reversal_potential, T>) {
+                os << "ion-reversal-potential";
+            }
+            else if constexpr (std::is_same_v<density, T>) {
+                os << "density:" << p.mech.name();
+            }
+        },
+        item);
+    return os.str();
+}
+
+
 struct cable_cell_impl {
     using value_type = cable_cell::value_type;
     using index_type = cable_cell::index_type;
@@ -128,7 +164,8 @@ struct cable_cell_impl {
             if (c.prox_pos==c.dist_pos) continue;
 
             if (!mm.insert(c, prop)) {
-                throw cable_cell_error(util::pprintf("cable {} overpaints", c));
+                std::stringstream rg; rg << reg;
+                throw cable_cell_error(util::pprintf("Setting property '{}' on region '{}' overpaints at '{}'", show(prop), rg.str(), c));
             }
         }
     }
-- 
GitLab