From dd4372fd373baa2ae2efbee9f08a0b7aebf1b924 Mon Sep 17 00:00:00 2001
From: Dave Casper <dcasper@uci.edu>
Date: Fri, 21 Jan 2022 03:34:46 -0800
Subject: [PATCH] Attempt to fix barcode errors once and for all

---
 .../python/FaserISF_ServicesConfigNew.py      | 13 +--
 .../FaserISF_Services/src/FaserTruthSvc.cxx   | 21 ++++-
 .../FaserISF_Services/src/FaserTruthSvc.h     |  4 +
 .../python/FaserISF_HepMC_ToolsConfigNew.py   | 79 ++++++++++++-------
 4 files changed, 81 insertions(+), 36 deletions(-)

diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/python/FaserISF_ServicesConfigNew.py b/Simulation/ISF/ISF_Core/FaserISF_Services/python/FaserISF_ServicesConfigNew.py
index 7260d59f..e507545c 100644
--- a/Simulation/ISF/ISF_Core/FaserISF_Services/python/FaserISF_ServicesConfigNew.py
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/python/FaserISF_ServicesConfigNew.py
@@ -10,7 +10,8 @@ from AthenaConfiguration.ComponentFactory import CompFactory
 
 from BarcodeServices.BarcodeServicesConfigNew import MC15aPlusBarcodeSvcCfg
 from ISF_HepMC_Tools.ISF_HepMC_ToolsConfigNew import ParticleFinalStateFilterCfg, GenParticleInteractingFilterCfg
-from FaserISF_HepMC_Tools.FaserISF_HepMC_ToolsConfigNew import FaserTruthStrategyCfg, FaserDipoleTruthStrategyCfg
+# from FaserISF_HepMC_Tools.FaserISF_HepMC_ToolsConfigNew import FaserTruthStrategyCfg, FaserDipoleTruthStrategyCfg
+from FaserISF_HepMC_Tools.FaserISF_HepMC_ToolsConfigNew import TruthStrategyGroupCfg
 
 ISF__FaserTruthSvc, ISF__FaserGeoIDSvc, ISF__FaserInputConverter = CompFactory.getComps("ISF::FaserTruthSvc","ISF::FaserGeoIDSvc","ISF::FaserInputConverter")
 
@@ -60,10 +61,12 @@ def FaserTruthServiceCfg(ConfigFlags, name="FaserISF_TruthService", **kwargs):
     result = MC15aPlusBarcodeSvcCfg(ConfigFlags)
     kwargs.setdefault('BarcodeSvc', result.getService("Barcode_MC15aPlusBarcodeSvc") )
     
-    acc = FaserTruthStrategyCfg(ConfigFlags)
-    acc2= FaserDipoleTruthStrategyCfg(ConfigFlags)
-    kwargs.setdefault('TruthStrategies',[result.popToolsAndMerge(acc), result.popToolsAndMerge(acc2)])
-
+    # acc = FaserTruthStrategyCfg(ConfigFlags)
+    # acc2= FaserDipoleTruthStrategyCfg(ConfigFlags)
+    # kwargs.setdefault('TruthStrategies',[result.popToolsAndMerge(acc), result.popToolsAndMerge(acc2)])
+    acc = TruthStrategyGroupCfg(ConfigFlags)
+    kwargs.setdefault('TruthStrategies', [result.popToolsAndMerge(acc)])
+    
     kwargs.setdefault('SkipIfNoChildren', True)
     kwargs.setdefault('SkipIfNoParentBarcode', True)
 
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.cxx b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.cxx
index b1a64408..c4392954 100644
--- a/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.cxx
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.cxx
@@ -128,6 +128,8 @@ StatusCode ISF::FaserTruthSvc::finalize()
 StatusCode ISF::FaserTruthSvc::initializeTruthCollection()
 {
   ATH_CHECK( m_barcodeSvc->initializeBarcodes() );
+  m_incrementProcs.clear();
+  m_secondaryProcs.clear();
   return StatusCode::SUCCESS;
 }
 
