From 767b1bf1b22e03a5214d23d05c4f97814ac2dbf8 Mon Sep 17 00:00:00 2001
From: Chengdong Fu <fucd@ihep.ac.cn>
Date: Mon, 1 Apr 2024 08:09:42 +0800
Subject: [PATCH] import as assocaition maker between MCPartilce and Track

---
 .../RecAssociationMaker/CMakeLists.txt        |  20 +++
 .../src/TrackParticleRelationAlg.cpp          | 150 ++++++++++++++++++
 .../src/TrackParticleRelationAlg.h            |  38 +++++
 3 files changed, 208 insertions(+)
 create mode 100644 Reconstruction/RecAssociationMaker/CMakeLists.txt
 create mode 100644 Reconstruction/RecAssociationMaker/src/TrackParticleRelationAlg.cpp
 create mode 100644 Reconstruction/RecAssociationMaker/src/TrackParticleRelationAlg.h

diff --git a/Reconstruction/RecAssociationMaker/CMakeLists.txt b/Reconstruction/RecAssociationMaker/CMakeLists.txt
new file mode 100644
index 00000000..d854356b
--- /dev/null
+++ b/Reconstruction/RecAssociationMaker/CMakeLists.txt
@@ -0,0 +1,20 @@
+# Modules
+gaudi_add_module(RecAssociationMaker
+                 SOURCES src/TrackParticleRelationAlg.cpp
+
+                 LINK GearSvc
+                      EventSeeder
+                      TrackSystemSvcLib
+                      DataHelperLib
+                      KiTrackLib
+                      Gaudi::GaudiKernel
+                      k4FWCore::k4FWCore
+                      ${GEAR_LIBRARIES}
+                      ${GSL_LIBRARIES}
+                      ${LCIO_LIBRARIES}
+)
+install(TARGETS RecAssociationMaker
+  EXPORT CEPCSWTargets
+  RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin
+  LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib
+  COMPONENT dev)
diff --git a/Reconstruction/RecAssociationMaker/src/TrackParticleRelationAlg.cpp b/Reconstruction/RecAssociationMaker/src/TrackParticleRelationAlg.cpp
new file mode 100644
index 00000000..1c764257
--- /dev/null
+++ b/Reconstruction/RecAssociationMaker/src/TrackParticleRelationAlg.cpp
@@ -0,0 +1,150 @@
+#include "TrackParticleRelationAlg.h"
+
+DECLARE_COMPONENT(TrackParticleRelationAlg)
+
+TrackParticleRelationAlg::TrackParticleRelationAlg(const std::string& name, ISvcLocator* svcLoc)
+: GaudiAlgorithm(name, svcLoc){
+  declareProperty("MCParticleCollection", m_inMCParticleColHdl, "Handle of the Input MCParticle collection");
+}
+
+StatusCode TrackParticleRelationAlg::initialize() {
+  for(auto name : m_inTrackCollectionNames) {
+    m_inTrackColHdls.push_back(new DataHandle<edm4hep::TrackCollection> (name, Gaudi::DataHandle::Reader, this));
+    m_outColHdls.push_back(new DataHandle<edm4hep::MCRecoTrackParticleAssociationCollection> (name+"ParticleAssociation", Gaudi::DataHandle::Writer, this));
+  }
+  
+  for(unsigned i=0; i<m_inAssociationCollectionNames.size(); i++) {
+    m_inAssociationColHdls.push_back(new DataHandle<edm4hep::MCRecoTrackerAssociationCollection> (m_inAssociationCollectionNames[i], Gaudi::DataHandle::Reader, this));
+  }
+  
+  if(m_inAssociationColHdls.size()==0) {
+    warning() << "no Association Collection input" << endmsg;
+    return StatusCode::FAILURE;
+  }
+
+  m_nEvt = 0;
+  return GaudiAlgorithm::initialize();
+}
+
+StatusCode TrackParticleRelationAlg::execute() {
+  info() << "start Event " << m_nEvt << endmsg;
+  
+  // MCParticle
+  const edm4hep::MCParticleCollection* mcpCol = nullptr;
+  try {
+    mcpCol = m_inMCParticleColHdl.get();
+    for (auto mcp : *mcpCol) {
+      debug() << "id=" << mcp.id() << " pdgid=" << mcp.getPDG() << " charge=" << mcp.getCharge() << " genstat=" << mcp.getGeneratorStatus() << " simstat=" << mcp.getSimulatorStatus()
+	      << " p=" << mcp.getMomentum() << endmsg;
+      int nparents = mcp.parents_size();
+      int ndaughters = mcp.daughters_size();
+      for (int i=0; i<nparents; i++) {
+	debug() << "<<<<<<" << mcp.getParents(i).id() << endmsg;
+      }
+      for (int i=0; i<ndaughters; i++) {
+        debug() << "<<<<<<" << mcp.getDaughters(i).id() << endmsg;
+      }
+    }
+  }
+  catch ( GaudiException &e ) {
+    debug() << "Collection " << m_inMCParticleColHdl.fullKey() << " is unavailable in event " << m_nEvt << endmsg;
+  }
+  if(!mcpCol) {
+    warning() << "pass this event because MCParticle collection can not read" << endmsg; 
+    return StatusCode::SUCCESS;
+  }
+
+  // Prepare map from hit to MCParticle
+  std::map<edm4hep::TrackerHit, edm4hep::MCParticle> mapHitParticle;
+  debug() << "reading Association" << endmsg;
+  for (auto hdl : m_inAssociationColHdls) {
+    const edm4hep::MCRecoTrackerAssociationCollection* assCol = nullptr;
+    try {
+      assCol = hdl->get();
+    }
+    catch ( GaudiException &e ) {
+      debug() << "Collection " << hdl->fullKey() << " is unavailable in event " << m_nEvt << endmsg;
+      return StatusCode::FAILURE;
+    }
+    for (auto ass: *assCol) {
+      auto hit = ass.getRec();
+      auto particle = ass.getSim().getMCParticle();
+      mapHitParticle[hit] = particle;
+    }
+  }
+  
+  // Handle all input TrackCollection
+  for (unsigned icol=0; icol<m_inTrackColHdls.size(); icol++) {
+    auto hdl = m_inTrackColHdls[icol];
+
+    const edm4hep::TrackCollection* trkCol = nullptr;
+    try {
+      trkCol = hdl->get();
+    }
+    catch ( GaudiException &e ) {
+      debug() << "Collection " << hdl->fullKey() << " is unavailable in event " << m_nEvt << endmsg;
+    }
+
+    auto outCol = m_outColHdls[icol]->createAndPut();
+    if(!outCol) {
+      error() << "Collection " << m_outColHdls[icol]->fullKey() << " cannot be created" << endmsg;
+      return StatusCode::FAILURE;
+    }
+    
+    if(trkCol) {
+      std::map<edm4hep::MCParticle, std::vector<edm4hep::TrackerHit> > mapParticleHits;
+
+      for (auto track: *trkCol) {
+	std::map<edm4hep::MCParticle, int> mapParticleNHits;
+	
+	// Count hits related to MCParticle
+	int nhits = track.trackerHits_size();
+	for (int ihit=0; ihit<nhits; ihit++) {
+	  auto hit = track.getTrackerHits(ihit);
+	  auto itHP  = mapHitParticle.find(hit);
+	  if (itHP==mapHitParticle.end()) {
+	    warning() << "track " << track.id() << "'s hit " << hit.id() << "not in association list, will be ignored" << endmsg;
+	  }
+	  else {
+	    auto particle = itHP->second;
+	    if(!particle.isAvailable()) continue;
+	    debug() << "track " << track.id() << "'s hit " << hit.id() << " link to MCParticle " << particle.id() << endmsg;
+	    auto itPN = mapParticleNHits.find(particle);
+	    if (itPN!=mapParticleNHits.end()) itPN->second++;
+	    else                             mapParticleNHits[particle] = 1;
+
+	    if (msgLevel(MSG::DEBUG)) mapParticleHits[particle].push_back(hit);
+	  }
+	}
+	debug() << "Total " << mapParticleNHits.size() << " particles link to the track " << track.id() << endmsg;
+
+	// Save to collection
+	for (std::map<edm4hep::MCParticle, int>::iterator it=mapParticleNHits.begin(); it!=mapParticleNHits.end(); it++) {
+	  auto ass = outCol->create();
+	  ass.setWeight(it->second);
+	  ass.setRec(track);
+	  ass.setSim(it->first);
+	}
+      }
+      
+      if (msgLevel(MSG::DEBUG)) {
+	for (std::map<edm4hep::MCParticle, std::vector<edm4hep::TrackerHit> >::iterator it=mapParticleHits.begin(); it!=mapParticleHits.end(); it++) {
+	  auto particle = it->first;
+	  auto hits     = it->second;
+	  debug() << "=== MCPaticle ===" << particle << endmsg;
+	  for (auto hit : hits) {
+	    debug() << hit << endmsg;
+	  }
+	}
+      }
+    }
+  }
+
+  m_nEvt++;
+  return StatusCode::SUCCESS;
+}
+
+StatusCode TrackParticleRelationAlg::finalize() {
+  
+  return StatusCode::SUCCESS;
+}
diff --git a/Reconstruction/RecAssociationMaker/src/TrackParticleRelationAlg.h b/Reconstruction/RecAssociationMaker/src/TrackParticleRelationAlg.h
new file mode 100644
index 00000000..9f19212b
--- /dev/null
+++ b/Reconstruction/RecAssociationMaker/src/TrackParticleRelationAlg.h
@@ -0,0 +1,38 @@
+#ifndef TrackParticleRelationAlg_h
+#define TrackParticleRelationAlg_h 1
+
+#include "k4FWCore/DataHandle.h"
+#include "GaudiAlg/GaudiAlgorithm.h"
+
+#include "edm4hep/MCParticleCollection.h"
+#include "edm4hep/TrackCollection.h"
+#include "edm4hep/MCRecoTrackerAssociationCollection.h"
+#include "edm4hep/MCRecoTrackParticleAssociationCollection.h"
+
+class TrackParticleRelationAlg : public GaudiAlgorithm {
+ public:
+  // Constructor of this form must be provided
+  TrackParticleRelationAlg( const std::string& name, ISvcLocator* pSvcLocator );
+
+  // Three mandatory member functions of any algorithm
+  StatusCode initialize() override;
+  StatusCode execute() override;
+  StatusCode finalize() override;
+
+ private:
+  // input MCParticle
+  DataHandle<edm4hep::MCParticleCollection>                              m_inMCParticleColHdl{"MCParticle", Gaudi::DataHandle::Reader, this};
+  // input Tracks to make relation
+  std::vector<DataHandle<edm4hep::TrackCollection>* >                    m_inTrackColHdls;
+  Gaudi::Property<std::vector<std::string> >                             m_inTrackCollectionNames{this, "TrackList", {"SiTracks"}};
+  // input TrackerAssociation to link TrackerHit and SimTrackerHit
+  std::vector<DataHandle<edm4hep::MCRecoTrackerAssociationCollection>* > m_inAssociationColHdls;
+  Gaudi::Property<std::vector<std::string> >                             m_inAssociationCollectionNames{this, "TrackerAssociationList", {"VXDTrackerHitAssociation",
+        "SITTrackerHitAssociation", "SETTrackerHitAssociation", "FTDTrackerHitAssociation"}};
+
+  // output TrackParticleAssociation
+  std::vector<DataHandle<edm4hep::MCRecoTrackParticleAssociationCollection>* > m_outColHdls;
+
+  int m_nEvt;
+};
+#endif
-- 
GitLab