Skip to content

Commit

Permalink
Merge pull request #27865 from danielwinterbottom/higgstautau-tau-gen…
Browse files Browse the repository at this point in the history
…filters2_for-CMSSW_7_1_X

backporting generator filter modifications to CMSSW_7_1_X
  • Loading branch information
cmsbuild authored Sep 10, 2019
2 parents ec9df9a + de45778 commit 516f70d
Show file tree
Hide file tree
Showing 4 changed files with 365 additions and 0 deletions.
80 changes: 80 additions & 0 deletions GeneratorInterface/Core/interface/EmbeddingHepMCFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#ifndef __EMBEDDINGHEPMCFILTER__
#define __EMBEDDINGHEPMCFILTER__

#include "FWCore/MessageLogger/interface/MessageLogger.h"

#include "GeneratorInterface/Core/interface/BaseHepMCFilter.h"
#include "DataFormats/Candidate/interface/Candidate.h"

class EmbeddingHepMCFilter : public BaseHepMCFilter {
private:
const int tauon_neutrino_PDGID_ = 16;
const int tauonPDGID_ = 15;
const int muon_neutrino_PDGID_ = 14;
const int muonPDGID_ = 13;
const int electron_neutrino_PDGID_ = 12;
const int electronPDGID_ = 11;
int ZPDGID_ = 23;

enum class TauDecayMode : int { Unfilled = -1, Muon = 0, Electron = 1, Hadronic = 2 };

std::string return_mode(TauDecayMode mode) {
if (mode == TauDecayMode::Muon)
return "Mu";
else if (mode == TauDecayMode::Electron)
return "El";
else if (mode == TauDecayMode::Hadronic)
return "Had";
else
return "Undefined";
}

struct DecayChannel {
TauDecayMode first = TauDecayMode::Unfilled;
TauDecayMode second = TauDecayMode::Unfilled;

void fill(TauDecayMode mode) {
if (first == TauDecayMode::Unfilled)
first = mode;
else if (second == TauDecayMode::Unfilled)
second = mode;
};
void reset() {
first = TauDecayMode::Unfilled;
second = TauDecayMode::Unfilled;
}
void reverse() {
TauDecayMode tmp = first;
first = second;
second = tmp;
}
};

DecayChannel ee, mm, hh, em, eh, mh;

struct CutsContainer {
double pt1 = -1.;
double pt2 = -1.;
double eta1 = -1.; // since we use abs eta values the -1 as default is OK
double eta2 = -1.;
DecayChannel decaychannel;
};

std::vector<CutsContainer> cuts_;
DecayChannel DecayChannel_;

virtual void fill_cut(std::string cut_string, EmbeddingHepMCFilter::DecayChannel &dc, CutsContainer &cut);
virtual void fill_cuts(std::string cut_string, EmbeddingHepMCFilter::DecayChannel &dc);

virtual void decay_and_sump4Vis(HepMC::GenParticle *particle, reco::Candidate::LorentzVector &p4Vis);
virtual void sort_by_convention(std::vector<reco::Candidate::LorentzVector> &p4VisPair);
virtual bool apply_cuts(std::vector<reco::Candidate::LorentzVector> &p4VisPair);

public:
explicit EmbeddingHepMCFilter(const edm::ParameterSet &);
~EmbeddingHepMCFilter() override;

bool filter(const HepMC::GenEvent *evt) override;
};

#endif
236 changes: 236 additions & 0 deletions GeneratorInterface/Core/src/EmbeddingHepMCFilter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
#include "GeneratorInterface/Core/interface/EmbeddingHepMCFilter.h"

#include "boost/algorithm/string.hpp"
#include "boost/algorithm/string/trim_all.hpp"

