LCOV - code coverage report
Current view: top level - TEvtGen/THepMCParser - THepMCParser.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 447 0.0 %
Date: 2016-06-14 17:26:59 Functions: 0 15 0.0 %

          Line data    Source code
       1             : // module identifier line...
       2             : // Author: Brian Thorsbro, 24/6-2014
       3             : 
       4             : #include <iostream>
       5             : #include <sstream>
       6             : #include <string>
       7             : #include <list>
       8             : #include <set>
       9             : #include <time.h>
      10             : 
      11             : #include "THepMCParser.h"
      12             : #include "TObject.h"
      13             : #include "TTree.h"
      14             : #include "TClonesArray.h"
      15             : #include "TFile.h"
      16             : #include "TParticle.h"
      17             : #include "TDatabasePDG.h"
      18             : #include "HepMC/IO_GenEvent.h"
      19             : 
      20             : 
      21             : using namespace std;
      22             : 
      23             : 
      24           0 : THepMCParser::THepMCParser(const char * infile) : fTree(0)
      25           0 : {
      26           0 :    HepMC::IO_BaseClass * events = new HepMC::IO_GenEvent(infile, std::ios::in);
      27           0 :    init(events);
      28           0 :    delete events;
      29             :    events = 0; // nullptr
      30           0 : }
      31           0 : THepMCParser::THepMCParser(HepMC::IO_BaseClass * events) : fTree(0)
      32           0 : {
      33           0 :    init(events);
      34           0 : }
      35             : void THepMCParser::init(HepMC::IO_BaseClass * events)
      36             : {
      37             :    int particlecount = 0;
      38           0 :    fTree = new TTree("treeEPOS","Tree EPOS");
      39           0 :    TClonesArray * array = new TClonesArray("TParticle");
      40             :    // array->BypassStreamer();
      41           0 :    fTree->Branch("Particles",&array); // more flags?
      42           0 :    THepMCParser::HeavyIonHeader_t heavyIonHeader;
      43           0 :    fTree->Branch("HeavyIonInfo", &heavyIonHeader, THepMCParser::fgHeavyIonHeaderBranchString);
      44           0 :    THepMCParser::PdfHeader_t pdfHeader;
      45           0 :    fTree->Branch("PdfInfo", &pdfHeader, THepMCParser::fgPdfHeaderBranchString);
      46             :    HepMC::GenEvent* evt =  0; // nullptr
      47           0 :    while ((evt = events->read_next_event())) {
      48           0 :       string errMsg1 = ParseGenEvent2TCloneArray(evt,array);
      49           0 :       string errMsg2 = ParseGenEvent2HeaderStructs(evt,heavyIonHeader,pdfHeader);
      50           0 :       if (errMsg1.length() == 0 && errMsg2.length() == 0) {
      51           0 :          fTree->Fill();
      52             :       } else {
      53           0 :          if (errMsg1.length() != 0) cerr << errMsg1 << endl;
      54           0 :          if (errMsg2.length() != 0) cerr << errMsg2 << endl;
      55             :       }
      56           0 :       particlecount += array->Capacity();
      57           0 :    }
      58             : //   array->Clear();
      59             : //   delete array;
      60             : //   array = 0; // nullptr
      61           0 :    cout << " parsed " << particlecount << " particles" << endl;
      62           0 :    if(array->Capacity() != array->GetEntries()) {
      63           0 :      cerr << ("Not all particles processed");
      64           0 :    }
      65           0 : }
      66             : 
      67             : 
      68             : TTree * THepMCParser::GetTTree()
      69             : {
      70           0 :    return fTree;
      71             : }
      72             : void THepMCParser::WriteTTreeToFile(const char *outfile)
      73             : {
      74           0 :    TFile * f = new TFile(outfile, "recreate");
      75           0 :    fTree->Write();
      76           0 :    delete f;
      77             :    f = 0; // nullptr
      78           0 : }
      79             : 
      80             : 
      81             : 
      82             : // Based on a validator written by Peter Hristov, CERN
      83             : bool THepMCParser::IsValidMotherDaughtersConsitency(bool useStdErr, bool requireSecondMotherBeforeDaughters)
      84             : {
      85             :    bool valid = true;
      86           0 :    TClonesArray * array = new TClonesArray("TParticle");
      87           0 :    TBranch* branch = fTree->GetBranch("Particles");
      88           0 :    branch->SetAddress(&array);
      89           0 :    Int_t count = branch->GetEntries();
      90           0 :    for (Int_t idx=0; idx<count; ++idx) {
      91           0 :       array->Clear();
      92           0 :       branch->GetEntry(idx); // "fill" the array
      93           0 :       Int_t nkeep = array->GetEntriesFast();
      94           0 :       for (Int_t i=0; i<nkeep; i++) {
      95           0 :          TParticle * part = (TParticle*)array->AddrAt(i);
      96           0 :          Int_t mum1 = part->GetFirstMother();
      97           0 :          Int_t mum2 = part->GetSecondMother();
      98           0 :          Int_t fd = part->GetFirstDaughter();
      99           0 :          Int_t ld = part->GetLastDaughter();
     100           0 :          if (mum1>-1 && i<mum1) {
     101             :             valid = false;
     102           0 :             if (useStdErr) cerr << "Problem: first_mother(" << mum1 << ") after daughter(" << i << ")" << endl;
     103             :          }
     104           0 :          if (mum2>-1 && i<mum2 && requireSecondMotherBeforeDaughters) {
     105             :             valid = false;
     106           0 :             if (useStdErr) cerr << "Problem: second_mother(" << mum2 << ") after daughter(" << i << ")" << endl;
     107             :          }
     108           0 :          if (fd > ld ) {
     109             :             valid = false;
     110           0 :             if (useStdErr) cerr << "Problem: first_daughter(" << fd << ") > last_daughter(" << ld << ")" << endl;
     111             :          }
     112           0 :          for (Int_t id=TMath::Max(fd,0); id<=ld; id++) {
     113           0 :             TParticle * daughter = (TParticle*)array->AddrAt(id);
     114           0 :             if (daughter->GetFirstMother() != i && daughter->GetSecondMother() != i) {
     115             :                valid = false;
     116           0 :                if (useStdErr) cerr << "Problem: mother("<< i << ") not registered as mother for either first_daughter("
     117           0 :                      << daughter->GetFirstMother() << ") or second_daughter("
     118           0 :                      << daughter->GetSecondMother() << ")" << endl;
     119             :             }
     120             :          }
     121             :       }
     122             :    }
     123           0 :    delete array;
     124           0 :    array = 0;
     125           0 :    return valid;
     126           0 : }
     127             : 
     128             : bool THepMCParser::IsValidParticleInvariantMass(bool useStdErr, bool includeStatusCode2Particles)
     129             : {
     130             :    bool valid = true;
     131           0 :    TClonesArray *array = new TClonesArray("TParticle");
     132           0 :    TBranch* branch = fTree->GetBranch("Particles");
     133           0 :    branch->SetAddress(&array);
     134           0 :    Int_t count = branch->GetEntries();
     135           0 :    for (Int_t idx=0; idx<count; ++idx) {
     136           0 :       array->Clear();
     137           0 :       branch->GetEntry(idx);
     138           0 :       Int_t nkeep = array->GetEntries();
     139           0 :       for (Int_t i=0; i<nkeep; i++) {
     140           0 :          TParticle * parton = (TParticle*)array->AddrAt(i);
     141           0 :          if (parton->GetStatusCode()==2 && !includeStatusCode2Particles) {
     142           0 :             continue;
     143             :          }
     144           0 :          TLorentzVector v;
     145           0 :          parton->Momentum(v);
     146           0 :          Double_t m1 = v.M(); // invariant mass from the particle in the HepMC event
     147           0 :          TParticlePDG *dbParton = parton->GetPDG();
     148           0 :          if (!dbParton) {
     149           0 :             if (useStdErr) cerr << "Warning: could not look up particle with PDG Code: " << parton->GetPdgCode() << endl << endl;
     150           0 :             continue;
     151             :          }
     152           0 :          Double_t m2 = dbParton->Mass();
     153             :          bool checkok;
     154           0 :          if (m2 == 0) {
     155           0 :             checkok = abs(m1) < 0.0001; // no such thing as negative mass...
     156           0 :          } else {
     157           0 :             checkok = abs(1 - m1/m2) < 0.01;
     158             :          }
     159           0 :          if (!checkok && useStdErr) {
     160           0 :             cerr << "Problem: " << GetParticleName(parton) << " HepMC:" << m1 << endl;
     161           0 :             cerr << ListReactionChain(array,i);
     162           0 :             cerr << endl;
     163             :          }
     164           0 :          if (!checkok)
     165           0 :             valid = false;
     166           0 :       }
     167             :    }
     168           0 :    delete array;
     169           0 :    array = 0;
     170           0 :    return valid;
     171           0 : }
     172             : 
     173             : bool THepMCParser::IsValidVertexInvariantMass(bool useStdErr, bool includeStatusCode2Particles)
     174             : {
     175             :    bool valid = true;
     176           0 :    TClonesArray * array = new TClonesArray("TParticle");
     177           0 :    TBranch* branch = fTree->GetBranch("Particles");
     178           0 :    branch->SetAddress(&array);
     179           0 :    Int_t count = branch->GetEntries();
     180           0 :    for (Int_t idx=0; idx<count; ++idx) {
     181           0 :       array->Clear();
     182           0 :       branch->GetEntry(idx); // "fill" the array
     183           0 :       TLorentzVector v_st1;
     184           0 :       TLorentzVector v_st4;
     185           0 :       Int_t nkeep = array->GetEntriesFast();
     186           0 :       for (Int_t i=0; i<nkeep; i++) {
     187           0 :          TParticle * parton = (TParticle*)array->AddrAt(i);
     188           0 :          TLorentzVector v_in;
     189           0 :          parton->Momentum(v_in);
     190           0 :          if (parton->GetStatusCode()==4) {
     191           0 :             v_st4 += v_in;
     192           0 :          } else if (parton->GetStatusCode()==1) {
     193           0 :             v_st1 += v_in;
     194             :          }
     195           0 :          if (!includeStatusCode2Particles) { // only check beam particles vs final particles
     196           0 :             continue;
     197             :          }
     198           0 :          Int_t fd = parton->GetFirstDaughter();
     199           0 :          Int_t ld = parton->GetLastDaughter();
     200           0 :          if (fd == -1) continue; // no daughters, continue loop
     201             :          Int_t mother2 = -1;
     202           0 :          TLorentzVector v_out;
     203             :          bool oneok = false; bool allok = true; bool agreemother2 = true;
     204           0 :          ostringstream daughterpdg;
     205           0 :          ostringstream motherpdg;
     206           0 :          for (Int_t id=TMath::Max(fd,0); id<=ld; id++) {
     207           0 :             TParticle * daughter = (TParticle*)array->AddrAt(id);
     208           0 :             if (fd==id) {
     209           0 :                daughter->Momentum(v_out);
     210           0 :                mother2 = daughter->GetSecondMother();
     211           0 :             } else {
     212           0 :                TLorentzVector d;
     213           0 :                daughter->Momentum(d);
     214           0 :                v_out += d;
     215           0 :                if (daughter->GetSecondMother() != mother2) agreemother2 = false;
     216           0 :             }
     217           0 :             if (daughter->GetFirstMother() == i) {
     218             :                oneok = true;
     219           0 :             } else {
     220             :                allok = false;
     221             :             }
     222           0 :             daughterpdg << " " << daughter->GetPdgCode();
     223             :          }
     224           0 :          motherpdg << " " << parton->GetPdgCode();
     225           0 :          if (mother2 > -1 && agreemother2) {
     226           0 :             TParticle * m2 = (TParticle*)array->AddrAt(mother2);
     227           0 :             TLorentzVector m2v;
     228           0 :             m2->Momentum(m2v);
     229           0 :             v_in += m2v;
     230           0 :             motherpdg << " " << m2->GetPdgCode();
     231           0 :          }
     232           0 :          if (oneok && allok && agreemother2) {
     233           0 :             bool checkok = abs(1 - v_in.M()/v_out.M()) < 0.1;
     234           0 :             if (!checkok) valid=false;
     235           0 :             if (!checkok && useStdErr) {
     236             :                //             cerr << "Problem: " << i << "[" << fd << "," << ld << "] PDG:" << motherpdg.str() << " ->" << daughterpdg.str() << "  Inv.mass: " << v_in.M() << " -> " << v_out.M() << endl;
     237           0 :                cerr << ListReactionChain(array,i);
     238           0 :                cerr << endl;
     239             :                //             cerr << v_in.Px() << " " << v_in.Py() << " " << v_in.Pz() << " " << v_in.E() << endl;
     240             :             } else if (useStdErr) {
     241             :                //             cerr << "OK: " << i << "[" << fd << "," << ld << "] PDG:" << motherpdg.str() << " ->" << daughterpdg.str() << "  Inv.mass: " << v_in.M() << " -> " << v_out.M() << endl;
     242             :             }
     243           0 :          }
     244           0 :       }
     245           0 :       bool checkok = abs(1 - v_st4.M()/v_st1.M()) < 0.001;
     246           0 :       if (!checkok) valid=false;
     247           0 :       if (!checkok && useStdErr) {
     248           0 :          cerr << " BEAM PARTICLES -> FINAL PARTICLES " << endl;
     249           0 :          cerr << " status 4 (" << v_st4.M() << ") -> status 1 (" << v_st1.M() << ")" << endl << endl;
     250             :       }
     251           0 :    }
     252           0 :    delete array;
     253           0 :    array = 0;
     254           0 :    return valid;
     255           0 : }
     256             : 
     257             : string THepMCParser::GetParticleName(TParticle * thisPart)
     258             : {
     259           0 :    TParticlePDG *dbPart = thisPart->GetPDG();
     260           0 :    ostringstream name;
     261           0 :    if (dbPart) {
     262           0 :       name << dbPart->GetName() << "(" << dbPart->PdgCode() << "," << dbPart->Mass() << ")";
     263             :    } else {
     264           0 :       name << thisPart->GetPdgCode() << "(NoDBinfo)";
     265             :    }
     266           0 :    return name.str();
     267           0 : }
     268             : 
     269             : string THepMCParser::ListReactionChain(TClonesArray * particles, Int_t particleId)
     270             : {
     271           0 :    ostringstream output;
     272             : 
     273           0 :    TParticle * part = (TParticle*)particles->AddrAt(particleId);
     274           0 :    Int_t m1id = part->GetFirstMother();
     275           0 :    Int_t m2id = part->GetSecondMother();
     276           0 :    if (m1id > 1) { // ignore the initial collision with beam particles
     277           0 :       ostringstream inStr;
     278           0 :       ostringstream outStr;
     279           0 :       TParticle * m1 = (TParticle*)particles->AddrAt(m1id);
     280           0 :       TLorentzVector v_in;
     281           0 :       m1->Momentum(v_in);
     282           0 :       inStr << GetParticleName(m1) << "[" << v_in.M() << "]";
     283           0 :       if (m2id > 1) {
     284           0 :          TParticle * m2 = (TParticle*)particles->AddrAt(m2id);
     285           0 :          TLorentzVector v_m2;
     286           0 :          m2->Momentum(v_m2);
     287           0 :          v_in += v_m2;
     288           0 :          inStr << " " << GetParticleName(m2) << "[" << v_m2.M() << "]";
     289           0 :       }
     290           0 :       Int_t fd = m1->GetFirstDaughter();
     291           0 :       Int_t ld = m1->GetLastDaughter();
     292           0 :       TLorentzVector v_out;
     293           0 :       part->Momentum(v_out);
     294           0 :       outStr << GetParticleName(part) << "[" << v_out.M() << "]";
     295           0 :       for (Int_t i=fd; i<=ld; ++i) {
     296           0 :          if (i!=particleId) {
     297           0 :             TParticle * d = (TParticle*)particles->AddrAt(i);
     298           0 :             TLorentzVector v_d;
     299           0 :             d->Momentum(v_d);
     300           0 :             v_out += v_d;
     301           0 :             outStr << " " << GetParticleName(d) << "[" << v_d.M() << "]";
     302           0 :          }
     303             :       }
     304           0 :       output << "Parent reaction, inv mass: " << v_in.M() << " -> " << v_out.M() << endl;
     305           0 :       output << " - partons: " << inStr.str() << " -> " << outStr.str() << endl;
     306           0 :    }
     307           0 :    Int_t fd = part->GetFirstDaughter();
     308           0 :    Int_t ld = part->GetLastDaughter();
     309           0 :    if (fd > -1) {
     310           0 :       ostringstream inStr;
     311           0 :       ostringstream outStr;
     312           0 :       TLorentzVector v_in;
     313           0 :       part->Momentum(v_in);
     314           0 :       inStr << GetParticleName(part) << "[" << v_in.M() << "]";
     315             : 
     316           0 :       TParticle * f = (TParticle*)particles->AddrAt(fd);
     317           0 :       m2id = f->GetSecondMother();
     318           0 :       if (m2id == particleId) {
     319           0 :          m2id = f->GetFirstMother();
     320           0 :       }
     321           0 :       if (m2id > -1) {
     322           0 :          TParticle * m2 = (TParticle*)particles->AddrAt(m2id);
     323           0 :          TLorentzVector v_m2;
     324           0 :          m2->Momentum(v_m2);
     325           0 :          v_in += v_m2;
     326           0 :          inStr << " " << GetParticleName(m2) << "[" << v_m2.M() << "]";
     327           0 :       }
     328           0 :       TLorentzVector v_out;
     329           0 :       f->Momentum(v_out);
     330           0 :       outStr << GetParticleName(f) << "[" << v_out.M() << "]";
     331           0 :       for (Int_t i=fd+1; i<=ld; ++i) {
     332           0 :          TParticle * d = (TParticle*)particles->AddrAt(i);
     333           0 :          TLorentzVector v_d;
     334           0 :          d->Momentum(v_d);
     335           0 :          v_out += v_d;
     336           0 :          outStr << " " << GetParticleName(d) << "[" << v_d.M() << "]";
     337           0 :       }
     338           0 :       output << "Child reaction, inv mass: " << v_in.M() << " -> " << v_out.M() << endl;
     339           0 :       output << " - partons: " << inStr.str() << " -> " << outStr.str() << endl;
     340           0 :    } else {
     341           0 :       output << "Child reaction" << endl << " - none" << endl;
     342             :    }
     343             : 
     344           0 :    return output.str();
     345           0 : }
     346             : 
     347             : 
     348             : string THepMCParser::ParseGenEvent2TCloneArray(HepMC::GenEvent * genEvent, TClonesArray * array, string momUnit, string lenUnit, bool requireSecondMotherBeforeDaughters)
     349             : {
     350           0 :    ostringstream errMsgStream;
     351           0 :    if (requireSecondMotherBeforeDaughters) {
     352           0 :       errMsgStream <<  " WARNING: requireSecondMotherBeforeDaughters not fully implemented yet!\n";
     353             :    }
     354           0 :    genEvent->use_units(momUnit, lenUnit);
     355           0 :    array->Clear();
     356           0 :    map<int,Int_t> partonMemory; // unordered_map in c++11 - but probably not much performance gain from that: log(n) vs log(1) where constant can be high
     357             :    Bool_t beamParticlesToTheSameVertex = kTRUE; // This is false if the beam particles do not end up in the same vertex. This happens for some HepMC files produced by agile-runmc
     358             : 
     359             :    
     360             :    // Check event with HepMC's internal validation algorithm
     361           0 :    if (!genEvent->is_valid()) {
     362           0 :       errMsgStream << "Error with event id: " << genEvent->event_number() << ", event is not valid!\n";
     363           0 :       return errMsgStream.str();
     364             :    }
     365             : 
     366             :    // Pull out the beam particles from the event
     367           0 :    const pair<HepMC::GenParticle *,HepMC::GenParticle *> beamparts = genEvent->beam_particles();
     368             : 
     369             :    // Four sanity checks:
     370             :    // - Beam particles exists and are not the same
     371             :    // - Both beam particles should have no production vertices, they come from the beams
     372             :    // - Both beam particles should have defined end vertices, as they both should contribute
     373             :    // - Both beam particles should have the exact same end vertex
     374           0 :    if (!beamparts.first || !beamparts.second || beamparts.first->barcode()==beamparts.second->barcode()) {
     375           0 :       errMsgStream << "Error with event id: " << genEvent->event_number() << ", beam particles doesn't exists or are the same\n";
     376           0 :       return errMsgStream.str();
     377             :    }
     378           0 :    if (beamparts.first->production_vertex() || beamparts.second->production_vertex()) {
     379           0 :       errMsgStream << "Error with event id: " << genEvent->event_number() << ", beam particles have production vertex/vertices...\n";
     380           0 :       return errMsgStream.str();
     381             :    }
     382           0 :    if (!beamparts.first->end_vertex() || !beamparts.second->end_vertex()) {
     383           0 :       errMsgStream << "Error with event id: " << genEvent->event_number() << ", beam particles have undefined end vertex/vertices...\n";
     384           0 :       return errMsgStream.str();
     385             :    }
     386           0 :    if (beamparts.first->end_vertex() != beamparts.second->end_vertex()) {
     387             :      
     388           0 :       errMsgStream << "Warning with event id: " << genEvent->event_number() << ", beam particles do not collide in the same end vertex.\n";// This was downgraded to a warning, because I noticed in Pythia 6 HepMC (generated via agile-runmc) files the barcode of the vertex was different, but the 4-vector of the vertices was the same.
     389             :       beamParticlesToTheSameVertex = kFALSE;
     390           0 :       if (beamparts.first->end_vertex()->position() != beamparts.second->end_vertex()->position()){
     391           0 :         errMsgStream << "Error with event id: " << genEvent->event_number() << ", beam particles do not collide in the same end vertex and the two vertices have different four vectors.\n"; 
     392           0 :         return errMsgStream.str();
     393             :       }
     394             :    }
     395             : 
     396             :    // Set the array to hold the number of particles in the event
     397           0 :    Int_t nParticlesInHepMC = genEvent->particles_size(); // FIXME
     398           0 :    array->Expand(genEvent->particles_size());
     399             : 
     400             :    // Create a TParticle for each beam particle
     401           0 :    new((*array)[0]) TParticle(
     402           0 :          beamparts.first->pdg_id(),
     403           0 :          beamparts.first->status(), // check if status has the same meaning
     404             :          -1, // no mother1
     405             :          -1, // no mother2
     406             :          -1, // first daughter not known yet
     407             :          -1, // last daughter not known yet
     408           0 :          beamparts.first->momentum().px(),
     409           0 :          beamparts.first->momentum().py(),
     410           0 :          beamparts.first->momentum().pz(),
     411           0 :          beamparts.first->momentum().e(),
     412             :          0, // no production vertex, so zero?
     413             :          0,
     414             :          0,
     415             :          0
     416             :    );
     417           0 :    partonMemory[beamparts.first->barcode()] = 0;
     418           0 :    new((*array)[1]) TParticle(
     419           0 :          beamparts.second->pdg_id(),
     420           0 :          beamparts.second->status(),
     421             :          -1, // no mother1
     422             :          -1, // no mother2
     423             :          -1, // first daughter not known yet
     424             :          -1, // last daughter not known yet
     425           0 :          beamparts.second->momentum().px(),
     426           0 :          beamparts.second->momentum().py(),
     427           0 :          beamparts.second->momentum().pz(),
     428           0 :          beamparts.second->momentum().e(),
     429             :          0, // no production vertex, so zero?
     430             :          0,
     431             :          0,
     432             :          0
     433             :    );
     434           0 :    partonMemory[beamparts.second->barcode()] = 1;
     435             :    
     436             :    Int_t arrayID = 2; // start counting IDs after the beam particles
     437             : 
     438             :    // If the beam particles end
     439             :    // in the same vertex, this has to be done only once, otherwise, it
     440             :    // has to be done twice (else we lose the "second beam part"
     441             :    // branch)
     442             : 
     443           0 :    for (Int_t ibeamPart =0 ; ibeamPart < 2; ibeamPart++) {
     444             :      //     std::cout << "1" << std::endl;
     445             :      
     446             :      HepMC::GenVertex * startVertex = 0;
     447           0 :      if (ibeamPart == 0) startVertex = beamparts.first  ->end_vertex();
     448             :      else                {
     449           0 :        startVertex = beamparts.second ->end_vertex();
     450           0 :        if (beamParticlesToTheSameVertex) break; // both beam particles end to the same vertex: no need to do this twice.
     451             :      }
     452             :      //     std::cout << "2" << std::endl;
     453             :      
     454             :      // Do first vertex as a special case for performance, since its often has the most daughters and both mothers are known
     455             :      Int_t firstDaughter = arrayID;
     456           0 :      for (HepMC::GenVertex::particles_out_const_iterator iter = startVertex->particles_out_const_begin();
     457           0 :           iter != startVertex->particles_out_const_end();
     458           0 :           ++iter) {
     459           0 :        new((*array)[arrayID]) TParticle(
     460           0 :                                         (*iter)->pdg_id(),
     461           0 :                                         (*iter)->status(),
     462             :                                         0, // beam particle 1
     463             :                                         1, // beam particle 2
     464             :                                         -1, // first daughter not known yet
     465             :                                         -1, // last daughter not known yet
     466           0 :                                         (*iter)->momentum().px(),
     467           0 :                                         (*iter)->momentum().py(),
     468           0 :                                         (*iter)->momentum().pz(),
     469           0 :                                         (*iter)->momentum().e(),
     470           0 :                                         beamparts.first->end_vertex()->position().x(),
     471           0 :                                         beamparts.first->end_vertex()->position().y(),
     472           0 :                                         beamparts.first->end_vertex()->position().z(),
     473           0 :                                         beamparts.first->end_vertex()->position().t()
     474             :                                         );
     475           0 :        partonMemory[(*iter)->barcode()] = arrayID;
     476           0 :        ++arrayID;
     477             :      }
     478           0 :      Int_t lastDaughter = arrayID-1;
     479           0 :      if (ibeamPart == 0){
     480           0 :        ((TParticle*)array->AddrAt(0))->SetFirstDaughter(firstDaughter); // beam particle 1
     481           0 :        ((TParticle*)array->AddrAt(0))->SetLastDaughter(lastDaughter);
     482             :        // If both beam particles end in the same vertex, we have to reference the daughters of the second beam particle here (this loop is only done once). Otherwise, we do it when ibeamPart is == 1
     483           0 :        if(beamParticlesToTheSameVertex) {
     484           0 :          ((TParticle*)array->AddrAt(1))->SetFirstDaughter(firstDaughter); // beam particle 2
     485           0 :          ((TParticle*)array->AddrAt(1))->SetLastDaughter(lastDaughter);
     486           0 :        }
     487             :      } else {
     488           0 :        ((TParticle*)array->AddrAt(1))->SetFirstDaughter(firstDaughter); // beam particle 2
     489           0 :        ((TParticle*)array->AddrAt(1))->SetLastDaughter(lastDaughter);
     490             : 
     491             :      }
     492             :      
     493             :      // Then we loop over all other vertices. 
     494             :      // Build vertex list by exploring tree and sorting such that
     495             :      // daughters comes after mothers
     496           0 :      list<HepMC::GenVertex*> vertexList;
     497           0 :      set<int> vertexSearchSet;
     498           0 :      ExploreVertex(startVertex,vertexList,vertexSearchSet,requireSecondMotherBeforeDaughters);
     499             : 
     500             :      // Analyze each vertex
     501           0 :      for (list<HepMC::GenVertex*>::iterator i = vertexList.begin(); i != vertexList.end(); ++i) {
     502           0 :        HepMC::GenVertex * vertex = (*i);
     503             :        //       std::cout << "Vertex: " << vertex->barcode() << std::endl;
     504             :        
     505             :        //      std::cout << "Processing vertex: " << vertex->barcode() << std::endl;
     506             :       
     507             :        // first establish mother-daughter relations (look at particles incoming in the vertex)
     508           0 :        HepMC::GenVertex::particles_in_const_iterator iterInParticles = vertex->particles_in_const_begin();
     509           0 :        if (iterInParticles == vertex->particles_in_const_end()) {
     510           0 :          return "Particle without a mother, and its not a beam particle!\n";
     511             :        }
     512           0 :        int motherA = partonMemory[(*iterInParticles)->barcode()];
     513             :        //      std::cout << "MotherA: "  << (*iterInParticles)->barcode() << ", " << motherA << std::endl;
     514             :       
     515           0 :        if (((TParticle*)array->AddrAt(motherA))->GetFirstDaughter() > -1 && motherA > 1) { // FIXME Temp hack: if motherA <2 it means it was not in the array (0 is the beam particle)
     516           0 :          errMsgStream << Form("Trying to assign new daughters to a particle that already has daughters defined! (motherA, barcode = %d, event = %d)\n",(*iterInParticles)->barcode(), genEvent->event_number());
     517           0 :          return errMsgStream.str();
     518             :          ((TParticle*)array->AddrAt(motherA))->Print();
     519             :        }
     520           0 :        ++iterInParticles;
     521             :        int motherB = -1;
     522           0 :        if (iterInParticles != vertex->particles_in_const_end()) {
     523           0 :          motherB = partonMemory[(*iterInParticles)->barcode()];
     524             :          //         std::cout << "MotherB: "  << (*iterInParticles)->barcode() << std::endl;
     525           0 :          if (((TParticle*)array->AddrAt(motherB))->GetFirstDaughter() > -1 && motherB > 1) { // FIXME Temp hack: if motherB < 2 it means it was not in the array (0 is the beam particle)
     526           0 :            errMsgStream << Form("Trying to assign new daughters to a particle that already has daughters defined! (motherB, barcode = %d, event = %d)\n",(*iterInParticles)->barcode(), genEvent->event_number());
     527           0 :            return errMsgStream.str();
     528             :          }
     529           0 :          ++iterInParticles;
     530           0 :          if (iterInParticles != vertex->particles_in_const_end() && (*iterInParticles)->pdg_id() != 93) { // If it's a string it could have many partons attached.. In that case, we ignore mother-daughter relationships
     531             :            //           std::cout << "Daughters" << std::endl;
     532           0 :            errMsgStream << Form ("Particle with more than two mothers! (Vertex Barcode: %d, PDG: %d)\n", (*iterInParticles)->barcode(), (*iterInParticles)->pdg_id()) ;
     533             :            //           return Form ("Particle with more than two mothers! (Vertex Barcode: %d, PDG: %d)", (*iterInParticles)->barcode(), (*iterInParticles)->pdg_id()) ;
     534             :             
     535             :          }
     536             :        }
     537           0 :        if (motherB > -1 && motherB < motherA) {
     538             :          int swap = motherA; motherA = motherB; motherB = swap;
     539           0 :        }
     540             : 
     541             :        // add the particles to the array, important that they are add in succession with respect to arrayID
     542             :        
     543             :        firstDaughter = arrayID;
     544           0 :        for (HepMC::GenVertex::particles_in_const_iterator iterOutParticles = vertex->particles_out_const_begin();
     545           0 :             iterOutParticles != vertex->particles_out_const_end();
     546           0 :             ++iterOutParticles) {
     547             :          //        std::cout << "Adding daughter: " << (*iterOutParticles)->barcode() << std::endl;
     548             :         
     549           0 :          new((*array)[arrayID]) TParticle(
     550           0 :                                           (*iterOutParticles)->pdg_id(),
     551           0 :                                           (*iterOutParticles)->status(),
     552             :                                           motherA, // mother 1
     553             :                                           motherB, // mother 2
     554             :                                           -1, // first daughter, if applicable, not known yet
     555             :                                           -1, // last daughter, if applicable, not known yet
     556           0 :                                           (*iterOutParticles)->momentum().px(),
     557           0 :                                           (*iterOutParticles)->momentum().py(),
     558           0 :                                           (*iterOutParticles)->momentum().pz(),
     559           0 :                                           (*iterOutParticles)->momentum().e(),
     560           0 :                                           vertex->position().x(),
     561           0 :                                           vertex->position().y(),
     562           0 :                                           vertex->position().z(),
     563           0 :                                           vertex->position().t()
     564             :                                           );
     565           0 :          partonMemory[(*iterOutParticles)->barcode()] = arrayID;
     566           0 :          ++arrayID;
     567             :        }
     568           0 :        lastDaughter = arrayID-1;
     569           0 :        if (lastDaughter < firstDaughter) {
     570           0 :          return "Vertex with no out particles, should not be possible!";
     571             :        }
     572             :        // update mother with daughter interval
     573           0 :        ((TParticle*)array->AddrAt(motherA))->SetFirstDaughter(firstDaughter);
     574           0 :        ((TParticle*)array->AddrAt(motherA))->SetLastDaughter(lastDaughter);
     575           0 :        if (motherB > -1) {
     576           0 :          ((TParticle*)array->AddrAt(motherB))->SetFirstDaughter(firstDaughter);
     577           0 :          ((TParticle*)array->AddrAt(motherB))->SetLastDaughter(lastDaughter);
     578           0 :        }
     579           0 :      }
     580           0 :    }
     581             : 
     582             :    // Printf("Particles in event: %d, added: %d, entries: %d/%d", nParticlesInHepMC, arrayID, array->GetEntries(), array->GetEntriesFast());
     583           0 :    std::cout << errMsgStream.str() << std::endl;
     584             :    
     585           0 :    return "";
     586           0 : }
     587             : 
     588             : 
     589             : void THepMCParser::ExploreVertex(HepMC::GenVertex * vertex, list<HepMC::GenVertex*> & vertexList, set<int> & vertexSearchSet, bool requireSecondMotherBeforeDaughters)
     590             : {
     591             :    // Prepare vertex list, and sort vertices so that mothers come before daughters (if required)
     592             : 
     593             :    // Loop over all particles exiting from our start vertex 
     594           0 :    for (HepMC::GenVertex::particles_out_const_iterator partOut = vertex->particles_out_const_begin();
     595           0 :          partOut != vertex->particles_out_const_end();
     596           0 :          ++partOut) {
     597           0 :       HepMC::GenVertex * testVertex = (*partOut)->end_vertex();
     598           0 :       if (testVertex) {
     599           0 :          bool foundVertex = vertexSearchSet.find((*partOut)->end_vertex()->barcode()) != vertexSearchSet.end(); // If this is true, the vertex was already found
     600           0 :          if (requireSecondMotherBeforeDaughters) {
     601             :             // redo this algorithem to move subtree instead of node....
     602             :             // its not completely error proof in its current implementation even though the error is extremely rare
     603             : 
     604             :             // Loop over all already found vertices if the vertex was already found, and remove the previous instance
     605           0 :             if (foundVertex) for (list<HepMC::GenVertex*>::iterator ivert = vertexList.begin(); ivert != vertexList.end(); ++ivert) {
     606           0 :                if ((*ivert)->barcode() == testVertex->barcode()) {
     607           0 :                   vertexList.erase(ivert);
     608           0 :                   cout << " it happened, the vertex parsing order had to be changed " << endl;
     609           0 :                   break;
     610             :                }
     611           0 :             } else {
     612             :               //otherwise, just add it to the list
     613           0 :                vertexSearchSet.insert((*partOut)->end_vertex()->barcode());
     614             :             }
     615           0 :             vertexList.push_back(testVertex);
     616             :             // Follow daughter recursively
     617           0 :             if (!foundVertex) ExploreVertex(testVertex,vertexList,vertexSearchSet,requireSecondMotherBeforeDaughters);
     618             : 
     619             :          } else {
     620           0 :             if (!foundVertex) {
     621             :               // If we don't care about having all mothers first, we just add it to list and set if not already found
     622           0 :                vertexSearchSet.insert((*partOut)->end_vertex()->barcode());
     623           0 :                vertexList.push_back(testVertex);
     624           0 :                ExploreVertex(testVertex,vertexList,vertexSearchSet,requireSecondMotherBeforeDaughters);
     625           0 :             }
     626             :          }
     627           0 :       }
     628           0 :    }
     629           0 : }
     630             : 
     631             : 
     632             : 
     633             : const char * THepMCParser::fgHeavyIonHeaderBranchString = "Ncoll_hard/I:Npart_proj:Npart_targ:Ncoll:spectator_neutrons:spectator_protons:N_Nwounded_collisions:Nwounded_N_collisions:Nwounded_Nwounded_collisions:impact_parameter/F:event_plane_angle:eccentricity:sigma_inel_NN";
     634             : const char * THepMCParser::fgPdfHeaderBranchString = "id1/I:id2:pdf_id1:pdf_id2:x1/D:x2:scalePDF:pdf1:pdf2";
     635             : 
     636             : string THepMCParser::ParseGenEvent2HeaderStructs(HepMC::GenEvent * genEvent, HeavyIonHeader_t & heavyIonHeader, PdfHeader_t & pdfHeader, bool fillZeroOnMissingHeavyIon, bool fillZeroOnMissingPdf)
     637             : {
     638           0 :    HepMC::HeavyIon * heavyIon = genEvent->heavy_ion();
     639           0 :    HepMC::PdfInfo * pdfInfo = genEvent->pdf_info();
     640           0 :    if ((!heavyIon && !fillZeroOnMissingHeavyIon) || (!pdfInfo && !fillZeroOnMissingPdf)) {
     641           0 :       return "HeavyIonInfo and/or PdfInfo not defined for this event, did you read it with IO_GenEvent?";
     642             :    }
     643           0 :    if (heavyIon) {
     644           0 :       heavyIonHeader.Ncoll_hard = heavyIon->Ncoll_hard();
     645           0 :       heavyIonHeader.Npart_proj = heavyIon->Npart_proj();
     646           0 :       heavyIonHeader.Npart_targ = heavyIon->Npart_targ();
     647           0 :       heavyIonHeader.Ncoll = heavyIon->Ncoll();
     648           0 :       heavyIonHeader.spectator_neutrons = heavyIon->spectator_neutrons();
     649           0 :       heavyIonHeader.spectator_protons = heavyIon->spectator_protons();
     650           0 :       heavyIonHeader.N_Nwounded_collisions = heavyIon->N_Nwounded_collisions();
     651           0 :       heavyIonHeader.Nwounded_N_collisions = heavyIon->Nwounded_N_collisions();
     652           0 :       heavyIonHeader.Nwounded_Nwounded_collisions = heavyIon->Nwounded_Nwounded_collisions();
     653           0 :       heavyIonHeader.impact_parameter = heavyIon->impact_parameter();
     654           0 :       heavyIonHeader.event_plane_angle = heavyIon->event_plane_angle();
     655           0 :       heavyIonHeader.eccentricity = heavyIon->eccentricity();
     656           0 :       heavyIonHeader.sigma_inel_NN = heavyIon->sigma_inel_NN();
     657           0 :    } else {
     658           0 :       heavyIonHeader.Ncoll_hard = 0;
     659           0 :       heavyIonHeader.Npart_proj = 0;
     660           0 :       heavyIonHeader.Npart_targ = 0;
     661           0 :       heavyIonHeader.Ncoll = 0;
     662           0 :       heavyIonHeader.spectator_neutrons = 0;
     663           0 :       heavyIonHeader.spectator_protons = 0;
     664           0 :       heavyIonHeader.N_Nwounded_collisions = 0;
     665           0 :       heavyIonHeader.Nwounded_N_collisions = 0;
     666           0 :       heavyIonHeader.Nwounded_Nwounded_collisions = 0;
     667           0 :       heavyIonHeader.impact_parameter = 0.0;
     668           0 :       heavyIonHeader.event_plane_angle = 0.0;
     669           0 :       heavyIonHeader.eccentricity = 0.0;
     670           0 :       heavyIonHeader.sigma_inel_NN = 0.0;
     671             :    }
     672           0 :    if (pdfInfo) {
     673           0 :       pdfHeader.id1 = pdfInfo->id1();
     674           0 :       pdfHeader.id2 = pdfInfo->id2();
     675           0 :       pdfHeader.pdf_id1 = pdfInfo->pdf_id1();
     676           0 :       pdfHeader.pdf_id2 = pdfInfo->pdf_id2();
     677           0 :       pdfHeader.x1 = pdfInfo->x1();
     678           0 :       pdfHeader.x2 = pdfInfo->x2();
     679           0 :       pdfHeader.scalePDF = pdfInfo->scalePDF();
     680           0 :       pdfHeader.pdf1 = pdfInfo->pdf1();
     681           0 :       pdfHeader.pdf2 = pdfInfo->pdf2();
     682           0 :    } else {
     683           0 :       pdfHeader.id1 = 0;
     684           0 :       pdfHeader.id2 = 0;
     685           0 :       pdfHeader.pdf_id1 = 0;
     686           0 :       pdfHeader.pdf_id2 = 0;
     687           0 :       pdfHeader.x1 = 0.0;
     688           0 :       pdfHeader.x2 = 0.0;
     689           0 :       pdfHeader.scalePDF = 0.0;
     690           0 :       pdfHeader.pdf1 = 0.0;
     691           0 :       pdfHeader.pdf2 = 0.0;
     692             :    }
     693           0 :    return "";
     694           0 : }
     695             : 
     696             : 
     697             : 
     698             : 
     699             : 
     700             : 
     701             : 

Generated by: LCOV version 1.11