From 8ce1a0073b25caf9b375552e50f863932eb19bd7 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Tue, 13 Feb 2018 21:38:06 +0100
Subject: [PATCH] Fix problem in DDG4 MC truth handling

---
 DDCore/include/XML/DocumentHandler.h |  2 +
 DDCore/include/XML/XML.h             |  1 -
 DDCore/include/XML/XMLElements.h     | 53 ++++++++++++++++++-
 DDCore/src/XML/DocumentHandler.cpp   | 22 ++++++--
 DDCore/src/XML/XMLElements.cpp       | 16 +++++-
 DDCore/src/XML/tinyxmlparser_inl.h   |  9 ++--
 DDG4/include/DDG4/Geant4Particle.h   |  1 +
 DDG4/src/Geant4Particle.cpp          | 68 +++++++++++++++++++++++--
 DDG4/src/Geant4ParticleHandler.cpp   | 76 ++++++++++++++++++++++------
 9 files changed, 214 insertions(+), 34 deletions(-)

diff --git a/DDCore/include/XML/DocumentHandler.h b/DDCore/include/XML/DocumentHandler.h
index ecc5a209c..bb52b1c7a 100644
--- a/DDCore/include/XML/DocumentHandler.h
+++ b/DDCore/include/XML/DocumentHandler.h
@@ -63,6 +63,8 @@ namespace dd4hep {
       /// Write xml document to output file (stdout if file name empty)
       virtual int output(Document doc, const std::string& fname) const;
 
+      /// Set minimum print level
+      static int setMinimumPrintLevel(int level);
       /// System ID of a given XML entity
       static std::string system_path(Handle_t base);
       /// System ID of a new XML entity in the same directory as base
diff --git a/DDCore/include/XML/XML.h b/DDCore/include/XML/XML.h
index 64cba6293..d81692608 100644
--- a/DDCore/include/XML/XML.h
+++ b/DDCore/include/XML/XML.h
@@ -33,7 +33,6 @@ typedef dd4hep::xml::DetElement      xml_det_t;
 typedef dd4hep::xml::Component       xml_comp_t;
 typedef dd4hep::xml::ChildValue      xml_val_t;
 typedef dd4hep::xml::Document        xml_doc_t;
-typedef dd4hep::xml::Document        xml_doc_t;
 typedef dd4hep::xml::DocumentHolder  xml_doc_holder_t;
 typedef dd4hep::xml::DocumentHandler xml_handler_t;
 
diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h
index d62cfe03f..c88a987dc 100644
--- a/DDCore/include/XML/XMLElements.h
+++ b/DDCore/include/XML/XMLElements.h
@@ -132,8 +132,6 @@ namespace dd4hep {
     void _toDictionary(const XmlChar* name, float  value);
     /// Helper function to populate the evaluator dictionary  \ingroup DD4HEP_XML
     void _toDictionary(const XmlChar* name, double value);
-    /// Helper function to lookup environment from the expression evaluator
-    std::string getEnviron(const std::string& env);
 
     /// Conversion function from raw unicode string to bool  \ingroup DD4HEP_XML
     bool _toBool(const XmlChar* value);
@@ -146,6 +144,11 @@ namespace dd4hep {
     /// Conversion function from raw unicode string to double  \ingroup DD4HEP_XML
     double _toDouble(const XmlChar* value);
 
+    /// Helper function to lookup environment from the expression evaluator
+    std::string getEnviron(const std::string& env);
+    /// Enable/disable environment resolution when parsing strings
+    bool enableEnvironResolution(bool new_value);
+    
     /// Helper class to encapsulate a unicode string.
     /**
      *  Simple conversion from ascii strings to unicode strings.
@@ -448,6 +451,8 @@ namespace dd4hep {
       void setAttrs(Handle_t e) const;
       /// Access typed attribute value by it's unicode name
       template <class T> T attr(const XmlChar* name) const;
+      /// Access typed attribute value by it's unicode name. If not existing returns default value
+      template <class T> T attr(const XmlChar* name, T default_value) const;
 
       /// Generic attribute setter with unicode value
       Attribute setAttr(const XmlChar* t, const XmlChar* v) const;
@@ -472,6 +477,11 @@ namespace dd4hep {
       template <class T> T attr(const char* name) const {
         return this->attr<T>(Strng_t(name));
       }
+      /// Access typed attribute value by it's name
+      template <class T> T attr(const char* name, const T& default_value) const {
+        Strng_t tag(name);
+        return this->hasAttr(tag) ? this->attr<T>(tag) : default_value;
+      }
       /// Generic attribute setter with text value
       Attribute setAttr(const XmlChar* t, const char* v) const;
 #endif
@@ -537,6 +547,37 @@ namespace dd4hep {
     template <> INLINE std::string Handle_t::attr<std::string>(const XmlChar* tag_value) const {
       return _toString(attr_value(tag_value));
     }
+
+    template <> INLINE bool Handle_t::attr<bool>(const XmlChar* tag_value, bool default_value) const {
+      Attribute a = attr_nothrow(tag_value);
+      return a ? _toBool(attr_value(a)) : default_value;
+    }
+
+    template <> INLINE int Handle_t::attr<int>(const XmlChar* tag_value, int default_value) const {
+      Attribute a = attr_nothrow(tag_value);
+      return a ? _toInt(attr_value(a)) : default_value;
+    }
+    
+    template <> INLINE long Handle_t::attr<long>(const XmlChar* tag_value, long default_value) const {
+      Attribute a = attr_nothrow(tag_value);
+      return a ? _toLong(attr_value(a)) : default_value;
+    }
+
+    template <> INLINE float Handle_t::attr<float>(const XmlChar* tag_value, float default_value) const {
+      Attribute a = attr_nothrow(tag_value);
+      return a ? _toFloat(attr_value(a)) : default_value;
+    }
+
+    template <> INLINE double Handle_t::attr<double>(const XmlChar* tag_value, double default_value) const {
+      Attribute a = attr_nothrow(tag_value);
+      return a ? _toDouble(attr_value(a)) : default_value;
+    }
+
+    template <> INLINE std::string Handle_t::attr<std::string>(const XmlChar* tag_value, std::string default_value) const {
+      Attribute a = attr_nothrow(tag_value);
+      return a ? _toString(attr_value(a)) : default_value;
+    }
+
 #if 0
     template<> INLINE bool Handle_t::attr<bool>(const Attribute tag_value) const
     { return _toBool(attr_value(tag_value));}
@@ -778,11 +819,19 @@ namespace dd4hep {
       template <class T> T attr(const XmlChar* tag_value) const {
         return m_element.attr<T>(tag_value);
       }
+      /// Access attribute with implicit return type conversion
+      template <class T> T attr(const XmlChar* tag_value, T default_value) const {
+        return m_element.attr<T>(tag_value, default_value);
+      }
 #ifndef __TIXML__
       /// Access typed attribute value by it's name
       template <class T> T attr(const char* name) const {
         return this->attr<T>(Strng_t(name));
       }
+      /// Access typed attribute value by it's name
+      template <class T> T attr(const char* name, T default_value) const {
+        return this->attr<T>(Strng_t(name), default_value);
+      }
 #endif
       /// Access attribute name (throws exception if not present)
       const XmlChar* attr_name(const Attribute a) const {
diff --git a/DDCore/src/XML/DocumentHandler.cpp b/DDCore/src/XML/DocumentHandler.cpp
index 3cd2264ae..3d42e7a95 100644
--- a/DDCore/src/XML/DocumentHandler.cpp
+++ b/DDCore/src/XML/DocumentHandler.cpp
@@ -40,6 +40,7 @@ namespace {
     }
     return fn;
   }
+  int s_minPrintLevel = INFO;
 }
 
 #ifndef __TIXML__
@@ -177,8 +178,10 @@ namespace dd4hep {
               string baseURI(_toString(id->getBaseURI()));
               string schema(_toString(id->getSchemaLocation()));
               string ns(_toString(id->getNameSpace()));
-              printout(INFO,"XercesC","+++ Resolved URI: sysID:%s uri:%s ns:%s schema:%s",
-                       systemID.c_str(), baseURI.c_str(), ns.c_str(), schema.c_str());
+              if ( s_minPrintLevel <= INFO ) {
+                printout(INFO,"XercesC","+++ Resolved URI: sysID:%s uri:%s ns:%s schema:%s",
+                         systemID.c_str(), baseURI.c_str(), ns.c_str(), schema.c_str());
+              }
 #endif
               return new MemBufInputSource(input,buf.length(),systemID.c_str(),true);
             }
@@ -481,7 +484,7 @@ Document DocumentHandler::load(const std::string& fname, UriReader* reader) cons
     printout(WARNING,"DocumentHandler","+++ Loading document URI: %s %s",
              fname.c_str(),"[URI Resolution is not supported by TiXML]");
   }
-  else  {
+  else if ( s_minPrintLevel <= INFO ) {
     printout(INFO,"DocumentHandler","+++ Loading document URI: %s [Resolved:'%s']",
              fname.c_str(),clean.c_str());
   }
@@ -506,8 +509,10 @@ Document DocumentHandler::load(const std::string& fname, UriReader* reader) cons
     printout(ERROR,"DocumentHandler","+++ Exception (TinyXML): parse(path):%s",e.what());
   }
   if ( result ) {
-    printout(INFO,"DocumentHandler","+++ Document %s succesfully parsed with TinyXML .....",
-             fname.c_str());
+    if ( s_minPrintLevel <= INFO ) {
+      printout(INFO,"DocumentHandler","+++ Document %s succesfully parsed with TinyXML .....",
+               fname.c_str());
+    }
     return (XmlDocument*)doc;
   }
   delete doc;
@@ -609,6 +614,13 @@ DocumentHandler::DocumentHandler() {}
 /// Default destructor of a document handler using TiXml
 DocumentHandler::~DocumentHandler() {}
 
+/// Set minimum print level
+int DocumentHandler::setMinimumPrintLevel(int level)    {
+  int tmp = s_minPrintLevel;
+  s_minPrintLevel = level;
+  return tmp;
+}
+
 /// Default comment string
 std::string DocumentHandler::defaultComment()  {
   const char comment[] = "\n"
diff --git a/DDCore/src/XML/XMLElements.cpp b/DDCore/src/XML/XMLElements.cpp
index 821a4a430..5a356494a 100644
--- a/DDCore/src/XML/XMLElements.cpp
+++ b/DDCore/src/XML/XMLElements.cpp
@@ -33,10 +33,15 @@ namespace dd4hep {
 }
 // Static storage
 namespace {
+  bool s_resolve_environment = true;
+
   XmlTools::Evaluator& eval(dd4hep::evaluator());
   string _checkEnviron(const string& env)  {
-    string r = getEnviron(env);
-    return r.empty() ? env : r;
+    if ( s_resolve_environment )  {
+      string r = getEnviron(env);
+      return r.empty() ? env : r;
+    }
+    return env;
   }
 }
 
@@ -424,6 +429,13 @@ string dd4hep::xml::getEnviron(const string& env)   {
   }
 }
 
+/// Enable/disable environment resolution when parsing strings
+bool dd4hep::xml::enableEnvironResolution(bool new_value)   {
+  bool tmp = s_resolve_environment;
+  s_resolve_environment = new_value;
+  return tmp;
+}
+
 template <typename B>
 static inline string i_add(const string& a, B b) {
   string r = a;
diff --git a/DDCore/src/XML/tinyxmlparser_inl.h b/DDCore/src/XML/tinyxmlparser_inl.h
index 9a0ade46b..436d44cb1 100644
--- a/DDCore/src/XML/tinyxmlparser_inl.h
+++ b/DDCore/src/XML/tinyxmlparser_inl.h
@@ -119,20 +119,23 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng
     --output;
     *output = (char)((input | BYTE_MARK) & BYTE_MASK);
     input >>= 6;
-    [[fallthrough]];
+    // fall through  [[fallthrough]];
   case 3:
     --output;
     *output = (char)((input | BYTE_MARK) & BYTE_MASK);
     input >>= 6;
-    [[fallthrough]];
+    // fall through  [[fallthrough]];
   case 2:
     --output;
     *output = (char)((input | BYTE_MARK) & BYTE_MASK);
     input >>= 6;
-    [[fallthrough]];
+    // fall through  [[fallthrough]];
   case 1:
     --output;
     *output = (char)(input | FIRST_BYTE_MARK[*length]);
+    // fall through  [[fallthrough]];
+  default:
+    break;
   }
 }
 
diff --git a/DDG4/include/DDG4/Geant4Particle.h b/DDG4/include/DDG4/Geant4Particle.h
index 9cce168b6..10ec3dd3c 100644
--- a/DDG4/include/DDG4/Geant4Particle.h
+++ b/DDG4/include/DDG4/Geant4Particle.h
@@ -226,6 +226,7 @@ namespace dd4hep {
       void dumpWithVertex(int level, const std::string& src, const char* tag) const;
       void dumpWithMomentum(int level, const std::string& src, const char* tag) const;
       void dumpWithMomentumAndVertex(int level, const std::string& src, const char* tag) const;
+      static void header4(int level, const std::string& src, const char* tag);
       void dump4(int level, const std::string& src, const char* tag) const;
 
       /// Handlers
diff --git a/DDG4/src/Geant4Particle.cpp b/DDG4/src/Geant4Particle.cpp
index 89aa18c13..61aa060e3 100644
--- a/DDG4/src/Geant4Particle.cpp
+++ b/DDG4/src/Geant4Particle.cpp
@@ -24,6 +24,7 @@
 #include "G4ChargedGeantino.hh"
 #include "G4Geantino.hh"
 
+#include <sstream>
 #include <iostream>
 
 using namespace dd4hep;
@@ -304,19 +305,75 @@ void Geant4ParticleHandle::dumpWithMomentumAndVertex(int level, const std::strin
            text);
 }
 
+void Geant4ParticleHandle::header4(int level, const std::string& src, const char* tag)  {
+  printout((dd4hep::PrintLevel)level,src,
+           "+++ %s %10s/%-7s %12s/%-10s %6s/%-6s %4s %4s "
+           "%-4s %-3s %-3s %-10s "
+           "%-5s %-6s %-3s %-3s  %-20s %s",
+           tag,"ID", "G4-ID", "Part-Name","PDG", "Parent","G4-ID", "#Par","#Dau",
+           "Prim","Sec",">E","Energy",
+           "EMPTY","STAB","DEC","DOC", 
+           "Process", "Processing Flags");
+}
+
 void Geant4ParticleHandle::dump4(int level, const std::string& src, const char* tag) const  {
   Geant4ParticleHandle p(*this);
-  char equiv[32];
+  //char equiv[32];
   PropertyMask mask(p->reason);
   PropertyMask status(p->status);
   std::string proc_name = p.processName();
   std::string proc_type = p.processTypeName();
+  std::string proc = '['+proc_name+(p->process ? "/" : "")+proc_type+']';
   int parent_id = p->parents.empty() ? -1 : *(p->parents.begin());
 
-  equiv[0] = 0;
-  if ( p->parents.end() == p->parents.find(p->g4Parent) )  {
-    ::snprintf(equiv,sizeof(equiv),"/%d",p->g4Parent);
-  }
+  //equiv[0] = 0;
+  //if ( p->parents.end() == p->parents.find(p->g4Parent) )  {
+  //  ::snprintf(equiv,sizeof(equiv),"/%d",p->g4Parent);
+  //}
+  std::stringstream str;
+  str << "Parents: ";
+  for( const auto i : p->parents )
+    str << i << " ";
+  str << " Daughters: ";
+  for( const auto i : p->daughters )
+    str << i << " ";
+  printout((dd4hep::PrintLevel)level,src,
+           "+++ %s ID:%7d/%-7d %12s/%-10d %6d/%-6d %4d %4d %-4s %-3s %-3s %+.3e  "
+           "%-5s %-4s %-3s %-3s  %-20s %c%c%c%c -- %c%c%c%c%c%c%c%c%c  %s",
+           tag,
+           p->id,p->originalG4ID,
+           p.particleName().c_str(),
+           p->pdgID,
+           parent_id,p->g4Parent,
+           p.numParent(),
+           int(p->daughters.size()),
+           yes_no(mask.isSet(G4PARTICLE_PRIMARY)),
+           yes_no(mask.isSet(G4PARTICLE_HAS_SECONDARIES)),
+           yes_no(mask.isSet(G4PARTICLE_ABOVE_ENERGY_THRESHOLD)),
+           p.energy(),
+           //
+           yes_no(mask.isSet(G4PARTICLE_CREATED_CALORIMETER_HIT)),
+           yes_no(mask.isSet(G4PARTICLE_CREATED_TRACKER_HIT)),
+           yes_no(mask.isSet(G4PARTICLE_KEEP_PROCESS)),
+           mask.isSet(G4PARTICLE_KEEP_PARENT) ? "YES" : "",
+           proc.c_str(),
+           // 13 flags in total
+           status.isSet(G4PARTICLE_GEN_EMPTY) ? 'E' : '.',               // 1
+           status.isSet(G4PARTICLE_GEN_STABLE) ? 'S' : '.',
+           status.isSet(G4PARTICLE_GEN_DECAYED) ? 'D' : '.',
+           status.isSet(G4PARTICLE_GEN_DOCUMENTATION) ? 'd' : '.',
+           status.isSet(G4PARTICLE_GEN_BEAM) ? 'B' : '.',                // 5
+           status.isSet(G4PARTICLE_GEN_OTHER) ? 'o' : '.',
+           status.isSet(G4PARTICLE_SIM_CREATED) ? 's' : '.',
+           status.isSet(G4PARTICLE_SIM_BACKSCATTER) ? 'b' : '.',
+           status.isSet(G4PARTICLE_SIM_PARENT_RADIATED) ? 'v' : '.',
+           status.isSet(G4PARTICLE_SIM_DECAY_TRACKER) ? 't' : '.',       // 10
+           status.isSet(G4PARTICLE_SIM_DECAY_CALO) ? 'c' : '.',
+           status.isSet(G4PARTICLE_SIM_LEFT_DETECTOR) ? 'l' : '.',
+           status.isSet(G4PARTICLE_SIM_STOPPED) ? 's' : '.',
+           str.str().c_str()
+           );
+#if 0
   printout((dd4hep::PrintLevel)level,src,
            "+++ %s ID:%7d %12s %6d%-7s %7s %3s %5d %3s %+.3e  %-4s %-7s %-3s %-3s %2d  [%s%s%s] %c%c%c%c -- %c%c%c%c%c%c%c",
            tag,
@@ -351,6 +408,7 @@ void Geant4ParticleHandle::dump4(int level, const std::string& src, const char*
            status.isSet(G4PARTICLE_SIM_LEFT_DETECTOR) ? 'l' : '.',
            status.isSet(G4PARTICLE_SIM_STOPPED) ? 's' : '.'
            );
+#endif
 }
 
 /// Default destructor
diff --git a/DDG4/src/Geant4ParticleHandler.cpp b/DDG4/src/Geant4ParticleHandler.cpp
index 6cad82846..f12a745e3 100644
--- a/DDG4/src/Geant4ParticleHandler.cpp
+++ b/DDG4/src/Geant4ParticleHandler.cpp
@@ -306,7 +306,6 @@ void Geant4ParticleHandler::end(const G4Track* track)   {
   ph->vey = p.y();
   ph->vez = p.z();
 
-
   // Set the simulator status bits
   PropertyMask simStatus(m_currTrack.status);
 
@@ -388,8 +387,10 @@ void Geant4ParticleHandler::beginEvent(const G4Event* event)  {
 
 /// Debugging: Dump Geant4 particle map
 void Geant4ParticleHandler::dumpMap(const char* tag)  const  {
+  const string& n = name();
+  Geant4ParticleHandle::header4(INFO,n,tag);
   for(ParticleMap::const_iterator iend=m_particleMap.end(), i=m_particleMap.begin(); i!=iend; ++i)  {
-    Geant4ParticleHandle((*i).second).dump4(INFO,name(),tag);
+    Geant4ParticleHandle((*i).second).dump4(INFO,n,tag);
   }
 }
 
@@ -398,14 +399,14 @@ void Geant4ParticleHandler::endEvent(const G4Event* event)  {
   int count = 0;
   int level = outputLevel();
   do {
-    if ( level <= VERBOSE ) dumpMap("Particle");
+    if ( level <= VERBOSE ) dumpMap("Particle  ");
     debug("+++ Iteration:%d Tracks:%d Equivalents:%d",++count,m_particleMap.size(),m_equivalentTracks.size());
   } while( recombineParents() > 0 );
 
-  if ( level <= VERBOSE ) dumpMap("Recombined");
+  if ( level <= VERBOSE ) dumpMap(  "Recombined");
   // Rebase the simulated tracks, so that they fit to the generator particles
   rebaseSimulatedTracks(0);
-  if ( level <= VERBOSE ) dumpMap("Rebased");
+  if ( level <= VERBOSE ) dumpMap(  "Rebased   ");
   // Consistency check....
   checkConsistency();
   /// Call the user particle handler
@@ -466,8 +467,8 @@ void Geant4ParticleHandler::rebaseSimulatedTracks(int )   {
     }
     TrackEquivalents::mapped_type equiv = (*ie).second;
     if ( ipar != m_particleMap.end() )   {
-      equivalents[(*ie).first] = (*ipar).second->id;  // requires (1) !
       Geant4ParticleHandle p = (*ipar).second;
+      equivalents[(*ie).first] = p->id;  // requires (1) to be filled properly!
       const G4ParticleDefinition* def = p.definition();
       int pdg = int(fabs(def->GetPDGEncoding())+0.1);
       if ( pdg != 0 && pdg<36 && !(pdg > 10 && pdg < 17) && pdg != 22 )  {
@@ -486,22 +487,65 @@ void Geant4ParticleHandler::rebaseSimulatedTracks(int )   {
   // (3) Compute the particle's parents and daughters.
   //     Replace the original Geant4 track with the
   //     equivalent particle still present in the record.
-  for(iend=m_particleMap.end(), i=m_particleMap.begin(); i!=iend; ++i)  {
+  // Note:
+  //     We rely here on the ordering of the particles accoding to their
+  //     Processing by Geant4 to establish mother daughter relationships.
+  //     == > use finalParticles map and NOT m_particleMap.
+  int equiv_id = -1;
+  for(iend=finalParticles.end(), i=finalParticles.begin(); i!=iend; ++i)  {
     Particle* p = (*i).second;
     if ( p->g4Parent > 0 )  {
-      int equiv_id = equivalents[p->g4Parent];
-      if ( (ipar=finalParticles.find(equiv_id)) != finalParticles.end() )  {
-        Particle* q = (*ipar).second;
-        q->daughters.insert(p->id);
-        p->parents.insert(q->id);
+      TrackEquivalents::iterator iequ = equivalents.find(p->g4Parent);
+      if ( iequ != equivalents.end() )  {
+        equiv_id = (*iequ).second;//equivalents[p->g4Parent];
+        if ( (ipar=finalParticles.find(equiv_id)) != finalParticles.end() )  {
+          Particle* q = (*ipar).second;
+          bool      prim = (p->reason&G4PARTICLE_PRIMARY) == G4PARTICLE_PRIMARY;
+          // We assume that the mother daughter relationship
+          // is filled by the event readers!
+          if ( !prim )  {
+            p->parents.insert(q->id);
+          }
+          if ( !p->parents.empty() )  {
+            int parent_id = (*p->parents.begin());
+            if ( parent_id == q->id )
+              q->daughters.insert(p->id);
+            else if ( !prim )
+              error("+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->id);
+          }
+          else   {
+            error("+++ Inconsistency in parent relashionship: %d NO parent!", p->id);
+          }
+          continue;
+        }
       }
-      else   {
-        error("+++ Inconsistency in particle record: Geant4 parent %d "
-              "of particle %d (equiv:%d) not in record!",
-              p->g4Parent,p->id,equiv_id);
+      error("+++ Inconsistency in particle record: Geant4 parent %d "
+            "of particle %d not in record of final particles!",
+            p->g4Parent,p->id);
+    }
+  }
+#if 0
+  for(iend=finalParticles.end(), i=finalParticles.begin(); i!=iend; ++i)  {
+    Particle* p = (*i).second;
+    if ( p->g4Parent > 0 )  {
+      int parent_id = (*p->parents.begin());
+      if ( (ipar=finalParticles.find(parent_id)) != finalParticles.end() )  {
+        Particle* q = (*ipar).second;
+        // Generator particles have a proper history.
+        // We only deal with particles, which are not of MC origin.
+        //p->parents.insert(q->id);
+        if ( parent_id == q->id )
+          q->daughters.insert(p->id);
+        else
+          error("+++ Inconsistency in equivalent record! Parent: %d Daughter:%d",q->id, p->id);
+        continue;
       }
+      error("+++ Inconsistency in particle record: Geant4 parent %d "
+            "of particle %d not in record of final particles!",
+            p->g4Parent,p->id);
     }
   }
+#endif
   m_equivalentTracks = equivalents;
   m_particleMap = finalParticles;
 }
-- 
GitLab