EmbeddingHepMCFilter::EmbeddingHepMCFilter(const edm::ParameterSet &iConfig)
: ZPDGID_(iConfig.getParameter<int>("BosonPDGID")) {
// Defining standard decay channels
ee.fill(TauDecayMode::Electron);
ee.fill(TauDecayMode::Electron);
mm.fill(TauDecayMode::Muon);
mm.fill(TauDecayMode::Muon);
hh.fill(TauDecayMode::Hadronic);
hh.fill(TauDecayMode::Hadronic);
em.fill(TauDecayMode::Electron);
em.fill(TauDecayMode::Muon);
eh.fill(TauDecayMode::Electron);
eh.fill(TauDecayMode::Hadronic);
mh.fill(TauDecayMode::Muon);
mh.fill(TauDecayMode::Hadronic);

// Filling CutContainers

std::string cut_string_elel = iConfig.getParameter<std::string>("ElElCut");
std::string cut_string_mumu = iConfig.getParameter<std::string>("MuMuCut");
std::string cut_string_hadhad = iConfig.getParameter<std::string>("HadHadCut");
std::string cut_string_elmu = iConfig.getParameter<std::string>("ElMuCut");
std::string cut_string_elhad = iConfig.getParameter<std::string>("ElHadCut");
std::string cut_string_muhad = iConfig.getParameter<std::string>("MuHadCut");

std::vector<std::string> use_final_states = iConfig.getParameter<std::vector<std::string> >("Final_States");

for (std::vector<std::string>::const_iterator final_state = use_final_states.begin();
final_state != use_final_states.end();
++final_state) {
if ((*final_state) == "ElEl")
fill_cuts(cut_string_elel, ee);
else if ((*final_state) == "MuMu")
fill_cuts(cut_string_mumu, mm);
else if ((*final_state) == "HadHad")
fill_cuts(cut_string_hadhad, hh);
else if ((*final_state) == "ElMu")
fill_cuts(cut_string_elmu, em);
else if ((*final_state) == "ElHad")
fill_cuts(cut_string_elhad, eh);
else if ((*final_state) == "MuHad")
fill_cuts(cut_string_muhad, mh);
else
edm::LogWarning("EmbeddingHepMCFilter")
<< (*final_state)
<< " this decay channel is not supported. Please choose on of (ElEl,MuMu,HadHad,ElMu,ElHad,MuHad)";
}
}

EmbeddingHepMCFilter::~EmbeddingHepMCFilter() {}

bool EmbeddingHepMCFilter::filter(const HepMC::GenEvent *evt) {
//Reset DecayChannel_ and p4VisPair_ at the beginning of each event.
DecayChannel_.reset();
std::vector<reco::Candidate::LorentzVector> p4VisPair_;

// Going through the particle list. Mother particles are allways before their children.
// One can stop the loop after the second tau is reached and processed.
for (HepMC::GenEvent::particle_const_iterator particle = evt->particles_begin(); particle != evt->particles_end();
++particle) {
int mom_id = 0; // No particle available with PDG ID 0
if ((*particle)->production_vertex() != nullptr) { // search for the mom via the production_vertex
if ((*particle)->production_vertex()->particles_in_const_begin() !=
(*particle)->production_vertex()->particles_in_const_end()) {
mom_id = (*(*particle)->production_vertex()->particles_in_const_begin())->pdg_id(); // mom was found
}
}

if (std::abs((*particle)->pdg_id()) == tauonPDGID_ && mom_id == ZPDGID_) {
reco::Candidate::LorentzVector p4Vis;
decay_and_sump4Vis((*particle), p4Vis); // recursive access to final states.
p4VisPair_.push_back(p4Vis);
} else if (std::abs((*particle)->pdg_id()) == muonPDGID_ &&
mom_id == ZPDGID_) { // Also handle the option when Z-> mumu
reco::Candidate::LorentzVector p4Vis = (reco::Candidate::LorentzVector)(*particle)->momentum();
DecayChannel_.fill(TauDecayMode::Muon); // take the muon cuts
p4VisPair_.push_back(p4Vis);
} else if (std::abs((*particle)->pdg_id()) == electronPDGID_ &&
mom_id == ZPDGID_) { // Also handle the option when Z-> ee
reco::Candidate::LorentzVector p4Vis = (reco::Candidate::LorentzVector)(*particle)->momentum();
DecayChannel_.fill(TauDecayMode::Electron); // take the electron cuts
p4VisPair_.push_back(p4Vis);
}
}
// Putting DecayChannel_ in default convention:
// For mixed decay channels use the Electron_Muon, Electron_Hadronic, Muon_Hadronic convention.
// For symmetric decay channels (e.g. Muon_Muon) use Leading_Trailing convention with respect to Pt.
if (p4VisPair_.size() == 2) {
sort_by_convention(p4VisPair_);
edm::LogInfo("EmbeddingHepMCFilter") << "Quantities of the visible decay products:"
<< "\tPt's: "
<< " 1st " << p4VisPair_[0].Pt() << ", 2nd " << p4VisPair_[1].Pt()
<< "\tEta's: "
<< " 1st " << p4VisPair_[0].Eta() << ", 2nd " << p4VisPair_[1].Eta()
<< " decay channel: " << return_mode(DecayChannel_.first)
<< return_mode(DecayChannel_.second);
} else {
edm::LogError("EmbeddingHepMCFilter") << "Size less non equal two";
}

return apply_cuts(p4VisPair_);
}

