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