From e7615fd7ee2a69c89fcec6557f686ca411271b60 Mon Sep 17 00:00:00 2001
From: John Chapman <John.Chapman@cern.ch>
Date: Wed, 15 May 2024 15:09:54 +0200
Subject: [PATCH] ISFTruthIncident: Improvements to properly update
 ISFParticles after the Truth Incident has been registered

---
 .../ISF_Event/ISF_Event/ISFTruthIncident.h    |  5 ++
 .../ISF_Event/src/ISFTruthIncident.cxx        | 79 ++++++++++++++++++-
 .../ISF_Core/ISF_Services/src/TruthSvc.cxx    |  6 ++
 3 files changed, 86 insertions(+), 4 deletions(-)

diff --git a/Simulation/ISF/ISF_Core/ISF_Event/ISF_Event/ISFTruthIncident.h b/Simulation/ISF/ISF_Core/ISF_Event/ISF_Event/ISFTruthIncident.h
index 95c9c3996fbf..998c185d0410 100644
--- a/Simulation/ISF/ISF_Core/ISF_Event/ISF_Event/ISFTruthIncident.h
+++ b/Simulation/ISF/ISF_Core/ISF_Event/ISF_Event/ISFTruthIncident.h
@@ -96,6 +96,11 @@ namespace ISF {
         simulation) - TODO only a dummy implementation currently */
     virtual HepMC::GenParticlePtr     updateChildParticle(unsigned short index,
                                                           HepMC::GenParticlePtr existingChild) const override final;
+    /** Update the id and particleLink properties of the parentAfterIncident (to be called after registerTruthIncident) */
+    void updateParentAfterIncidentProperties();
+    /** Update the id and particleLink properties of the child particles (to be called after registerTruthIncident) */
+    void updateChildParticleProperties();
+
   private:
     ISFTruthIncident();
 
diff --git a/Simulation/ISF/ISF_Core/ISF_Event/src/ISFTruthIncident.cxx b/Simulation/ISF/ISF_Core/ISF_Event/src/ISFTruthIncident.cxx
index b7b31cf2686c..5ec65d0abfbd 100644
--- a/Simulation/ISF/ISF_Core/ISF_Event/src/ISFTruthIncident.cxx
+++ b/Simulation/ISF/ISF_Core/ISF_Event/src/ISFTruthIncident.cxx
@@ -22,8 +22,9 @@ static HepMC::GenParticlePtr ParticleHelper_convert( const ISF::ISFParticle &par
   HepMC::FourVector fourMomentum( mom.x(), mom.y(), mom.z(), energy);
 
   auto hepParticle = HepMC::newGenParticlePtr( fourMomentum, particle.pdgCode(), particle.status() );
+#ifndef HEPMC3
   HepMC::suggest_barcode(hepParticle, particle.barcode() );
-
+#endif
   // return a newly created GenParticle
   return hepParticle;
 }
@@ -119,6 +120,9 @@ HepMC::GenParticlePtr ISF::ISFTruthIncident::parentParticleAfterIncident(int new
   // set a new status
   m_parent.setStatus( parentStatus() + HepMC::SIM_STATUS_INCREMENT );
 
+  // FIXME At this point the m_parent ISFParticle's id, truthBinding
+  // and particleLink all still need to be updated
+
   // and update truth info (including the ISFParticle's HMPL)
   return updateHepMCTruthParticle(m_parent, &m_parent);
 }
@@ -154,6 +158,12 @@ HepMC::GenParticlePtr ISF::ISFTruthIncident::childParticle(unsigned short index,
     sec->setBarcode( bc);
   }
 
+  // Enforce that the status is set correctly
+  sec->setStatus(1 + HepMC::SIM_STATUS_THRESHOLD);
+
+  // FIXME At this point the sec ISFParticle's id, truthBinding
+  // and particleLink all still need to be updated
+
   // and update truth info (including the ISFParticle's HMPL)
   return updateHepMCTruthParticle( *sec, &m_parent );
 }