void EmbeddingHepMCFilter::decay_and_sump4Vis(HepMC::GenParticle *particle, reco::Candidate::LorentzVector &p4Vis) {
bool decaymode_known = false;
for (HepMC::GenVertex::particle_iterator daughter = particle->end_vertex()->particles_begin(HepMC::children);
daughter != particle->end_vertex()->particles_end(HepMC::children);
++daughter) {
bool neutrino = (std::abs((*daughter)->pdg_id()) == tauon_neutrino_PDGID_) ||
(std::abs((*daughter)->pdg_id()) == muon_neutrino_PDGID_) ||
(std::abs((*daughter)->pdg_id()) == electron_neutrino_PDGID_);

// Determining DecayMode, if particle is tau lepton.
// Asuming, that there are only the two tauons from the Z-boson.
// This is the case for the simulated Z->tautau event constructed by EmbeddingLHEProducer.
if (std::abs(particle->pdg_id()) == tauonPDGID_ && !decaymode_known) {
// use these bools to protect againt taus that aren't the last copy (which "decay" to a tau and a gamma)
bool isGamma = std::abs((*daughter)->pdg_id()) == 22;
bool isTau = std::abs((*daughter)->pdg_id()) == 15;
if (std::abs((*daughter)->pdg_id()) == muonPDGID_) {
DecayChannel_.fill(TauDecayMode::Muon);
decaymode_known = true;
} else if (std::abs((*daughter)->pdg_id()) == electronPDGID_) {
DecayChannel_.fill(TauDecayMode::Electron);
decaymode_known = true;
} else if (!neutrino && !isGamma && !isTau) {
DecayChannel_.fill(TauDecayMode::Hadronic);
decaymode_known = true;
}
}
// Adding up all visible momentum in recursive way.
if ((*daughter)->status() == 1 && !neutrino)
p4Vis += (reco::Candidate::LorentzVector)(*daughter)->momentum();
else if (!neutrino)
decay_and_sump4Vis((*daughter), p4Vis);
}
}

void EmbeddingHepMCFilter::sort_by_convention(std::vector<reco::Candidate::LorentzVector> &p4VisPair) {
bool mixed_false_order =
(DecayChannel_.first == TauDecayMode::Hadronic && DecayChannel_.second == TauDecayMode::Muon) ||
(DecayChannel_.first == TauDecayMode::Hadronic && DecayChannel_.second == TauDecayMode::Electron) ||
(DecayChannel_.first == TauDecayMode::Muon && DecayChannel_.second == TauDecayMode::Electron);

if (DecayChannel_.first == DecayChannel_.second && p4VisPair[0].Pt() < p4VisPair[1].Pt()) {
edm::LogVerbatim("EmbeddingHepMCFilter") << "Changing symmetric channels to Leading_Trailing convention in Pt";
edm::LogVerbatim("EmbeddingHepMCFilter") << "Pt's before: " << p4VisPair[0].Pt() << " " << p4VisPair[1].Pt();
std::reverse(p4VisPair.begin(), p4VisPair.end());
edm::LogVerbatim("EmbeddingHepMCFilter") << "Pt's after: " << p4VisPair[0].Pt() << " " << p4VisPair[1].Pt();
} else if (mixed_false_order) {
edm::LogVerbatim("EmbeddingHepMCFilter") << "Swapping order of mixed channels";
edm::LogVerbatim("EmbeddingHepMCFilter") << "Pt's before: " << p4VisPair[0].Pt() << " " << p4VisPair[1].Pt();
DecayChannel_.reverse();
edm::LogVerbatim("EmbeddingHepMCFilter")
<< "DecayChannel: " << return_mode(DecayChannel_.first) << return_mode(DecayChannel_.second);
std::reverse(p4VisPair.begin(), p4VisPair.end());
edm::LogVerbatim("EmbeddingHepMCFilter") << "Pt's after: " << p4VisPair[0].Pt() << " " << p4VisPair[1].Pt();
}
}

