CMS 3D CMS Logo

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