From db51dba6904b8ee4850cebdf23b1e56a6fb70dd1 Mon Sep 17 00:00:00 2001
From: "lintao@ihep.ac.cn" <lintao@ihep.ac.cn>
Date: Wed, 26 Mar 2025 09:52:50 +0000
Subject: [PATCH] WIP: improve the MCTruth handling in detector simulation

---
 Detector/DetCRD/scripts/TDR_o1_v01/sim.py     |  4 +++
 .../src/Edm4hepWriterAnaElemTool.cpp          | 35 ++++++++++++++++---
 .../DetSimAna/src/Edm4hepWriterAnaElemTool.h  |  7 ++--
 3 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/Detector/DetCRD/scripts/TDR_o1_v01/sim.py b/Detector/DetCRD/scripts/TDR_o1_v01/sim.py
index 8bcb3eeb..89159f9d 100644
--- a/Detector/DetCRD/scripts/TDR_o1_v01/sim.py
+++ b/Detector/DetCRD/scripts/TDR_o1_v01/sim.py
@@ -93,6 +93,10 @@ detsimalg.AnaElems = [
 ]
 detsimalg.RootDetElem = "WorldDetElemTool"
 
+from Configurables import Edm4hepWriterAnaElemTool
+detsim_anatool = Edm4hepWriterAnaElemTool("Edm4hepWriterAnaElemTool")
+detsim_anatool.IsTrk2Primary = False # True: primary; False: ancestor
+
 from Configurables import TimeProjectionChamberSensDetTool
 tpc_sensdettool = TimeProjectionChamberSensDetTool("TimeProjectionChamberSensDetTool")
 tpc_sensdettool.TypeOption = 1
diff --git a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp
index 5f20cc77..3139e2ef 100644
--- a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp
+++ b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp
@@ -282,7 +282,7 @@ Edm4hepWriterAnaElemTool::EndOfEventAction(const G4Event* anEvent) {
                     
                     int pritrkid = m_track2primary[trackID];
                     if (pritrkid <= 0) {
-                        error() << "Failed to find the primary track for trackID #" << trackID << endmsg;
+                        error() << "Failed to find the primary (or ancestor) track for trackID #" << trackID << endmsg;
                         pritrkid = 1;
                     }
 
@@ -363,6 +363,16 @@ Edm4hepWriterAnaElemTool::PreUserTrackingAction(const G4Track* track) {
     int curparid = track->GetParentID();
     int pritrkid = curparid;
 
+    // if it is ancestor mode, then we need to check whether current track is associated
+    // with MCParticle or not.
+    // If it is associated, then we will record this info.
+    if (not m_istrk2primary.value()) {
+        auto trackinfo = dynamic_cast<CommonUserTrackInfo*>(track->GetUserInformation());
+        if (trackinfo) {
+            curparid = 0; // force to zero, so that it will be set as primary
+        }
+    }
+    
     // try to find the primary track id from the parent track id.
     if (curparid) {
         auto it = m_track2primary.find(curparid);
@@ -429,6 +439,11 @@ Edm4hepWriterAnaElemTool::PostUserTrackingAction(const G4Track* track) {
         auto trackinfo = dynamic_cast<CommonUserTrackInfo*>(track->GetUserInformation());
         if (trackinfo) {
             idxedm4hep = trackinfo->idxEdm4hep();
+            // if the current track is a secondary track and it is associated
+            // with a MCParticle, we need to update the event level user info
+            if (idxedm4hep) {
+                m_userinfo->setIdxG4Track2Edm4hep(curtrkid, idxedm4hep);
+            }
         }
     }
     
@@ -475,6 +490,7 @@ Edm4hepWriterAnaElemTool::PostUserTrackingAction(const G4Track* track) {
 
     // flags
     bool is_decay = false;
+    G4ThreeVector decay_pos; // only valid when is decay
 
     size_t nSeco = secondaries->size();
     for (size_t i = 0; i < nSeco; ++i) {
@@ -506,7 +522,9 @@ Edm4hepWriterAnaElemTool::PostUserTrackingAction(const G4Track* track) {
                 << " momentum: " << sectrk->GetMomentum() // 
                 << endmsg;
 
-        if (creatorProcess==proc_decay) is_decay = true;
+        if (creatorProcess==proc_decay) {
+            is_decay = true;
+        }
 
         // create secondaries in MC particles
         // todo: convert the const collection to non-const
@@ -524,6 +542,11 @@ Edm4hepWriterAnaElemTool::PostUserTrackingAction(const G4Track* track) {
         double y=sec_init_pos.y()/CLHEP::mm;
         double z=sec_init_pos.z()/CLHEP::mm;
 
+        // if the particle decay, record the position
+        if (is_decay) {
+            decay_pos = sec_init_pos;
+        }
+
         const G4ThreeVector& sec_init_mom = sectrk->GetMomentum();
         double px=sec_init_mom.x()/CLHEP::GeV;
         double py=sec_init_mom.y()/CLHEP::GeV;
@@ -548,8 +571,12 @@ Edm4hepWriterAnaElemTool::PostUserTrackingAction(const G4Track* track) {
 
     // now update
     if (is_decay) {
-        primary_particle.setDecayedInTracker(is_decay);
-        primary_particle.setDecayedInCalorimeter(is_decay);
+        bool is_in_tracker = decay_pos.perp() < R && std::fabs(decay_pos.z()) < Z;
+        if (is_in_tracker) {
+            primary_particle.setDecayedInTracker(is_decay);
+        } else {
+            primary_particle.setDecayedInCalorimeter(is_decay);
+        }
     }
 
 }
diff --git a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.h b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.h
index 7b9b6e71..b386b122 100644
--- a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.h
+++ b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.h
@@ -77,11 +77,12 @@ private:
     Gaudi::Property<double> m_sectrk_Ek{this, "SecTrackEk", 100., "Ek (MeV) threshold to record a secondary track"};
     Gaudi::Property<double> m_sectrk_rho{this, "SecTrackRho", 1830., "rho (mm) threshold to record a secondary track"};
     Gaudi::Property<double> m_sectrk_z{this, "SecTrackZ", 2900., "+/- z (mm) threshold to record a secondary track"};
-    
+
+    Gaudi::Property<bool> m_istrk2primary{this, "IsTrk2Primary", true, "For m_track2primary, the value is primary or ancestor"};
 private:
-    // in order to associate the hit contribution with the primary track,
+    // in order to associate the hit contribution with the primary track or ancestor track,
     // we have a bookkeeping of every track.
-    // The primary track will assign the same key/value.
+    // The primary or ancestor track will assign the same key/value.
 
     // Following is an example:
     //    1 -> 1,
-- 
GitLab