CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/GeneratorInterface/LHEInterface/src/LHEEvent.cc

Go to the documentation of this file.
00001 #include <algorithm>
00002 #include <iostream>
00003 #include <iomanip>
00004 #include <sstream>
00005 #include <cstring>
00006 #include <string>
00007 #include <vector>
00008 #include <memory>
00009 #include <cmath>
00010 
00011 #include <HepMC/GenEvent.h>
00012 #include <HepMC/GenVertex.h>
00013 #include <HepMC/GenParticle.h>
00014 #include <HepMC/SimpleVector.h>
00015 
00016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00017 
00018 #include "SimDataFormats/GeneratorProducts/interface/LesHouches.h"
00019 
00020 #include "GeneratorInterface/LHEInterface/interface/LHERunInfo.h"
00021 #include "GeneratorInterface/LHEInterface/interface/LHEEvent.h"
00022 
00023 static int skipWhitespace(std::istream &in)
00024 {
00025         int ch;
00026         do {
00027                 ch = in.get();
00028         } while(std::isspace(ch));
00029         if (ch != std::istream::traits_type::eof())
00030                 in.putback(ch);
00031         return ch;
00032 }
00033 
00034 namespace lhef {
00035 
00036 LHEEvent::LHEEvent(const boost::shared_ptr<LHERunInfo> &runInfo,
00037                    std::istream &in) :
00038   runInfo(runInfo), weights_(0), counted(false), 
00039   readAttemptCounter(0)
00040   
00041 {
00042         hepeup.NUP = 0;
00043         hepeup.XPDWUP.first = hepeup.XPDWUP.second = 0.0;
00044 
00045         in >> hepeup.NUP >> hepeup.IDPRUP >> hepeup.XWGTUP
00046            >> hepeup.SCALUP >> hepeup.AQEDUP >> hepeup.AQCDUP;
00047         if (!in.good())
00048                 throw cms::Exception("InvalidFormat")
00049                         << "Les Houches file contained invalid"
00050                            " event header." << std::endl;
00051 
00052         // store the original value of XWGTUP for the user
00053         originalXWGTUP_ = hepeup.XWGTUP;
00054 
00055         int idwtup = runInfo->getHEPRUP()->IDWTUP;
00056         if (idwtup >= 0 && hepeup.XWGTUP < 0) {
00057                 edm::LogWarning("Generator|LHEInterface")
00058                         << "Non-allowed negative event weight encountered."
00059                         << std::endl;
00060                 hepeup.XWGTUP = std::abs(hepeup.XWGTUP);
00061         }
00062 
00063         if (std::abs(idwtup) == 3 && std::abs(hepeup.XWGTUP) != 1.) {
00064                 edm::LogInfo("Generator|LHEInterface")
00065                         << "Event weight not set to one for abs(IDWTUP) == 3"
00066                         << std::endl;
00067                 hepeup.XWGTUP = hepeup.XWGTUP > 0. ? 1.0 : -1.0;
00068         }
00069 
00070         hepeup.resize();
00071 
00072         for(int i = 0; i < hepeup.NUP; i++) {
00073                 in >> hepeup.IDUP[i] >> hepeup.ISTUP[i]
00074                    >> hepeup.MOTHUP[i].first >> hepeup.MOTHUP[i].second
00075                    >> hepeup.ICOLUP[i].first >> hepeup.ICOLUP[i].second
00076                    >> hepeup.PUP[i][0] >> hepeup.PUP[i][1] >> hepeup.PUP[i][2]
00077                    >> hepeup.PUP[i][3] >> hepeup.PUP[i][4]
00078                    >> hepeup.VTIMUP[i] >> hepeup.SPINUP[i];
00079                 if (!in.good())
00080                         throw cms::Exception("InvalidFormat")
00081                                 << "Les Houches file contained invalid event"
00082                                    " in particle line " << (i + 1)
00083                                 << "." << std::endl;
00084         }
00085 
00086         while(skipWhitespace(in) == '#') {
00087           std::string line;
00088           std::getline(in, line);
00089           std::istringstream ss(line);
00090           std::string tag;
00091           ss >> tag;
00092           if (tag == "#pdf") {
00093             pdf.reset(new PDF);
00094             ss >> pdf->id.first >> pdf->id.second
00095                >> pdf->x.first >> pdf->x.second
00096                >> pdf->scalePDF
00097                >> pdf->xPDF.first >> pdf->xPDF.second;
00098             if (ss.bad()) {
00099               edm::LogWarning("Generator|LHEInterface")
00100                 << "Les Houches event contained"
00101                 " unparseable PDF information."
00102                                         << std::endl;
00103               pdf.reset();
00104             } else
00105               continue;
00106           }
00107           size_t found = line.find("amcatnlo");
00108           double NEVT = 1.0;
00109           if ( found != std::string::npos) {
00110             std::string avalue = line.substr(found+1,line.size());
00111             found = avalue.find("_");
00112             avalue = avalue.substr(found+1,avalue.size());
00113             NEVT = atof(avalue.c_str());
00114           }
00115           hepeup.XWGTUP = hepeup.XWGTUP*NEVT; 
00116           comments.push_back(line + "\n");
00117         }
00118         
00119         if (!in.eof())
00120           edm::LogWarning("Generator|LHEInterface")
00121             << "Les Houches file contained spurious"
00122             " content after event data." << std::endl;
00123 }
00124 
00125 LHEEvent::LHEEvent(const boost::shared_ptr<LHERunInfo> &runInfo,
00126                    const HEPEUP &hepeup) :
00127         runInfo(runInfo), hepeup(hepeup), counted(false), readAttemptCounter(0)
00128 {
00129 }
00130 
00131 LHEEvent::LHEEvent(const boost::shared_ptr<LHERunInfo> &runInfo,
00132                    const HEPEUP &hepeup,
00133                    const LHEEventProduct::PDF *pdf,
00134                    const std::vector<std::string> &comments) :
00135         runInfo(runInfo), hepeup(hepeup), pdf(pdf ? new PDF(*pdf) : 0),
00136         comments(comments), counted(false), readAttemptCounter(0)
00137 {
00138 }
00139 
00140 LHEEvent::LHEEvent(const boost::shared_ptr<LHERunInfo> &runInfo,
00141                    const LHEEventProduct &product) :
00142         runInfo(runInfo), hepeup(product.hepeup()),
00143         pdf(product.pdf() ? new PDF(*product.pdf()) : 0),
00144         weights_(product.weights()),
00145         comments(product.comments_begin(), product.comments_end()),
00146         counted(false), readAttemptCounter(0)
00147 {
00148 }
00149 
00150 LHEEvent::~LHEEvent()
00151 {
00152 }
00153 
00154 template<typename T>
00155 static inline void pop(std::vector<T> &vec, unsigned int index)
00156 {
00157         unsigned int size = vec.size() - 1;
00158         std::memmove(&vec[index], &vec[index + 1], (size - index) * sizeof(T));
00159 }
00160 
00161 void LHEEvent::removeParticle(HEPEUP &hepeup, int index)
00162 {
00163         index--;
00164         if (index < 0 || index >= hepeup.NUP) {
00165                 edm::LogError("Generator|LHEInterface")
00166                         << "removeParticle: Index " << (index + 1)
00167                         << " out of bounds." << std::endl;
00168                 return;
00169         }
00170 
00171         std::pair<int, int> mo = hepeup.MOTHUP[index];
00172 
00173         pop(hepeup.IDUP, index);
00174         pop(hepeup.ISTUP, index);
00175         pop(hepeup.MOTHUP, index);
00176         pop(hepeup.ICOLUP, index);
00177         pop(hepeup.PUP, index);
00178         pop(hepeup.VTIMUP, index);
00179         pop(hepeup.SPINUP, index);
00180         hepeup.NUP--;
00181         hepeup.resize();
00182 
00183         index++;
00184         for(int i = 0; i < hepeup.NUP; i++) {
00185                 if (hepeup.MOTHUP[i].first == index) {
00186                         if (hepeup.MOTHUP[i].second > 0)
00187                                 edm::LogError("Generator|LHEInterface")
00188                                         << "removeParticle: Particle "
00189                                         << (i + 2) << " has two mothers."
00190                                         << std::endl;
00191                         hepeup.MOTHUP[i] = mo;
00192                 }
00193 
00194                 if (hepeup.MOTHUP[i].first > index)
00195                         hepeup.MOTHUP[i].first--;
00196                 if (hepeup.MOTHUP[i].second > index)
00197                         hepeup.MOTHUP[i].second--;
00198         }
00199 }
00200 
00201 void LHEEvent::removeResonances(const std::vector<int> &ids)
00202 {
00203         for(int i = 1; i <= hepeup.NUP; i++) {
00204                 int id = std::abs(hepeup.IDUP[i - 1]);
00205                 if (hepeup.MOTHUP[i - 1].first > 0 &&
00206                     hepeup.MOTHUP[i - 1].second > 0 &&
00207                     std::find(ids.begin(), ids.end(), id) != ids.end())
00208                         removeParticle(hepeup, i--);
00209         }
00210 }
00211 
00212 void LHEEvent::count(LHERunInfo::CountMode mode,
00213                      double weight, double matchWeight)
00214 {
00215         if (counted)
00216                 edm::LogWarning("Generator|LHEInterface")
00217                         << "LHEEvent::count called twice on same event!"
00218                         << std::endl;
00219 
00220         runInfo->count(hepeup.IDPRUP, mode, hepeup.XWGTUP,
00221                        weight, matchWeight);
00222 
00223         counted = true;
00224 }
00225 
00226 void LHEEvent::fillPdfInfo(HepMC::PdfInfo *info) const
00227 {
00228         if (pdf.get()) {
00229                 info->set_id1(pdf->id.first);
00230                 info->set_id2(pdf->id.second);
00231                 info->set_x1(pdf->x.first);
00232                 info->set_x2(pdf->x.second);
00233                 info->set_pdf1(pdf->xPDF.first);
00234                 info->set_pdf2(pdf->xPDF.second);
00235                 info->set_scalePDF(pdf->scalePDF);
00236         } else if (hepeup.NUP >= 2) {
00237                 const HEPRUP *heprup = getHEPRUP();
00238                 info->set_id1(hepeup.IDUP[0] == 21 ? 0 : hepeup.IDUP[0]);
00239                 info->set_id2(hepeup.IDUP[1] == 21 ? 0 : hepeup.IDUP[1]);
00240                 info->set_x1(std::abs(hepeup.PUP[0][2] / heprup->EBMUP.first));
00241                 info->set_x2(std::abs(hepeup.PUP[1][2] / heprup->EBMUP.second));
00242                 info->set_pdf1(-1.0);
00243                 info->set_pdf2(-1.0);
00244                 info->set_scalePDF(hepeup.SCALUP);
00245         } else {
00246                 info->set_x1(-1.0);
00247                 info->set_x2(-1.0);
00248                 info->set_pdf1(-1.0);
00249                 info->set_pdf2(-1.0);
00250                 info->set_scalePDF(hepeup.SCALUP);
00251         }
00252 }
00253 
00254 void LHEEvent::fillEventInfo(HepMC::GenEvent *event) const
00255 {
00256         event->set_signal_process_id(hepeup.IDPRUP);
00257         event->set_event_scale(hepeup.SCALUP);
00258         event->set_alphaQED(hepeup.AQEDUP);
00259         event->set_alphaQCD(hepeup.AQCDUP);
00260 }
00261 
00262 std::auto_ptr<HepMC::GenEvent> LHEEvent::asHepMCEvent() const
00263 {
00264         std::auto_ptr<HepMC::GenEvent> hepmc(new HepMC::GenEvent);
00265 
00266         hepmc->set_signal_process_id(hepeup.IDPRUP);
00267         hepmc->set_event_scale(hepeup.SCALUP);
00268         hepmc->set_alphaQED(hepeup.AQEDUP);
00269         hepmc->set_alphaQCD(hepeup.AQCDUP);
00270 
00271         unsigned int nup = hepeup.NUP; // particles in event
00272 
00273         // any particles in HEPEUP block?
00274         if (!nup) {
00275                 edm::LogWarning("Generator|LHEInterface")
00276                         << "Les Houches Event does not contain any partons. "
00277                         << "Not much to convert." ;
00278                 return hepmc;
00279         }
00280 
00281         // stores (pointers to) converted particles
00282         std::vector<HepMC::GenParticle*> genParticles;
00283         std::vector<HepMC::GenVertex*> genVertices;
00284 
00285         // I. convert particles
00286         for(unsigned int i = 0; i < nup; i++)
00287                 genParticles.push_back(makeHepMCParticle(i));
00288 
00289         // II. loop again to build vertices
00290         for(unsigned int i = 0; i < nup; i++) {
00291                 unsigned int mother1 = hepeup.MOTHUP.at(i).first;
00292                 unsigned int mother2 = hepeup.MOTHUP.at(i).second;
00293                 double cTau = hepeup.VTIMUP.at(i);      // decay time
00294         
00295                 // current particle has a mother? --- Sorry, parent! We're PC.
00296                 if (mother1) {
00297                         mother1--;      // FORTRAN notation!
00298                 if (mother2)
00299                         mother2--;
00300                 else
00301                         mother2 = mother1;
00302 
00303                 HepMC::GenParticle *in_par = genParticles.at(mother1);
00304                 HepMC::GenVertex *current_vtx = in_par->end_vertex();  // vertex of first mother
00305 
00306                 if (!current_vtx) {
00307                         current_vtx = new HepMC::GenVertex(
00308                                         HepMC::FourVector(0, 0, 0, cTau));
00309 
00310                         // add vertex to event
00311                         genVertices.push_back(current_vtx);
00312                 }
00313 
00314                 for(unsigned int j = mother1; j <= mother2; j++)        // set mother-daughter relations
00315                         if (!genParticles.at(j)->end_vertex())
00316                                 current_vtx->add_particle_in(genParticles.at(j));
00317 
00318                         // connect THIS outgoing particle to current vertex
00319                         current_vtx->add_particle_out(genParticles.at(i));
00320                 }
00321         }
00322 
00323         checkHepMCTree(hepmc.get());
00324 
00325         // III. restore color flow
00326         // ok, nobody knows how to do it so far...
00327 
00328         // IV. fill run information
00329         const HEPRUP *heprup = getHEPRUP();
00330 
00331         // set beam particles
00332         HepMC::GenParticle *b1 = new HepMC::GenParticle(
00333                         HepMC::FourVector(0.0, 0.0, +heprup->EBMUP.first,
00334                                                      heprup->EBMUP.first),
00335                         heprup->IDBMUP.first);
00336         HepMC::GenParticle *b2 = new HepMC::GenParticle(
00337                         HepMC::FourVector(0.0, 0.0, -heprup->EBMUP.second,
00338                                                      heprup->EBMUP.second),
00339                         heprup->IDBMUP.second);
00340         b1->set_status(3);
00341         b2->set_status(3);
00342 
00343         HepMC::GenVertex *v1 = new HepMC::GenVertex();
00344         HepMC::GenVertex *v2 = new HepMC::GenVertex();
00345         v1->add_particle_in(b1);
00346         v2->add_particle_in(b2);
00347 
00348         hepmc->add_vertex(v1);
00349         hepmc->add_vertex(v2);
00350         hepmc->set_beam_particles(b1, b2);
00351 
00352         // first two particles have to be the hard partons going into the interaction
00353         if (genParticles.size() >= 2) {
00354                 if (!genParticles.at(0)->production_vertex() &&
00355                     !genParticles.at(1)->production_vertex()) {
00356                         v1->add_particle_out(genParticles.at(0));
00357                         v2->add_particle_out(genParticles.at(1));
00358                 } else
00359                         edm::LogWarning("Generator|LHEInterface")
00360                                 << "Initial partons do already have a"
00361                                    " production vertex. " << std::endl
00362                                 << "Beam particles not connected.";
00363         } else
00364                 edm::LogWarning("Generator|LHEInterface")
00365                         << "Can't find any initial partons to be"
00366                            " connected to the beam particles.";
00367 
00368         for(std::vector<HepMC::GenVertex*>::const_iterator iter = genVertices.begin();
00369             iter != genVertices.end(); ++iter)
00370                 hepmc->add_vertex(*iter);
00371 
00372         // do some more consistency checks
00373         for(unsigned int i = 0; i < nup; i++) {
00374                 if (!genParticles.at(i)->parent_event()) {
00375                         edm::LogWarning("Generator|LHEInterface")
00376                                 << "Not all LHE particles could be stored"
00377                                    "  stored in the HepMC event. "
00378                                 << std::endl
00379                                 << "Check the mother-daughter relations"
00380                                    " in the given LHE input file.";
00381                         break;
00382                 }
00383         }
00384 
00385         hepmc->set_signal_process_vertex(
00386                         const_cast<HepMC::GenVertex*>(
00387                                 findSignalVertex(hepmc.get(), false)));
00388 
00389         return hepmc;
00390 }
00391 
00392 HepMC::GenParticle *LHEEvent::makeHepMCParticle(unsigned int i) const
00393 {
00394         HepMC::GenParticle *particle = new HepMC::GenParticle(
00395                         HepMC::FourVector(hepeup.PUP.at(i)[0],
00396                                           hepeup.PUP.at(i)[1],
00397                                           hepeup.PUP.at(i)[2],
00398                                           hepeup.PUP.at(i)[3]),
00399                         hepeup.IDUP.at(i));
00400 
00401         int status = hepeup.ISTUP.at(i);
00402 
00403         particle->set_generated_mass(hepeup.PUP.at(i)[4]);
00404         particle->set_status(status > 0 ? (status == 2 ? 3 : status) : 3);
00405 
00406         return particle;
00407 }
00408 
00409 bool LHEEvent::checkHepMCTree(const HepMC::GenEvent *event)
00410 {
00411         double px = 0, py = 0, pz = 0, E = 0;
00412 
00413         for(HepMC::GenEvent::particle_const_iterator iter = event->particles_begin();
00414             iter != event->particles_end(); iter++) {
00415                 int status = (*iter)->status();
00416                 HepMC::FourVector fv = (*iter)->momentum();
00417 
00418                 // incoming particles
00419                 if (status == 3 &&
00420                     *iter != event->beam_particles().first &&
00421                     *iter != event->beam_particles().second) {
00422                         px -= fv.px();
00423                         py -= fv.py();
00424                         pz -= fv.pz();
00425                         E  -= fv.e();
00426                 }
00427 
00428                 // outgoing particles
00429                 if (status == 1) {
00430                         px += fv.px();
00431                         py += fv.py();
00432                         pz += fv.pz();
00433                         E  += fv.e();
00434                 }
00435         }
00436 
00437         if (px*px + py*py + pz*pz + E*E > 0.1) {
00438                 edm::LogWarning("Generator|LHEInterface")
00439                         << "Energy-momentum badly conserved. "
00440                         << std::setprecision(3)
00441                         << "sum p_i  = ["
00442                         << std::setw(7) << E << ", "
00443                         << std::setw(7) << px << ", "
00444                         << std::setw(7) << py << ", "
00445                         << std::setw(7) << pz << "]";
00446 
00447                 return false;
00448         }
00449 
00450         return true;
00451 }
00452 
00453 const HepMC::GenVertex *LHEEvent::findSignalVertex(
00454                                 const HepMC::GenEvent *event, bool status3)
00455 {
00456         double largestMass2 = -9.0e-30;
00457         const HepMC::GenVertex *vertex = 0;
00458         for(HepMC::GenEvent::vertex_const_iterator iter = event->vertices_begin();
00459             iter != event->vertices_end(); ++iter) {
00460                 if ((*iter)->particles_in_size() < 2)
00461                         continue;
00462                 if ((*iter)->particles_out_size() < 1 ||
00463                     ((*iter)->particles_out_size() == 1 &&
00464                      (!(*(*iter)->particles_out_const_begin())->end_vertex() ||
00465                       !(*(*iter)->particles_out_const_begin())
00466                                 ->end_vertex()->particles_out_size())))
00467                         continue;
00468 
00469                 double px = 0.0, py = 0.0, pz = 0.0, E = 0.0;
00470                 bool hadStatus3 = false;
00471                 for(HepMC::GenVertex::particles_out_const_iterator iter2 =
00472                                         (*iter)->particles_out_const_begin();
00473                     iter2 != (*iter)->particles_out_const_end(); ++iter2) {
00474                         hadStatus3 = hadStatus3 || (*iter2)->status() == 3;
00475                         px += (*iter2)->momentum().px();
00476                         py += (*iter2)->momentum().py();
00477                         pz += (*iter2)->momentum().pz();
00478                         E += (*iter2)->momentum().e();
00479                 }
00480                 if (status3 && !hadStatus3)
00481                         continue;
00482 
00483                 double mass2 = E * E - (px * px + py * py + pz * pz);
00484                 if (mass2 > largestMass2) {
00485                         vertex = *iter;
00486                         largestMass2 = mass2;
00487                 }
00488         }
00489 
00490         return vertex;
00491 }
00492 
00493 static void fixSubTree(HepMC::GenVertex *vertex,
00494                        HepMC::FourVector time,
00495                        std::set<const HepMC::GenVertex*> &visited)
00496 {
00497         HepMC::FourVector curTime = vertex->position();
00498         bool needsFixup = curTime.t() < time.t();
00499 
00500         if (!visited.insert(vertex).second && !needsFixup)
00501                 return;
00502 
00503         if (needsFixup)
00504                 vertex->set_position(time);
00505         else
00506                 time = curTime;
00507 
00508         for(HepMC::GenVertex::particles_out_const_iterator iter =
00509                                         vertex->particles_out_const_begin();
00510             iter != vertex->particles_out_const_end(); ++iter) {
00511                 HepMC::GenVertex *endVertex = (*iter)->end_vertex();
00512                 if (endVertex)
00513                         fixSubTree(endVertex, time, visited);
00514         }
00515 }
00516 
00517 void LHEEvent::fixHepMCEventTimeOrdering(HepMC::GenEvent *event)
00518 {
00519         std::set<const HepMC::GenVertex*> visited;
00520         HepMC::FourVector zeroTime;
00521         for(HepMC::GenEvent::vertex_iterator iter = event->vertices_begin();
00522             iter != event->vertices_end(); ++iter)
00523                 fixSubTree(*iter, zeroTime, visited);
00524 }
00525 
00526 } // namespace lhef