@@ -264,13 +266,20 @@ void ISF::FaserTruthSvc::recordIncidentToMCTruth( ISF::IFaserTruthIncident& ti)
     newPrimBC = this->maxGeneratedParticleBarcode(ti.parentParticle()->parent_event())+1;
   }
   else {
+    if (m_incrementProcs.count(processCode) == 0)
+      m_incrementProcs[processCode] = 0;
+    m_incrementProcs[processCode]++;
     newPrimBC = m_barcodeSvc->incrementBarcode( parentBC, processCode);
   }
   if ( newPrimBC == Barcode::fUndefinedBarcode) {
+    for (auto pair : m_incrementProcs)
+    {
+      ATH_MSG_ALWAYS("Process code: " << pair.first << " : " << pair.second);
+    }
     if (m_ignoreUndefinedBarcodes) {
       ATH_MSG_WARNING("Unable to generate new Particle Barcode. Continuing due to 'IgnoreUndefinedBarcodes'==True");
     } else {
-      ATH_MSG_FATAL("Unable to generate new Particle Barcode in region " << ti.geoID() << ", at vertex (" <<  vtx->position().x() << ", " << vtx->position().y() << ", " << vtx->position().z() << "). Aborting");
+      ATH_MSG_FATAL("Unable to generate new Particle Barcode from " << parentBC << "( id= " << ti.parentPdgCode() << ", Ekin = " << ti.parentEkin()/Gaudi::Units::GeV << " GeV) with process code " << processCode << " in region " << ti.geoID() << ", at vertex (" <<  vtx->position().x() << ", " << vtx->position().y() << ", " << vtx->position().z() << "). Aborting");
       abort();
     }
   }