bool EmbeddingHepMCFilter::apply_cuts(std::vector<reco::Candidate::LorentzVector> &p4VisPair) {
for (std::vector<CutsContainer>::const_iterator cut = cuts_.begin(); cut != cuts_.end(); ++cut) {
if (DecayChannel_.first == cut->decaychannel.first &&
DecayChannel_.second == cut->decaychannel.second) { // First the match to the decay channel
edm::LogInfo("EmbeddingHepMCFilter")
<< "Cut pt1 = " << cut->pt1 << " pt2 = " << cut->pt2 << " abs(eta1) = " << cut->eta1
<< " abs(eta2) = " << cut->eta2 << " decay channel: " << return_mode(cut->decaychannel.first)
<< return_mode(cut->decaychannel.second);

if ((cut->pt1 == -1. || (p4VisPair[0].Pt() > cut->pt1)) && (cut->pt2 == -1. || (p4VisPair[1].Pt() > cut->pt2)) &&
(cut->eta1 == -1. || (std::abs(p4VisPair[0].Eta()) < cut->eta1)) &&
(cut->eta2 == -1. || (std::abs(p4VisPair[1].Eta()) < cut->eta2))) {
edm::LogInfo("EmbeddingHepMCFilter") << "This cut was passed (Stop here and take the event)";
return true;
}
}
}
return false;
}

void EmbeddingHepMCFilter::fill_cuts(std::string cut_string, EmbeddingHepMCFilter::DecayChannel &dc) {
edm::LogInfo("EmbeddingHepMCFilter") << return_mode(dc.first) << return_mode(dc.second) << "Cut : " << cut_string;
boost::trim_fill(cut_string, "");
std::vector<std::string> cut_paths;
boost::split(cut_paths, cut_string, boost::is_any_of("||"), boost::token_compress_on);
for (unsigned int i = 0; i < cut_paths.size(); ++i) {
// Translating the cuts of a path into a struct which is later accessed to apply them on a event.
CutsContainer cut;
fill_cut(cut_paths[i], dc, cut);
cuts_.push_back(cut);
}
}

