27 #include "TLorentzVector.h" 58 #include "CLHEP/Random/RandExponential.h" 67 class HepRandomEngine;
74 edm::EndRunProducer> {
84 void endJob()
override;
89 void fill_lhe_from_mumu(TLorentzVector &positiveLepton, TLorentzVector &negativeLepton,
lhef::HEPEUP &outlhe, CLHEP::HepRandomEngine* engine);
90 void fill_lhe_with_particle(
lhef::HEPEUP &outlhe, TLorentzVector &particle,
int pdgid,
double spin,
double ctau);
92 void transform_mumu_to_tautau(TLorentzVector &positiveLepton, TLorentzVector &negativeLepton);
95 void mirror(TLorentzVector &positiveLepton, TLorentzVector &negativeLepton);
96 void rotate180(TLorentzVector &positiveLepton, TLorentzVector &negativeLepton);
104 const double tauMass_ = 1.77682;
105 const double elMass_ = 0.00051;
106 const int embeddingParticles[3] {11,13,15};
123 produces<LHEEventProduct>();
124 produces<LHERunInfoProduct, edm::Transition::BeginRun>();
125 produces<math::XYZTLorentzVectorD>(
"vertexPosition");
129 particleToEmbed_ = iConfig.
getParameter<
int>(
"particleToEmbed");
136 if (lhe_ouputfile !=
""){
143 particleToEmbed_) ==
std::end(embeddingParticles)) {
145 <<
"The given particle to embed is not in the list of allowed particles.";
151 <<
"The EmbeddingLHEProducer requires the RandomNumberGeneratorService\n" 152 "which is not present in the configuration file. \n" 153 "You must add the service\n" 154 "in the configuration file or remove the modules that require it.";
181 iEvent.
getByToken(muonsCollection_, muonHandle);
185 iEvent.
getByToken(vertexCollection_ , coll_vertices);
187 TLorentzVector positiveLepton, negativeLepton;
188 bool mu_plus_found =
false;
189 bool mu_minus_found =
false;
199 if (
muon->charge() == 1 && !mu_plus_found)
201 assign_4vector(positiveLepton, &(*
muon), studyFSRmode_);
202 mu_plus_found =
true;
204 else if (
muon->charge() == -1 && !mu_minus_found)
206 assign_4vector(negativeLepton, &(*
muon), studyFSRmode_);
207 mu_minus_found =
true;
209 else if (mu_minus_found && mu_plus_found)
break;
211 mirror(positiveLepton,negativeLepton);
212 rotate180(positiveLepton,negativeLepton);
213 transform_mumu_to_tautau(positiveLepton,negativeLepton);
214 fill_lhe_from_mumu(positiveLepton,negativeLepton,hepeup,engine);
216 double originalXWGTUP_ = 1.;
217 std::unique_ptr<LHEEventProduct> product(
new LHEEventProduct(hepeup,originalXWGTUP_) );
219 if (write_lheout)
std::copy(product->begin(), product->end(), std::ostream_iterator<std::string>(
file));
223 std::unique_ptr<math::XYZTLorentzVectorD> vertex_position (
new math::XYZTLorentzVectorD(coll_vertices->at(0).x(),coll_vertices->at(0).y(),coll_vertices->at(0).z(),0.0));
224 iEvent.
put(
std::move(vertex_position),
"vertexPosition");
279 runInfo->addHeader(give_slha());
282 if (write_lheout)
std::copy(runInfo->begin(), runInfo->end(),std::ostream_iterator<std::string>(
file));
302 TLorentzVector
Z = positiveLepton + negativeLepton;
303 int leptonPDGID = particleToEmbed_;
306 double tau_ctau0 = 8.71100e-02;
307 double tau_ctau_p = tau_ctau0 * CLHEP::RandExponential::shoot(engine);
309 double tau_ctau_n = tau_ctau0 * CLHEP::RandExponential::shoot(engine);
312 fill_lhe_with_particle(outlhe, Z,23,9.0, 0);
313 fill_lhe_with_particle(outlhe, positiveLepton,-leptonPDGID,1.0, tau_ctau_p);
314 fill_lhe_with_particle(outlhe, negativeLepton,leptonPDGID,-1.0, tau_ctau_n);
325 int particleindex = outlhe.
NUP;
328 outlhe.
PUP[particleindex][0] = particle.Px();
329 outlhe.
PUP[particleindex][1] = particle.Py();
330 outlhe.
PUP[particleindex][2] = particle.Pz();
331 outlhe.
PUP[particleindex][3] = particle.E();
332 outlhe.
PUP[particleindex][4] = particle.M();
335 outlhe.
VTIMUP[particleindex] = ctau;
337 outlhe.
ICOLUP[particleindex].first = 0;
338 outlhe.
ICOLUP[particleindex].second = 0;
341 outlhe.
MOTHUP[particleindex].first = 0;
342 outlhe.
MOTHUP[particleindex].second = 0;
343 outlhe.
ISTUP[particleindex] = 2;
349 outlhe.
MOTHUP[particleindex].first = 1;
350 outlhe.
MOTHUP[particleindex].second = 1;
352 outlhe.
ISTUP[particleindex] = 1;
365 if (particleToEmbed_ == 11) {
367 }
else if (particleToEmbed_ == 15) {
373 TLorentzVector
Z = positiveLepton + negativeLepton;
375 TVector3 boost_from_Z_to_LAB = Z.BoostVector();
376 TVector3 boost_from_LAB_to_Z = -Z.BoostVector();
379 positiveLepton.Boost(boost_from_LAB_to_Z);
380 negativeLepton.Boost(boost_from_LAB_to_Z);
383 double lep_mass_squared = lep_mass*lep_mass;
384 double lep_energy_squared = 0.25*Z.M2();
385 double lep_3momentum_squared = lep_energy_squared - lep_mass_squared;
386 if (lep_3momentum_squared < 0)
393 double scale =
std::sqrt(lep_3momentum_squared/positiveLepton.Vect().Mag2());
394 positiveLepton.SetPxPyPzE(scale*positiveLepton.Px(),scale*positiveLepton.Py(),scale*positiveLepton.Pz(),
std::sqrt(lep_energy_squared));
395 negativeLepton.SetPxPyPzE(scale*negativeLepton.Px(),scale*negativeLepton.Py(),scale*negativeLepton.Pz(),
std::sqrt(lep_energy_squared));
398 positiveLepton.Boost(boost_from_Z_to_LAB);
399 negativeLepton.Boost(boost_from_Z_to_LAB);
406 if(
"afterFSR" == FSRmode && muon->
genParticle() !=
nullptr)
409 Lepton.SetPxPyPzE(afterFSRMuon->
p4().px(),afterFSRMuon->
p4().py(),afterFSRMuon->
p4().pz(), afterFSRMuon->
p4().e());
411 else if (
"beforeFSR" == FSRmode && muon->
genParticle() !=
nullptr)
414 Lepton.SetPxPyPzE(beforeFSRMuon->
p4().px(),beforeFSRMuon->
p4().py(),beforeFSRMuon->
p4().pz(), beforeFSRMuon->
p4().e());
418 Lepton.SetPxPyPzE(muon->
p4().px(),muon->
p4().py(),muon->
p4().pz(), muon->
p4().e());
425 if(muon->
mother(0) ==
nullptr)
return muon;
432 if (!rotate180_)
return;
433 edm::LogInfo(
"TauEmbedding") <<
"Applying 180<C2><B0> rotation" ;
436 TLorentzVector
Z = positiveLepton + negativeLepton;
438 edm::LogInfo(
"TauEmbedding") <<
"MuMinus before. Pt: " << negativeLepton.Pt() <<
" Eta: " << negativeLepton.Eta() <<
" Phi: " << negativeLepton.Phi() <<
" Mass: " << negativeLepton.M();
440 TVector3 Z3 = Z.Vect();
441 TVector3 positiveLepton3 = positiveLepton.Vect();
442 TVector3 negativeLepton3 = negativeLepton.Vect();
444 TVector3 p3_perp = positiveLepton3 - positiveLepton3.Dot(Z3)/Z3.Dot(Z3)*Z3;
445 p3_perp = p3_perp.Unit();
447 positiveLepton3 -= 2*positiveLepton3.Dot(p3_perp)*p3_perp;
448 negativeLepton3 -= 2*negativeLepton3.Dot(p3_perp)*p3_perp;
450 positiveLepton.SetVect(positiveLepton3);
451 negativeLepton.SetVect(negativeLepton3);
453 edm::LogInfo(
"TauEmbedding") <<
"MuMinus after. Pt: " << negativeLepton.Pt() <<
" Eta: " << negativeLepton.Eta() <<
" Phi: " << negativeLepton.Phi() <<
" Mass: " << negativeLepton.M();
462 TLorentzVector
Z = positiveLepton + negativeLepton;
464 edm::LogInfo(
"TauEmbedding") <<
"MuMinus before. Pt: " << negativeLepton.Pt() <<
" Eta: " << negativeLepton.Eta() <<
" Phi: " << negativeLepton.Phi() <<
" Mass: " << negativeLepton.M() ;
466 TVector3 Z3 = Z.Vect();
467 TVector3 positiveLepton3 = positiveLepton.Vect();
468 TVector3 negativeLepton3 = negativeLepton.Vect();
470 TVector3 beam(0.,0.,1.);
471 TVector3 perpToZandBeam = Z3.Cross(beam).Unit();
473 positiveLepton3 -= 2*positiveLepton3.Dot(perpToZandBeam)*perpToZandBeam;
474 negativeLepton3 -= 2*negativeLepton3.Dot(perpToZandBeam)*perpToZandBeam;
476 positiveLepton.SetVect(positiveLepton3);
477 negativeLepton.SetVect(negativeLepton3);
479 edm::LogInfo(
"TauEmbedding") <<
"MuMinus after. Pt: " << negativeLepton.Pt() <<
" Eta: " << negativeLepton.Eta() <<
" Phi: " << negativeLepton.Phi() <<
" Mass: " << negativeLepton.M() ;
488 slhah.
addLine(
"######################################################################\n");
489 slhah.
addLine(
"## PARAM_CARD AUTOMATICALY GENERATED BY MG5 FOLLOWING UFO MODEL ####\n");
490 slhah.
addLine(
"######################################################################\n");
492 slhah.
addLine(
"## Width set on Auto will be computed following the information ##\n");
493 slhah.
addLine(
"## present in the decay.py files of the model. ##\n");
494 slhah.
addLine(
"## See arXiv:1402.1178 for more details. ##\n");
496 slhah.
addLine(
"######################################################################\n");
498 slhah.
addLine(
"###################################\n");
499 slhah.
addLine(
"## INFORMATION FOR MASS\n");
500 slhah.
addLine(
"###################################\n");
501 slhah.
addLine(
"Block mass \n");
502 slhah.
addLine(
" 6 1.730000e+02 # MT \n");
503 slhah.
addLine(
" 15 1.777000e+00 # MTA \n");
504 slhah.
addLine(
" 23 9.118800e+01 # MZ \n");
505 slhah.
addLine(
" 25 1.250000e+02 # MH \n");
506 slhah.
addLine(
"## Dependent parameters, given by model restrictions.\n");
507 slhah.
addLine(
"## Those values should be edited following the \n");
508 slhah.
addLine(
"## analytical expression. MG5 ignores those values \n");
509 slhah.
addLine(
"## but they are important for interfacing the output of MG5\n");
510 slhah.
addLine(
"## to external program such as Pythia.\n");
511 slhah.
addLine(
" 1 0.000000 # d : 0.0 \n");
512 slhah.
addLine(
" 2 0.000000 # u : 0.0 \n");
513 slhah.
addLine(
" 3 0.000000 # s : 0.0 \n");
514 slhah.
addLine(
" 4 0.000000 # c : 0.0 \n");
515 slhah.
addLine(
" 5 0.000000 # b : 0.0 \n");
516 slhah.
addLine(
" 11 0.000000 # e- : 0.0 \n");
517 slhah.
addLine(
" 12 0.000000 # ve : 0.0 \n");
518 slhah.
addLine(
" 13 0.000000 # mu- : 0.0 \n");
519 slhah.
addLine(
" 14 0.000000 # vm : 0.0 \n");
520 slhah.
addLine(
" 16 0.000000 # vt : 0.0 \n");
521 slhah.
addLine(
" 21 0.000000 # g : 0.0 \n");
522 slhah.
addLine(
" 22 0.000000 # a : 0.0 \n");
523 slhah.
addLine(
" 24 80.419002 # w+ : cmath.sqrt(MZ__exp__2/2. + cmath.sqrt(MZ__exp__4/4. - (aEW*cmath.pi*MZ__exp__2)/(Gf*sqrt__2))) \n");
525 slhah.
addLine(
"###################################\n");
526 slhah.
addLine(
"## INFORMATION FOR SMINPUTS\n");
527 slhah.
addLine(
"###################################\n");
528 slhah.
addLine(
"Block sminputs \n");
529 slhah.
addLine(
" 1 1.325070e+02 # aEWM1 \n");
530 slhah.
addLine(
" 2 1.166390e-05 # Gf \n");
531 slhah.
addLine(
" 3 1.180000e-01 # aS \n");
533 slhah.
addLine(
"###################################\n");
534 slhah.
addLine(
"## INFORMATION FOR WOLFENSTEIN\n");
535 slhah.
addLine(
"###################################\n");
536 slhah.
addLine(
"Block wolfenstein \n");
537 slhah.
addLine(
" 1 2.253000e-01 # lamWS \n");
538 slhah.
addLine(
" 2 8.080000e-01 # AWS \n");
539 slhah.
addLine(
" 3 1.320000e-01 # rhoWS \n");
540 slhah.
addLine(
" 4 3.410000e-01 # etaWS \n");
542 slhah.
addLine(
"###################################\n");
543 slhah.
addLine(
"## INFORMATION FOR YUKAWA\n");
544 slhah.
addLine(
"###################################\n");
545 slhah.
addLine(
"Block yukawa \n");
546 slhah.
addLine(
" 6 1.730000e+02 # ymt \n");
547 slhah.
addLine(
" 15 1.777000e+00 # ymtau \n");
549 slhah.
addLine(
"###################################\n");
550 slhah.
addLine(
"## INFORMATION FOR DECAY\n");
551 slhah.
addLine(
"###################################\n");
552 slhah.
addLine(
"DECAY 6 1.491500e+00 # WT \n");
553 slhah.
addLine(
"DECAY 15 2.270000e-12 # WTau \n");
554 slhah.
addLine(
"DECAY 23 2.441404e+00 # WZ \n");
555 slhah.
addLine(
"DECAY 24 2.047600e+00 # WW \n");
556 slhah.
addLine(
"DECAY 25 6.382339e-03 # WH \n");
557 slhah.
addLine(
"## Dependent parameters, given by model restrictions.\n");
558 slhah.
addLine(
"## Those values should be edited following the \n");
559 slhah.
addLine(
"## analytical expression. MG5 ignores those values \n");
560 slhah.
addLine(
"## but they are important for interfacing the output of MG5\n");
561 slhah.
addLine(
"## to external program such as Pythia.\n");
562 slhah.
addLine(
"DECAY 1 0.000000 # d : 0.0 \n");
563 slhah.
addLine(
"DECAY 2 0.000000 # u : 0.0 \n");
564 slhah.
addLine(
"DECAY 3 0.000000 # s : 0.0 \n");
565 slhah.
addLine(
"DECAY 4 0.000000 # c : 0.0 \n");
566 slhah.
addLine(
"DECAY 5 0.000000 # b : 0.0 \n");
567 slhah.
addLine(
"DECAY 11 0.000000 # e- : 0.0 \n");
568 slhah.
addLine(
"DECAY 12 0.000000 # ve : 0.0 \n");
569 slhah.
addLine(
"DECAY 13 0.000000 # mu- : 0.0 \n");
570 slhah.
addLine(
"DECAY 14 0.000000 # vm : 0.0 \n");
571 slhah.
addLine(
"DECAY 16 0.000000 # vt : 0.0 \n");
572 slhah.
addLine(
"DECAY 21 0.000000 # g : 0.0 \n");
573 slhah.
addLine(
"DECAY 22 0.000000 # a : 0.0\n");
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
void mirror(TLorentzVector &positiveLepton, TLorentzVector &negativeLepton)
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
const reco::GenParticle * genParticle(size_t idx=0) const
bool getByToken(EDGetToken token, Handle< PROD > &result) const
#define DEFINE_FWK_MODULE(type)
virtual const Candidate * mother(size_type i=0) const =0
return pointer to mother
std::string studyFSRmode_
std::vector< double > VTIMUP
void transform_mumu_to_tautau(TLorentzVector &positiveLepton, TLorentzVector &negativeLepton)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
~EmbeddingLHEProducer() override
virtual CLHEP::HepRandomEngine & getEngine(StreamID const &)=0
Use this engine in event methods.
void fill_lhe_with_particle(lhef::HEPEUP &outlhe, TLorentzVector &particle, int pdgid, double spin, double ctau)
void beginRunProduce(edm::Run &run, edm::EventSetup const &es) override
LHERunInfoProduct::Header give_slha()
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
std::vector< std::pair< int, int > > MOTHUP
void addDefault(ParameterSetDescription const &psetDescription)
const_iterator begin() const
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector
virtual int pdgId() const =0
PDG identifier.
void assign_4vector(TLorentzVector &Lepton, const pat::Muon *muon, std::string FSRmode)
std::vector< FiveVector > PUP
std::vector< double > SPINUP
Abs< T >::type abs(const T &t)
const LorentzVector & p4() const final
four-momentum Lorentz vector
void endRunProduce(edm::Run &, edm::EventSetup const &) override
std::vector< double > XERRUP
std::vector< double > XMAXUP
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void put(std::unique_ptr< PROD > product)
Put a new product.
void rotate180(TLorentzVector &positiveLepton, TLorentzVector &negativeLepton)
edm::EDGetTokenT< edm::View< pat::Muon > > muonsCollection_
void produce(edm::Event &, const edm::EventSetup &) override
const reco::Candidate * find_original_muon(const reco::Candidate *muon)
boost::indirect_iterator< typename seq_t::const_iterator > const_iterator
StreamID streamID() const
edm::EDGetTokenT< reco::VertexCollection > vertexCollection_
static const std::string & endOfFile()
const_iterator end() const
void fill_lhe_from_mumu(TLorentzVector &positiveLepton, TLorentzVector &negativeLepton, lhef::HEPEUP &outlhe, CLHEP::HepRandomEngine *engine)
std::vector< double > XSECUP
Analysis-level muon class.
std::vector< std::pair< int, int > > ICOLUP
EmbeddingLHEProducer(const edm::ParameterSet &)