@@ -370,12 +379,20 @@ void ISF::FaserTruthSvc::recordIncidentToMCTruth( ISF::IFaserTruthIncident& ti)
       }
       else {
         // generate a new barcode for the child particle
+        if (m_secondaryProcs.count(processCode) == 0)
+          m_secondaryProcs[processCode] = 0;
+        m_secondaryProcs[processCode]++;
         Barcode::ParticleBarcode secBC = m_barcodeSvc->newSecondary( parentBC, processCode);
         if ( secBC == Barcode::fUndefinedBarcode) {
+          for (auto pair : m_secondaryProcs)
+          {
+            ATH_MSG_ALWAYS("Process code: " << pair.first << " : " << pair.second);
+          }
+
           if (m_ignoreUndefinedBarcodes)
             ATH_MSG_WARNING("Unable to generate new Secondary Particle Barcode. Continuing due to 'IgnoreUndefinedBarcodes'==True");
           else {
-            ATH_MSG_ERROR("Unable to generate new Secondary Particle Barcode. Aborting");
+            ATH_MSG_FATAL("Unable to generate new Secondary Particle Barcode from " << parentBC << " with process code " << processCode <<" in region " << ti.geoID() << ", at vertex (" <<  vtx->position().x() << ", " << vtx->position().y() << ", " << vtx->position().z() << "). Aborting");
             abort();
           }
         }
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.h b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.h
index d674d807..21b4d271 100644
--- a/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.h
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.h
@@ -126,6 +126,10 @@ namespace ISF {
 
     bool                                      m_quasiStableParticlesIncluded; //!< does this job simulate quasi-stable particles.
 
+    mutable std::map<int, int>                m_incrementProcs;
+    mutable std::map<int, int>                m_secondaryProcs;
+    
+
   };
 }
 
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigNew.py b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigNew.py
index 0f251682..4f739f6c 100644
--- a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigNew.py
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigNew.py
@@ -153,44 +153,65 @@ def FaserParticleGenericFilterCfg(ConfigFlags, name="ISF_FaserGenericFilter", **
 #  http://www-geant4.kek.jp/lxr/source//processes/hadronic/management/include/G4HadronicProcessType.hh#L46
 
 
-def FaserDipoleTruthStrategyCfg(ConfigFlags, name="ISF_FaserDipoleTruthStrategy", **kwargs):
-    result = ComponentAccumulator()
+def TruthStrategyGroupCfg(ConfigFlags, name="ISF_MCTruthStrategyGroupID", **kwargs):
 
     import ROOT, cppyy
     cppyy.load_library('FaserDetDescrDict')
     FaserRegion = ROOT.FaserDetDescr.FaserRegion
-    #
-    # Save truth in Dipole region
-    #
-    kwargs.setdefault('Regions', [FaserRegion.fFaserDipole,
-                                  FaserRegion.fFaserNeutrino,
+
+    result = ComponentAccumulator()
+    kwargs.setdefault("ParentMinEkin", 100.*MeV)
+    kwargs.setdefault("ChildMinEkin" , 100.*MeV)
+    kwargs.setdefault("VertexTypes", [3, 14, 15, 4, 5, 6, 7, 2, 12, 13])
+    kwargs.setdefault("VertexTypeRangeLow"  , 201)  # All kinds of decay processes
+    kwargs.setdefault("VertexTypeRangeHigh" , 298)  # ...
+    kwargs.setdefault("Regions", [FaserRegion.fFaserNeutrino,
+                                  FaserRegion.fFaserScintillator,
+                                  FaserRegion.fFaserTracker,
+                                  FaserRegion.fFaserCalorimeter,
                                   FaserRegion.fFaserCavern])
-    kwargs.setdefault('ParentMinEkin', 1000.0*MeV)
-    kwargs.setdefault('ChildMinEkin', 1000.0*MeV)
-    result.setPrivateTools(ISF__FaserTruthStrategy(name, **kwargs))
+    result.setPrivateTools(CompFactory.ISF.FaserTruthStrategy(name, **kwargs))
     return result
 
 
-def FaserTruthStrategyCfg(ConfigFlags, name="ISF_FaserTruthStrategy", **kwargs):
-    result = ComponentAccumulator()
+# def FaserDipoleTruthStrategyCfg(ConfigFlags, name="ISF_FaserDipoleTruthStrategy", **kwargs):
+#     result = ComponentAccumulator()
 
-    import ROOT, cppyy
-    cppyy.load_library('FaserDetDescrDict')
-    FaserRegion = ROOT.FaserDetDescr.FaserRegion
-    #
-    # Save truth in all regions except Dipole
-    #
-    kwargs.setdefault('Regions', [
-                                #   FaserRegion.fFaserNeutrino,
-                                  FaserRegion.fFaserScintillator,
-                                  FaserRegion.fFaserTracker])
-                                #   FaserRegion.fFaserDipole,
-                                #   FaserRegion.fFaserCalorimeter,
-                                #   FaserRegion.fFaserCavern])
-    # kwargs.setdefault('ParentMinEkin', 0.1*MeV)
-    # kwargs.setdefault('ChildMinEkin', 0.1*MeV)
-    result.setPrivateTools(ISF__FaserTruthStrategy(name, **kwargs))
-    return result
+#     import ROOT, cppyy
+#     cppyy.load_library('FaserDetDescrDict')
+#     FaserRegion = ROOT.FaserDetDescr.FaserRegion
+#     #
+#     # Save truth in Dipole region
+#     #
+#     kwargs.setdefault('Regions', [FaserRegion.fFaserDipole,
+#                                   FaserRegion.fFaserNeutrino,
+#                                   FaserRegion.fFaserCavern])
+#     kwargs.setdefault('ParentMinEkin', 1000.0*MeV)
+#     kwargs.setdefault('ChildMinEkin', 1000.0*MeV)
+#     result.setPrivateTools(ISF__FaserTruthStrategy(name, **kwargs))
+#     return result
+
+
+# def FaserTruthStrategyCfg(ConfigFlags, name="ISF_FaserTruthStrategy", **kwargs):
+#     result = ComponentAccumulator()
+
+#     import ROOT, cppyy
+#     cppyy.load_library('FaserDetDescrDict')
+#     FaserRegion = ROOT.FaserDetDescr.FaserRegion
+#     #
+#     # Save truth in all regions except Dipole
+#     #
+#     kwargs.setdefault('Regions', [
+#                                 #   FaserRegion.fFaserNeutrino,
+#                                   FaserRegion.fFaserScintillator,
+#                                   FaserRegion.fFaserTracker])
+#                                 #   FaserRegion.fFaserDipole,
+#                                 #   FaserRegion.fFaserCalorimeter,
+#                                 #   FaserRegion.fFaserCavern])
+#     # kwargs.setdefault('ParentMinEkin', 0.1*MeV)
+#     # kwargs.setdefault('ChildMinEkin', 0.1*MeV)
+#     result.setPrivateTools(ISF__FaserTruthStrategy(name, **kwargs))
+#     return result
 
 # def TruthStrategyGroupID_MC15Cfg(ConfigFlags, name="ISF_MCTruthStrategyGroupID_MC15", **kwargs):
 #     result = ComponentAccumulator()
-- 
GitLab