@@ -171,7 +181,7 @@ HepMC::GenParticlePtr ISF::ISFTruthIncident::getHepMCTruthParticle( ISF::ISFPart
   HepMC::GenParticlePtr hepTruthParticle = truthBinding ? truthBinding->getTruthParticle() : nullptr;
  
   // We have what we want
-  if(hepTruthParticle){
+  if (hepTruthParticle) {
     return hepTruthParticle;
   }
   //Otherwise we need to create it
@@ -194,7 +204,12 @@ HepMC::GenParticlePtr ISF::ISFTruthIncident::updateHepMCTruthParticle( ISF::ISFP
     particle.setTruthBinding(truthBinding);
   }
 
-  //register the new GenParticle as HepMcParticleLink, copying over some old properties if present
+#ifndef HEPMC3
+  // Register the new GenParticle as HepMcParticleLink, copying over
+  // some old properties if present.
+  // This only makes sense to do if the GenParticle has a valid unique
+  // ID which it won't in HepMC3 until it has been added to the
+  // GenEvent
   const HepMcParticleLink* oldHMPL = particle.getParticleLink();
   HepMcParticleLink* newHMPL = nullptr;
   if (oldHMPL) {
@@ -204,6 +219,62 @@ HepMC::GenParticlePtr ISF::ISFTruthIncident::updateHepMCTruthParticle( ISF::ISFP
     newHMPL = new HepMcParticleLink(hepTruthParticle, 0, HepMcParticleLink::IS_EVENTNUM); // FIXME should be HepMcParticleLink::IS_POSITION
   }
   particle.setParticleLink(newHMPL);
-
+#endif
   return hepTruthParticle;
 }
+
+/** Update the id and particleLink properties of the parentAfterIncident */
+void ISF::ISFTruthIncident::updateParentAfterIncidentProperties() {
+  const ISF::TruthBinding *parentAfterIncidentTruthBinding = m_parent.getTruthBinding();
+  auto parentAfterIncidentGenParticle = (parentAfterIncidentTruthBinding)  ? parentAfterIncidentTruthBinding->getTruthParticle() : nullptr;
+  const int parentAfterIncidentID = (parentAfterIncidentGenParticle) ? HepMC::uniqueID(parentAfterIncidentGenParticle) : HepMC::UNDEFINED_ID;
+  HepMcParticleLink* parentAfterIncidentHMPL{};
+  const HepMcParticleLink* parentBeforeIncidentHMPL = m_parent.getParticleLink();
+  int eventIndex{0};
+  if (parentAfterIncidentGenParticle) { eventIndex = parentAfterIncidentGenParticle->parent_event()->event_number(); }
+  else if (parentBeforeIncidentHMPL) { eventIndex = parentBeforeIncidentHMPL->eventIndex(); }
+  const HepMcParticleLink::PositionFlag idxFlag =
+    (eventIndex==0) ? HepMcParticleLink::IS_POSITION: HepMcParticleLink::IS_EVENTNUM;
+  if (parentBeforeIncidentHMPL) {
+    delete parentBeforeIncidentHMPL;
+  }
+  if (!parentAfterIncidentGenParticle) {
+    parentAfterIncidentHMPL = new HepMcParticleLink(parentAfterIncidentID, eventIndex, idxFlag, HepMcParticleLink::IS_ID);
+  }
+  else {
+    parentAfterIncidentHMPL = new HepMcParticleLink(parentAfterIncidentGenParticle, eventIndex, idxFlag);
+  }
+  m_parent.setId(parentAfterIncidentID);
+  m_parent.setParticleLink(parentAfterIncidentHMPL);
+}
+
+/** Update the id and particleLink properties of the child particles (to be called after registerTruthIncident) */
+void ISF::ISFTruthIncident::updateChildParticleProperties() {
+  unsigned short numSec = numberOfChildren();
+  for (unsigned short i=0; i<numSec; i++) {
+    // the current particle
+    ISF::ISFParticle *child = m_children[i];
+    const ISF::TruthBinding *childTruthBinding = child->getTruthBinding();
+    auto childGenParticle = (childTruthBinding)  ? childTruthBinding->getTruthParticle() : nullptr;
+    // FIXME should probably have some kind of sanity check here to avoid bogus TruthBindings
+    const int childID = (childGenParticle) ? HepMC::uniqueID(childGenParticle) : HepMC::UNDEFINED_ID;
+    HepMcParticleLink* childHMPL{};
+    const HepMcParticleLink* oldChildHMPL = child->getParticleLink();
+    int eventIndex{0};
+    if (childGenParticle) { eventIndex = childGenParticle->parent_event()->event_number(); }
+    else if (oldChildHMPL) { eventIndex = oldChildHMPL->eventIndex(); }
+    const HepMcParticleLink::PositionFlag idxFlag =
+      (eventIndex==0) ? HepMcParticleLink::IS_POSITION: HepMcParticleLink::IS_EVENTNUM;
+    if (oldChildHMPL) {
+      delete oldChildHMPL;
+    }
+    if (!childGenParticle) {
+      childHMPL = new HepMcParticleLink(childID, eventIndex, idxFlag, HepMcParticleLink::IS_ID);
+    }
+    else {
+      childHMPL = new HepMcParticleLink(childGenParticle, eventIndex, idxFlag);
+    }
+    child->setId(childID);
+    child->setParticleLink(childHMPL);
+  }
+}
diff --git a/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx b/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx
index 2c63fcb7fd22..d5d340ffe371 100644
--- a/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx
+++ b/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx
@@ -250,6 +250,9 @@ void ISF::TruthSvc::recordIncidentToMCTruth( ISF::ITruthIncident& ti, bool passW
 #ifdef HEPMC3
     HepMC::suggest_barcode( parentAfterIncident, newPrimaryBC ); // TODO check this works correctly
 #endif
+    // NB For ISFTruthIncident the m_parent ISFParticle still needs
+    // its id and particleLink properties to be properly updated at
+    // this point.
     ATH_MSG_VERBOSE ( "Parent After Incident: " << parentAfterIncident << ", barcode: " << HepMC::barcode(parentAfterIncident));
   }
 
@@ -278,6 +281,9 @@ void ISF::TruthSvc::recordIncidentToMCTruth( ISF::ITruthIncident& ti, bool passW
 #ifdef HEPMC3
         int secondaryParticleBCFromTI = ti.childBarcode(i);
         HepMC::suggest_barcode( p, secondaryParticleBCFromTI ? secondaryParticleBCFromTI : secondaryParticleBC );
+        // NB For ISFTruthIncident the current child ISFParticle still needs
+        // its id and particleLink properties to be properly updated at
+        // this point.
 #endif
       }
       ATH_MSG_VERBOSE ( "Writing out " << i << "th child particle: " << p << ", barcode: " << HepMC::barcode(p));
-- 
GitLab