void EmbeddingHepMCFilter::fill_cut(std::string cut_string,
EmbeddingHepMCFilter::DecayChannel &dc,
CutsContainer &cut) {
cut.decaychannel = dc;

boost::replace_all(cut_string, "(", "");
boost::replace_all(cut_string, ")", "");
std::vector<std::string> single_cuts;
boost::split(single_cuts, cut_string, boost::is_any_of("&&"), boost::token_compress_on);
for (unsigned int i = 0; i < single_cuts.size(); ++i) {
std::string pt1_str, pt2_str, eta1_str, eta2_str;
if (dc.first == dc.second) {
pt1_str = return_mode(dc.first) + "1" + ".Pt" + ">";
pt2_str = return_mode(dc.second) + "2" + ".Pt" + ">";
eta1_str = return_mode(dc.first) + "1" + ".Eta" + "<";
eta2_str = return_mode(dc.second) + "2" + ".Eta" + "<";
} else {
pt1_str = return_mode(dc.first) + ".Pt" + ">";
pt2_str = return_mode(dc.second) + ".Pt" + ">";
eta1_str = return_mode(dc.first) + ".Eta" + "<";
eta2_str = return_mode(dc.second) + ".Eta" + "<";
}

if (boost::find_first(single_cuts[i], pt1_str)) {
boost::erase_first(single_cuts[i], pt1_str);
cut.pt1 = std::stod(single_cuts[i]);
} else if (boost::find_first(single_cuts[i], pt2_str)) {
boost::erase_first(single_cuts[i], pt2_str);
cut.pt2 = std::stod(single_cuts[i]);
} else if (boost::find_first(single_cuts[i], eta1_str)) {
boost::erase_first(single_cuts[i], eta1_str);
cut.eta1 = std::stod(single_cuts[i]);
} else if (boost::find_first(single_cuts[i], eta2_str)) {
boost::erase_first(single_cuts[i], eta2_str);
cut.eta2 = std::stod(single_cuts[i]);
}
}
}
4 changes: 4 additions & 0 deletions GeneratorInterface/Core/src/HepMCFilterDriver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "GeneratorInterface/Core/interface/GenericDauHepMCFilter.h"
#include "GeneratorInterface/Core/interface/PartonShowerBsHepMCFilter.h"
#include "GeneratorInterface/Core/interface/PartonShowerCsHepMCFilter.h"
#include "GeneratorInterface/Core/interface/EmbeddingHepMCFilter.h"

#include "FWCore/MessageLogger/interface/MessageLogger.h"

Expand Down Expand Up @@ -29,6 +30,9 @@ HepMCFilterDriver::HepMCFilterDriver(const edm::ParameterSet& pset) :
else if (filterName=="PartonShowerCsHepMCFilter") {
filter_ = new PartonShowerCsHepMCFilter(filterParameters);
}
else if (filterName == "EmbeddingHepMCFilter") {
filter_ = new EmbeddingHepMCFilter(filterParameters);
}
else {
edm::LogError("HepMCFilterDriver")<< "Invalid HepMCFilter name:" << filterName;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import FWCore.ParameterSet.Config as cms
from Configuration.Generator.Pythia8CommonSettings_cfi import *
from Configuration.Generator.Pythia8CUEP8M1Settings_cfi import *
from GeneratorInterface.ExternalDecays.TauolaSettings_cff import *



generator = cms.EDFilter("Pythia8HadronizerFilter",

maxEventsToPrint = cms.untracked.int32(1),
nAttempts = cms.uint32(1000),
HepMCFilter = cms.PSet(
filterName = cms.string('EmbeddingHepMCFilter'),
filterParameters = cms.PSet(
ElElCut = cms.string('El1.Pt > 22 && El2.Pt > 10'),
ElHadCut = cms.string('El.Pt > 28 && Had.Pt > 25'),
ElMuCut = cms.string('(El.Pt > 21 && Mu.Pt > 10) || (El.Pt > 10 && Mu.Pt > 21)'),
HadHadCut = cms.string('Had1.Pt > 35 && Had2.Pt > 30'),
MuHadCut = cms.string('Mu.Pt > 18 && Had.Pt > 25 && Mu.Eta < 2.1'),
MuMuCut = cms.string('Mu1.Pt > 17 && Mu2.Pt > 8'),
Final_States = cms.vstring('ElEl','ElHad','ElMu','HadHad','MuHad','MuMu'),
BosonPDGID = cms.int32(23)
),
),
pythiaPylistVerbosity = cms.untracked.int32(0),
filterEfficiency = cms.untracked.double(1.0),
pythiaHepMCVerbosity = cms.untracked.bool(False),
comEnergy = cms.double(13000.),
crossSection = cms.untracked.double(1.0),
PythiaParameters = cms.PSet(
pythia8CommonSettingsBlock,
pythia8CUEP8M1SettingsBlock,
processParameters = cms.vstring(

'JetMatching:merge = off',
'Init:showChangedSettings = off',
'Init:showChangedParticleData = off'
),
parameterSets = cms.vstring('pythia8CommonSettings',
'pythia8CUEP8M1Settings',
'processParameters'
)
)
)

0 comments on commit 516f70d

Please sign in to comment.