From f8d7b87a1956e0203399dad7e5ab42ceb8fb8c7b Mon Sep 17 00:00:00 2001
From: Andrii Verbytskyi <andrii.verbytskyi@cern.ch>
Date: Tue, 23 Jun 2020 18:51:29 +0000
Subject: [PATCH] Migrate xaodtruthcnv  to HepMC3

---
 .../xAODTruthCnv/src/HepMCTruthReader.cxx     | 31 +++++++-
 .../xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx | 71 ++++++++++++++++---
 Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h |  6 ++
 3 files changed, 97 insertions(+), 11 deletions(-)

diff --git a/Event/xAOD/xAODTruthCnv/src/HepMCTruthReader.cxx b/Event/xAOD/xAODTruthCnv/src/HepMCTruthReader.cxx
index bb5b253bb65..f0ddf24c69f 100644
--- a/Event/xAOD/xAODTruthCnv/src/HepMCTruthReader.cxx
+++ b/Event/xAOD/xAODTruthCnv/src/HepMCTruthReader.cxx
@@ -74,14 +74,22 @@ StatusCode HepMCTruthReader::execute() {
 void HepMCTruthReader::printEvent(const HepMC::GenEvent* event) {
   cout << "--------------------------------------------------------------------------------\n";
   cout << "GenEvent: #" << "NNN" << "\n";
+#ifdef HEPMC3 
+  cout << " Entries this event: " << event->vertices().size() << " vertices, " << event->particles().size() << " particles.\n";
+#else 
   cout << " Entries this event: " << event->vertices_size() << " vertices, " << event->particles_size() << " particles.\n";
   // Particles and vertices
+#endif
   cout << "                                    GenParticle Legend\n";
   cout << "        Barcode   PDG ID      ( Px,       Py,       Pz,     E ) Stat  DecayVtx\n";
   cout << "--------------------------------------------------------------------------------\n";
+#ifdef HEPMC3
+  for (auto iv: ((HepMC::GenEvent*)event)->vertices()) {  printVertex(iv);  } 
+#else
   for (HepMC::GenEvent::vertex_const_iterator iv = event->vertices_begin(); iv != event->vertices_end(); ++iv) {
     printVertex(*iv);
   }
+#endif
   cout << "--------------------------------------------------------------------------------\n";
 }
 
@@ -130,7 +138,7 @@ void HepMCTruthReader::printVertex(const HepMC::GenVertexPtr vertex) {
     //  print out gives us a unique tag for the particle.
     if (vertex->position().x() != 0.0 && vertex->position().y() != 0.0 && vertex->position().z() != 0.0) {
       cout.width(9);
-      cout << (void*)vertex;
+      cout << HepMC::raw_pointer(vertex);
       cout << " ID:";
       cout.width(5);
       cout << vertex->id();
@@ -154,7 +162,7 @@ void HepMCTruthReader::printVertex(const HepMC::GenVertexPtr vertex) {
       cout << endl;
     } else {
       cout.width(9);
-      cout << (void*)vertex;
+      cout << HepMC::raw_pointer(vertex);
       cout << " ID:";
       cout.width(5);
       cout << vertex->id();
@@ -170,6 +178,24 @@ void HepMCTruthReader::printVertex(const HepMC::GenVertexPtr vertex) {
   //   cout << endl;
   // }
   // Print out all the incoming, then outgoing particles
+#ifdef HEPMC3
+  for (auto  iPIn: vertex->particles_in()) {       
+    if ( iPIn == vertex->particles_in().front() ) {
+      cout << " I: ";
+      cout.width(2);
+      cout << vertex->particles_in().size();
+    } else cout << "      ";
+    printParticle(iPIn);
+  }
+  for (auto iPOut: vertex->particles_out()) {
+    if ( iPOut == vertex->particles_out().front()) {
+      cout << " O: ";
+      cout.width(2);
+      cout << vertex->particles_out().size();
+    } else cout << "      ";
+    printParticle(iPOut);
+  }  
+#else  
   for (HepMC::GenVertex::particles_in_const_iterator iPIn = vertex->particles_in_const_begin();
        iPIn != vertex->particles_in_const_end(); ++iPIn) {       
     if ( iPIn == vertex->particles_in_const_begin() ) {
@@ -189,6 +215,7 @@ void HepMCTruthReader::printVertex(const HepMC::GenVertexPtr vertex) {
     printParticle(*iPOut);
   }
 
+#endif
   cout.flags(f); 
 }
 
diff --git a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx
index 6a3698116eb..a651259d159 100644
--- a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx
+++ b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx
@@ -186,8 +186,13 @@ namespace xAODMaker {
 	    xTruthEventContainer->push_back( xTruthEvent );
 	    // Cross-section
 	    auto crossSection = genEvt->cross_section();
+#ifdef HEPMC3
+	    xTruthEvent->setCrossSection(crossSection ? (float)crossSection->xsec() : -1);
+	    xTruthEvent->setCrossSectionError(crossSection ? (float)crossSection->xsec_err() : -1);
+#else
 	    xTruthEvent->setCrossSection(crossSection ? (float)crossSection->cross_section() : -1);
 	    xTruthEvent->setCrossSectionError(crossSection ? (float)crossSection->cross_section_error() : -1);
+#endif
                     
 	    if (m_writeMetaData) {
 	      //The mcChannelNumber is used as a unique identifier for which truth meta data belongs to
@@ -211,6 +216,22 @@ namespace xAODMaker {
 	    // Heavy ion info
 	    auto const hiInfo = genEvt->heavy_ion();
 	    if (hiInfo) {
+#ifdef HEPMC3
+              /* Please note HepMC3 as well as more recent HePMC2 versions   have more Hi parameters */
+	      xTruthEvent->setHeavyIonParameter(hiInfo->Ncoll_hard, xAOD::TruthEvent::NCOLLHARD);
+	      xTruthEvent->setHeavyIonParameter(hiInfo->Npart_proj, xAOD::TruthEvent::NPARTPROJ);
+	      xTruthEvent->setHeavyIonParameter(hiInfo->Npart_targ, xAOD::TruthEvent::NPARTTARG);
+	      xTruthEvent->setHeavyIonParameter(hiInfo->Ncoll, xAOD::TruthEvent::NCOLL);
+	      xTruthEvent->setHeavyIonParameter(hiInfo->spectator_neutrons, xAOD::TruthEvent::SPECTATORNEUTRONS);
+	      xTruthEvent->setHeavyIonParameter(hiInfo->spectator_protons, xAOD::TruthEvent::SPECTATORPROTONS);
+	      xTruthEvent->setHeavyIonParameter(hiInfo->N_Nwounded_collisions, xAOD::TruthEvent::NNWOUNDEDCOLLISIONS);
+	      xTruthEvent->setHeavyIonParameter(hiInfo->Nwounded_N_collisions, xAOD::TruthEvent::NWOUNDEDNCOLLISIONS);
+	      xTruthEvent->setHeavyIonParameter(hiInfo->Nwounded_Nwounded_collisions, xAOD::TruthEvent::NWOUNDEDNWOUNDEDCOLLISIONS);
+	      xTruthEvent->setHeavyIonParameter((float)hiInfo->impact_parameter, xAOD::TruthEvent::IMPACTPARAMETER);
+	      xTruthEvent->setHeavyIonParameter((float)hiInfo->event_plane_angle, xAOD::TruthEvent::EVENTPLANEANGLE);
+	      xTruthEvent->setHeavyIonParameter((float)hiInfo->eccentricity, xAOD::TruthEvent::ECCENTRICITY);
+	      xTruthEvent->setHeavyIonParameter((float)hiInfo->sigma_inel_NN, xAOD::TruthEvent::SIGMAINELNN);
+#else
 	      xTruthEvent->setHeavyIonParameter(hiInfo->Ncoll_hard(), xAOD::TruthEvent::NCOLLHARD);
 	      xTruthEvent->setHeavyIonParameter(hiInfo->Npart_proj(), xAOD::TruthEvent::NPARTPROJ);
 	      xTruthEvent->setHeavyIonParameter(hiInfo->Npart_targ(), xAOD::TruthEvent::NPARTTARG);
@@ -224,6 +245,7 @@ namespace xAODMaker {
 	      xTruthEvent->setHeavyIonParameter(hiInfo->event_plane_angle(), xAOD::TruthEvent::EVENTPLANEANGLE);
 	      xTruthEvent->setHeavyIonParameter(hiInfo->eccentricity(), xAOD::TruthEvent::ECCENTRICITY);
 	      xTruthEvent->setHeavyIonParameter(hiInfo->sigma_inel_NN(), xAOD::TruthEvent::SIGMAINELNN);
+#endif
 	      // This doesn't yet exist in our version of HepMC
 	      // xTruthEvent->setHeavyIonParameter(hiInfo->centrality(),xAOD::TruthEvent::CENTRALITY);
 	    }
@@ -232,6 +254,18 @@ namespace xAODMaker {
 	    // This will exist 99% of the time, except for e.g. cosmic or particle gun simulation
 	    auto const pdfInfo = genEvt->pdf_info();
 	    if (pdfInfo) {
+#ifdef HEPMC3
+	      xTruthEvent->setPdfInfoParameter(pdfInfo->parton_id[0], xAOD::TruthEvent::PDGID1);
+	      xTruthEvent->setPdfInfoParameter(pdfInfo->parton_id[1], xAOD::TruthEvent::PDGID2);
+	      xTruthEvent->setPdfInfoParameter(pdfInfo->pdf_id[1], xAOD::TruthEvent::PDFID1);
+	      xTruthEvent->setPdfInfoParameter(pdfInfo->pdf_id[1], xAOD::TruthEvent::PDFID2);
+                        
+	      xTruthEvent->setPdfInfoParameter((float)pdfInfo->x[0], xAOD::TruthEvent::X1);
+	      xTruthEvent->setPdfInfoParameter((float)pdfInfo->x[1], xAOD::TruthEvent::X2);
+	      xTruthEvent->setPdfInfoParameter((float)pdfInfo->scale, xAOD::TruthEvent::Q);
+	      xTruthEvent->setPdfInfoParameter((float)pdfInfo->xf[0], xAOD::TruthEvent::XF1);
+	      xTruthEvent->setPdfInfoParameter((float)pdfInfo->xf[1], xAOD::TruthEvent::XF2);
+#else
 	      xTruthEvent->setPdfInfoParameter(pdfInfo->id1(), xAOD::TruthEvent::PDGID1);
 	      xTruthEvent->setPdfInfoParameter(pdfInfo->id2(), xAOD::TruthEvent::PDGID2);
 	      xTruthEvent->setPdfInfoParameter(pdfInfo->pdf_id1(), xAOD::TruthEvent::PDFID1);
@@ -242,6 +276,7 @@ namespace xAODMaker {
 	      xTruthEvent->setPdfInfoParameter((float)pdfInfo->scalePDF(), xAOD::TruthEvent::Q);
 	      xTruthEvent->setPdfInfoParameter((float)pdfInfo->pdf1(), xAOD::TruthEvent::XF1);
 	      xTruthEvent->setPdfInfoParameter((float)pdfInfo->pdf2(), xAOD::TruthEvent::XF2);
+#endif
 	    }
 	  }
 	  if (!isSignalProcess) xTruthPileupEventContainer->push_back( xTruthPileupEvent );
@@ -258,8 +293,13 @@ namespace xAODMaker {
 	  // If this is a disconnected vertex, add it manually or won't be added from the loop over particles below.
 	   auto disconnectedSignalProcessVtx = HepMC::signal_process_vertex((HepMC::GenEvent*)genEvt); // Get the signal process vertex
 	  if (disconnectedSignalProcessVtx) {
+#ifdef HEPMC3
+	    if (disconnectedSignalProcessVtx->particles_in().size() == 0 &&
+		disconnectedSignalProcessVtx->particles_out().size() == 0 ) {
+#else
 	    if (disconnectedSignalProcessVtx->particles_in_size() == 0 &&
 		disconnectedSignalProcessVtx->particles_out_size() == 0 ) {
+#endif
 	      //This is a disconnected vertex, add it manually
 	      vertices.push_back (disconnectedSignalProcessVtx);
 	    }
@@ -270,31 +310,37 @@ namespace xAODMaker {
 	  // Get the beam particles
 	  pair<HepMC::GenParticlePtr,HepMC::GenParticlePtr> beamParticles;
 	  bool genEvt_valid_beam_particles=false;
+#ifdef HEPMC3
+	  auto beamParticles_vec = ((HepMC::GenEvent*)genEvt)->beams();
+	  genEvt_valid_beam_particles=(beamParticles_vec.size()>1);
+	  if (genEvt_valid_beam_particles){beamParticles.first=beamParticles_vec[0]; beamParticles.second=beamParticles_vec[1]; }
+#else	  
           genEvt_valid_beam_particles=genEvt->valid_beam_particles();
 	  if ( genEvt_valid_beam_particles ) beamParticles = genEvt->beam_particles();
-	  for (HepMC::GenEvent::particle_const_iterator pitr=genEvt->particles_begin(); pitr!=genEvt->particles_end(); ++pitr) {
+#endif 
+	  for (auto  part: *((HepMC::GenEvent*)genEvt)) {
 	    // (a) create TruthParticle
 	    xAOD::TruthParticle* xTruthParticle = new xAOD::TruthParticle();
 	    xTruthParticleContainer->push_back( xTruthParticle );
-	    fillParticle(xTruthParticle, *pitr); // (b) Copy HepMC info into the new particle
+	    fillParticle(xTruthParticle, part); // (b) Copy HepMC info into the new particle
 	    // (c) Put particle into container; Build Event<->Particle element link
 	    const ElementLink<xAOD::TruthParticleContainer> eltp(*xTruthParticleContainer, xTruthParticleContainer->size()-1);
 	    if (isSignalProcess) xTruthEvent->addTruthParticleLink(eltp);
 	    if (!isSignalProcess) xTruthPileupEvent->addTruthParticleLink(eltp);
                     
 	    // Create link between HepMC and xAOD truth
-	    if (isSignalProcess) truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*pitr),0,EBC_MAINEVCOLL,HepMcParticleLink::IS_POSITION), eltp));
-	    if (!isSignalProcess) truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*pitr),genEvt->event_number()), eltp));
+	    if (isSignalProcess) truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink(part,0,EBC_MAINEVCOLL,HepMcParticleLink::IS_POSITION), eltp));
+	    if (!isSignalProcess) truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink(part,genEvt->event_number()), eltp));
                     
 	    // Is this one of the beam particles?
 	    if (genEvt_valid_beam_particles) {
 	      if (isSignalProcess) {
-		if (*pitr == beamParticles.first) xTruthEvent->setBeamParticle1Link(eltp);
-		if (*pitr == beamParticles.second) xTruthEvent->setBeamParticle2Link(eltp);
+		if (part == beamParticles.first) xTruthEvent->setBeamParticle1Link(eltp);
+		if (part == beamParticles.second) xTruthEvent->setBeamParticle2Link(eltp);
 	      }
 	    }
 	    // (d) Particle's production vertex
-	    auto productionVertex = (*pitr)->production_vertex();
+	    auto productionVertex = part->production_vertex();
 	    if (productionVertex) {
 	      VertexParticles& parts = vertexMap[productionVertex];
 	      if (parts.incoming.empty() && parts.outgoing.empty())
@@ -306,7 +352,7 @@ namespace xAODMaker {
 	    // else maybe want to keep track that this is the production vertex
 	    //
 	    // (e) Particle's decay vertex
-	    auto decayVertex = (*pitr)->end_vertex();
+	    auto decayVertex = part->end_vertex();
 	    if (decayVertex) {
 	      VertexParticles& parts = vertexMap[decayVertex];
 	      if (parts.incoming.empty() && parts.outgoing.empty())
@@ -378,7 +424,7 @@ namespace xAODMaker {
         tp->setBarcode(HepMC::barcode(gp));
         tp->setStatus(gp->status());
         
-        const HepMC::Polarization& pol = gp->polarization();
+        auto pol = HepMC::polarization(gp);
         if (pol.is_defined()) {
             tp->setPolarizationParameter(pol.theta(), xAOD::TruthParticle::polarizationTheta);
             tp->setPolarizationParameter(pol.phi(), xAOD::TruthParticle::polarizationPhi);
@@ -424,6 +470,12 @@ namespace xAODMaker {
         m_tmd->push_back (std::make_unique <xAOD::TruthMetaData>());
         xAOD::TruthMetaData* md = m_tmd->back();
         
+#ifdef HEPMC3
+        ///Here comes the fix. Note that HepMC2.06.11 also contains the fix
+        md->setMcChannelNumber(mcChannelNumber);
+        std::vector<std::string> orderedWeightNameVec=genEvt.weight_names();
+        md->setWeightNames(orderedWeightNameVec);
+#else 
         // FIXME: class member protection violation here.
         // This appears to be because WeightContainer has no public methods
         // to get information about the weight names.
@@ -441,6 +493,7 @@ namespace xAODMaker {
                             
         md->setMcChannelNumber(mcChannelNumber);
         md->setWeightNames( std::move(orderedWeightNameVec) );
+#endif
       }
 
       return StatusCode::SUCCESS;
diff --git a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h
index 79513e702cc..7dbd7ab4166 100644
--- a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h
+++ b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h
@@ -7,6 +7,9 @@
 
 #include "AthenaBaseComps/AthReentrantAlgorithm.h"
 
+#ifdef HEPMC3
+// This form of ifdef is kept for convenience
+#else
 // The lines below I don't like. We should fix them when we update the
 // the metadata to handles (ATLASRECTS-4162).
 // Needs changes in HepMC to resolve.
@@ -20,6 +23,7 @@
 #ifdef __clang__
 #pragma clang diagnostic pop
 #endif
+#endif
 
 #include "GeneratorObjects/xAODTruthParticleLink.h"
 #include "GeneratorObjects/McEventCollection.h"
@@ -39,6 +43,8 @@
 #include <unordered_set>
 
 
+#include "AtlasHepMC/WeightContainer.h"
+#include "AtlasHepMC/Polarization.h"
 #include "AtlasHepMC/GenVertex_fwd.h"
 #include "AtlasHepMC/GenParticle_fwd.h"
 
-- 
GitLab