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
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;
00272
00273
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
00282 std::vector<HepMC::GenParticle*> genParticles;
00283 std::vector<HepMC::GenVertex*> genVertices;
00284
00285
00286 for(unsigned int i = 0; i < nup; i++)
00287 genParticles.push_back(makeHepMCParticle(i));
00288
00289
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);
00294
00295
00296 if (mother1) {
00297 mother1--;
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();
00305
00306 if (!current_vtx) {
00307 current_vtx = new HepMC::GenVertex(
00308 HepMC::FourVector(0, 0, 0, cTau));
00309
00310
00311 genVertices.push_back(current_vtx);
00312 }
00313
00314 for(unsigned int j = mother1; j <= mother2; j++)
00315 if (!genParticles.at(j)->end_vertex())
00316 current_vtx->add_particle_in(genParticles.at(j));
00317
00318
00319 current_vtx->add_particle_out(genParticles.at(i));
00320 }
00321 }
00322
00323 checkHepMCTree(hepmc.get());
00324
00325
00326
00327
00328
00329 const HEPRUP *heprup = getHEPRUP();
00330
00331
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
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
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
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
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 }