diff --git a/BPHNano/plugins/BTo4TrkBuilder.cc b/BPHNano/plugins/BTo4TrkBuilder.cc new file mode 100644 index 00000000000..6699f9777be --- /dev/null +++ b/BPHNano/plugins/BTo4TrkBuilder.cc @@ -0,0 +1,245 @@ +#include "FWCore/Framework/interface/global/EDProducer.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Utilities/interface/InputTag.h" + +#include +#include +#include +#include +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" +#include "CommonTools/Utils/interface/StringCutObjectSelector.h" +#include "DataFormats/PatCandidates/interface/CompositeCandidate.h" +#include "DataFormats/Math/interface/deltaR.h" +#include "CommonTools/Statistics/interface/ChiSquaredProbability.h" +#include "TrackingTools/TransientTrack/interface/TransientTrack.h" +#include "helper.h" +#include +#include +#include "KinVtxFitter.h" +#include "RecoVertex/VertexTools/interface/VertexDistance3D.h" + +/* + * This class was originally designed to reconstruct the Bs -> phi(KK)phi/KK) decay. + * It can be generalised to other fully-hadronic B decays. + */ + +class BTo4TrkBuilder : public edm::global::EDProducer<> { + +public: + typedef std::vector TransientTrackCollection; + + explicit BTo4TrkBuilder(const edm::ParameterSet &cfg): + phi_candidates_{consumes( cfg.getParameter("phis") )}, + kaon_ttracks_{consumes( cfg.getParameter("phisTransientTracks") )}, + pre_vtx_selection_ {cfg.getParameter("pre_vtx_selection")}, + post_vtx_selection_ {cfg.getParameter("post_vtx_selection")}, + beamspot_{consumes(cfg.getParameter("beamSpot"))}{ + produces(); + } + + ~BTo4TrkBuilder() override {} + + void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override; + + static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {} + +private: + const edm::EDGetTokenT phi_candidates_; + const edm::EDGetTokenT kaon_ttracks_; + const StringCutObjectSelector pre_vtx_selection_; + const StringCutObjectSelector post_vtx_selection_; + const edm::EDGetTokenT beamspot_; +}; + +void BTo4TrkBuilder::produce(edm::StreamID, edm::Event &evt, edm::EventSetup const &) const { + + edm::Handle phi_candidates; + evt.getByToken(phi_candidates_, phi_candidates); + + edm::Handle kaon_ttracks; + evt.getByToken(kaon_ttracks_, kaon_ttracks); + + edm::Handle beamspot; + evt.getByToken(beamspot_, beamspot); + + // output + std::unique_ptr ret_value(new pat::CompositeCandidateCollection()); + + // loop on first phi candidate (phi1) + for(size_t phi1_idx = 0; phi1_idx < phi_candidates->size(); ++phi1_idx) { + edm::Ptr phi1_ptr(phi_candidates, phi1_idx); + + // retrieve kaons + edm::Ptr k1_ptr = phi1_ptr->userCand("trk1"); + edm::Ptr k2_ptr = phi1_ptr->userCand("trk2"); + int k1_idx = phi1_ptr->userInt("trk1_idx"); + int k2_idx = phi1_ptr->userInt("trk2_idx"); + + // loop on second phi candidate (phi2) + for(size_t phi2_idx = phi1_idx + 1; phi2_idx < phi_candidates->size(); ++phi2_idx) { + edm::Ptr phi2_ptr(phi_candidates, phi2_idx); + + // retrieve kaons + edm::Ptr k3_ptr = phi2_ptr->userCand("trk1"); + edm::Ptr k4_ptr = phi2_ptr->userCand("trk2"); + int k3_idx = phi2_ptr->userInt("trk1_idx"); + int k4_idx = phi2_ptr->userInt("trk2_idx"); + + if(phi2_ptr->pt() > phi1_ptr->pt()){ + std::cout << "not ordered in pt!" << std::endl; + } + + if(k3_idx == k1_idx || k3_idx == k2_idx) { + continue; + } + if(k4_idx == k1_idx || k4_idx == k2_idx){ + continue; + } + + // build Bs candidate + pat::CompositeCandidate Bs_cand; + Bs_cand.setP4(phi1_ptr->p4() + phi2_ptr->p4()); + Bs_cand.setCharge(phi1_ptr->charge() + phi2_ptr->charge()); + + // apply pre-fit selection on Bs candidate + if( !pre_vtx_selection_(Bs_cand) ) continue; + + // save indices + Bs_cand.addUserInt("k1_idx", k1_idx); + Bs_cand.addUserInt("k2_idx", k2_idx); + Bs_cand.addUserInt("k3_idx", k3_idx); + Bs_cand.addUserInt("k4_idx", k4_idx); + Bs_cand.addUserInt("phi1_idx", phi1_idx); + Bs_cand.addUserInt("phi2_idx", phi2_idx); + + // save candidates + Bs_cand.addUserCand("k1", k1_ptr); + Bs_cand.addUserCand("k2", k2_ptr); + Bs_cand.addUserCand("k3", k3_ptr); + Bs_cand.addUserCand("k4", k4_ptr); + Bs_cand.addUserCand("phi1", phi1_ptr); + Bs_cand.addUserCand("phi2", phi2_ptr); + + // fit the four kaon tracks to a common vertex + KinVtxFitter fitter_Bs( + {kaon_ttracks->at(k1_idx), kaon_ttracks->at(k2_idx), kaon_ttracks->at(k3_idx), kaon_ttracks->at(k4_idx)}, + {K_MASS, K_MASS, K_MASS, K_MASS}, // force kaon mass + {K_SIGMA, K_SIGMA, K_SIGMA, K_SIGMA} + ); + + if(!fitter_Bs.success()) continue; + + Bs_cand.setVertex( + reco::Candidate::Point( + fitter_Bs.fitted_vtx().x(), + fitter_Bs.fitted_vtx().y(), + fitter_Bs.fitted_vtx().z() + ) + ); + + Bs_cand.addUserFloat("Bs_vx", fitter_Bs.fitted_vtx().x()); + Bs_cand.addUserFloat("Bs_vy", fitter_Bs.fitted_vtx().y()); + Bs_cand.addUserFloat("Bs_vz", fitter_Bs.fitted_vtx().z()); + + const auto& covMatrix = fitter_Bs.fitted_vtx_uncertainty(); + Bs_cand.addUserFloat("Bs_vtx_cxx", covMatrix.cxx()); + Bs_cand.addUserFloat("Bs_vtx_cyy", covMatrix.cyy()); + Bs_cand.addUserFloat("Bs_vtx_czz", covMatrix.czz()); + Bs_cand.addUserFloat("Bs_vtx_cyx", covMatrix.cyx()); + Bs_cand.addUserFloat("Bs_vtx_czx", covMatrix.czx()); + Bs_cand.addUserFloat("Bs_vtx_czy", covMatrix.czy()); + + Bs_cand.addUserFloat("Bs_sv_chi2", fitter_Bs.chi2()); + Bs_cand.addUserFloat("Bs_sv_ndof", fitter_Bs.dof()); + Bs_cand.addUserFloat("Bs_sv_prob", fitter_Bs.prob()); + + auto fit_p4 = fitter_Bs.fitted_p4(); + Bs_cand.addUserFloat("Bs_fitted_pt" , fit_p4.pt()); + Bs_cand.addUserFloat("Bs_fitted_eta" , fit_p4.eta()); + Bs_cand.addUserFloat("Bs_fitted_phi" , fit_p4.phi()); + Bs_cand.addUserFloat("Bs_fitted_mass", fit_p4.mass()); + Bs_cand.addUserFloat("Bs_fitted_mass_corr", fit_p4.mass() - (fitter_Bs.daughter_p4(0) + fitter_Bs.daughter_p4(1)).mass() + 1.0195 - (fitter_Bs.daughter_p4(2) + fitter_Bs.daughter_p4(3)).mass() + 1.0195); + Bs_cand.addUserFloat("Bs_fitted_massErr", sqrt(fitter_Bs.fitted_candidate().kinematicParametersError().matrix()(6,6))); + Bs_cand.addUserFloat("Bs_charge", Bs_cand.charge()); + Bs_cand.addUserFloat("Bs_cos_theta_2D", cos_theta_2D(fitter_Bs, *beamspot, fit_p4)); + auto Bs_lxy = l_xy(fitter_Bs, *beamspot); + Bs_cand.addUserFloat("Bs_lxy", Bs_lxy.value()); + Bs_cand.addUserFloat("Bs_lxy_sig", Bs_lxy.value() / Bs_lxy.error()); + + auto k1_p4 = fitter_Bs.daughter_p4(0); + auto k2_p4 = fitter_Bs.daughter_p4(1); + auto k3_p4 = fitter_Bs.daughter_p4(2); + auto k4_p4 = fitter_Bs.daughter_p4(3); + auto phi1_p4 = k1_p4 + k2_p4; + auto phi2_p4 = k3_p4 + k4_p4; + + // phi candidates + std::vector phi_names{"phi1", "phi2"}; + for (size_t i = 0; i < phi_names.size(); i++){ + int idx1 = -99; + int idx2 = -99; + if(phi_names[i] == "phi1"){ + idx1 = 0; + idx2 = 1; + } + else if(phi_names[i] == "phi2"){ + idx1 = 2; + idx2 = 3; + } + Bs_cand.addUserFloat(phi_names[i] + "_fitted_mass", (fitter_Bs.daughter_p4(idx1) + fitter_Bs.daughter_p4(idx2)).mass()); + Bs_cand.addUserFloat(phi_names[i] + "_fitted_pt", (fitter_Bs.daughter_p4(idx1) + fitter_Bs.daughter_p4(idx2)).pt()); + Bs_cand.addUserFloat(phi_names[i] + "_fitted_eta", (fitter_Bs.daughter_p4(idx1) + fitter_Bs.daughter_p4(idx2)).eta()); + Bs_cand.addUserFloat(phi_names[i] + "_fitted_phi", (fitter_Bs.daughter_p4(idx1) + fitter_Bs.daughter_p4(idx2)).phi()); + } + + // compute deltaR + Bs_cand.addUserFloat("deltaR_phi1phi2", reco::deltaR(phi1_p4, phi2_p4)); + Bs_cand.addUserFloat("deltaR_k1k3", reco::deltaR(k1_p4, k3_p4)); + Bs_cand.addUserFloat("deltaR_k1k4", reco::deltaR(k1_p4, k4_p4)); + Bs_cand.addUserFloat("deltaR_k2k3", reco::deltaR(k2_p4, k3_p4)); + Bs_cand.addUserFloat("deltaR_k2k4", reco::deltaR(k2_p4, k4_p4)); + + Bs_cand.addUserFloat("deltaR_k1k2", reco::deltaR(k1_p4, k2_p4)); + Bs_cand.addUserFloat("deltaR_k3k4", reco::deltaR(k3_p4, k4_p4)); + + auto dr_info = min_max_dr({k1_ptr, k2_ptr, k3_ptr, k4_ptr}); + Bs_cand.addUserFloat("deltaR_min", dr_info.first); + Bs_cand.addUserFloat("deltaR_max", dr_info.second); + + // compute invariant masses + Bs_cand.addUserFloat("k1k3_mass", (k1_p4 + k3_p4).mass()); + Bs_cand.addUserFloat("k1k4_mass", (k1_p4 + k4_p4).mass()); + Bs_cand.addUserFloat("k2k3_mass", (k2_p4 + k3_p4).mass()); + Bs_cand.addUserFloat("k2k4_mass", (k2_p4 + k4_p4).mass()); + + Bs_cand.addUserFloat("k1k3_pt", (k1_p4 + k3_p4).pt()); + Bs_cand.addUserFloat("k1k4_pt", (k1_p4 + k4_p4).pt()); + Bs_cand.addUserFloat("k2k3_pt", (k2_p4 + k3_p4).pt()); + Bs_cand.addUserFloat("k2k4_pt", (k2_p4 + k4_p4).pt()); + + // kaons + std::vector kaon_names{"k1", "k2", "k3", "k4"}; + + for (size_t i = 0; i < kaon_names.size(); i++){ + Bs_cand.addUserFloat(kaon_names[i] + "_fitted_mass" ,fitter_Bs.daughter_p4(i).mass()); + Bs_cand.addUserFloat(kaon_names[i] + "_fitted_pt" ,fitter_Bs.daughter_p4(i).pt()); + Bs_cand.addUserFloat(kaon_names[i] + "_fitted_eta",fitter_Bs.daughter_p4(i).eta()); + Bs_cand.addUserFloat(kaon_names[i] + "_fitted_phi",fitter_Bs.daughter_p4(i).phi()); + } + + // apply pots-fit selection on phi1 candidate + if(!post_vtx_selection_(Bs_cand)) continue; + + // save candidate + ret_value->push_back(Bs_cand); + } + } + + evt.put(std::move(ret_value)); +} + +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_FWK_MODULE(BTo4TrkBuilder); diff --git a/BPHNano/plugins/DiTrackBuilder.cc b/BPHNano/plugins/DiTrackBuilder.cc index ca699527510..e3d47416564 100644 --- a/BPHNano/plugins/DiTrackBuilder.cc +++ b/BPHNano/plugins/DiTrackBuilder.cc @@ -29,7 +29,6 @@ - class DiTrackBuilder : public edm::global::EDProducer<> { @@ -81,9 +80,10 @@ void DiTrackBuilder::produce(edm::StreamID, edm::Event &evt, edm::EventSetup con // output - std::unique_ptr kstar_out(new pat::CompositeCandidateCollection()); - + std::unique_ptr cand_out(new pat::CompositeCandidateCollection()); + // needed to sort in pt + std::vector vector_candidates; // main loop for (size_t trk1_idx = 0; trk1_idx < pfcands->size(); ++trk1_idx ) { @@ -98,37 +98,53 @@ void DiTrackBuilder::produce(edm::StreamID, edm::Event &evt, edm::EventSetup con if (!trk2_selection_(*trk2_ptr)) continue; bool UsedAgain = false; + + std::vector< std::pair > list_masses; + if (trk1_mass_ == trk2_mass_) { + list_masses.push_back(std::pair(trk1_mass_, trk2_mass_)); + } + else{ + list_masses.push_back(std::pair(trk1_mass_, trk2_mass_)); + list_masses.push_back(std::pair(trk2_mass_, trk1_mass_)); + } + // Loop in all possible hypothesis - for ( std::pair masses : { std::pair(trk1_mass_, trk2_mass_), std::pair(trk2_mass_, trk1_mass_) } ) { - // create a K* candidate; add first quantities that can be used for pre fit selection - pat::CompositeCandidate kstar_cand; + for ( std::pair masses : list_masses ) { + // create a candidate; add first quantities that can be used for pre fit selection + pat::CompositeCandidate cand; + auto trk1_p4 = trk1_ptr->polarP4(); auto trk2_p4 = trk2_ptr->polarP4(); trk1_p4.SetM(masses.first); trk2_p4.SetM(masses.second); + //adding stuff for pre fit selection - kstar_cand.setP4(trk1_p4 + trk2_p4); - kstar_cand.setCharge(trk1_ptr->charge() + trk2_ptr->charge()); - kstar_cand.addUserFloat("trk_deltaR", reco::deltaR(*trk1_ptr, *trk2_ptr)); + cand.setP4(trk1_p4 + trk2_p4); + cand.setCharge(trk1_ptr->charge() + trk2_ptr->charge()); + cand.addUserFloat("trk_deltaR", reco::deltaR(*trk1_ptr, *trk2_ptr)); + // save indices - kstar_cand.addUserInt("trk1_idx", trk1_idx ); - kstar_cand.addUserInt("trk2_idx", trk2_idx ); - kstar_cand.addUserFloat("trk1_mass", masses.first); - kstar_cand.addUserFloat("trk2_mass", masses.second); + cand.addUserInt("trk1_idx", trk1_idx ); + cand.addUserInt("trk2_idx", trk2_idx ); + cand.addUserFloat("trk1_mass", masses.first); + cand.addUserFloat("trk2_mass", masses.second); + // save cands - kstar_cand.addUserCand("trk1", trk1_ptr ); - kstar_cand.addUserCand("trk2", trk2_ptr ); + cand.addUserCand("trk1", trk1_ptr ); + cand.addUserCand("trk2", trk2_ptr ); + // selection before fit - if ( !pre_vtx_selection_(kstar_cand) ) continue; + if ( !pre_vtx_selection_(cand) ) continue; //std::cout<<"trk1 "<at(trk1_idx), ttracks->at(trk2_idx)}, + {ttracks->at(trk1_idx), ttracks->at(trk2_idx)}, { masses.first, masses.second }, {K_SIGMA, K_SIGMA} //K and PI sigma equal... ); if ( !fitter.success() ) continue; - kstar_cand.setVertex( + cand.setVertex( reco::Candidate::Point( fitter.fitted_vtx().x(), fitter.fitted_vtx().y(), @@ -136,36 +152,47 @@ void DiTrackBuilder::produce(edm::StreamID, edm::Event &evt, edm::EventSetup con ) ); // save quantities after fit - kstar_cand.addUserInt("sv_ok", fitter.success() ? 1 : 0); - kstar_cand.addUserFloat("sv_chi2", fitter.chi2()); - kstar_cand.addUserFloat("sv_ndof", fitter.dof()); - kstar_cand.addUserFloat("sv_prob", fitter.prob()); - kstar_cand.addUserFloat("fitted_mass", fitter.fitted_candidate().mass() ); - kstar_cand.addUserFloat("fitted_pt", + cand.addUserInt("sv_ok", fitter.success() ? 1 : 0); + cand.addUserFloat("sv_chi2", fitter.chi2()); + cand.addUserFloat("sv_ndof", fitter.dof()); + cand.addUserFloat("sv_prob", fitter.prob()); + cand.addUserFloat("fitted_mass", fitter.fitted_candidate().mass() ); + cand.addUserFloat("fitted_pt", fitter.fitted_candidate().globalMomentum().perp() ); - kstar_cand.addUserFloat("fitted_eta", + cand.addUserFloat("fitted_eta", fitter.fitted_candidate().globalMomentum().eta() ); - kstar_cand.addUserFloat("fitted_phi", + cand.addUserFloat("fitted_phi", fitter.fitted_candidate().globalMomentum().phi() ); - kstar_cand.addUserInt("second_mass_hypothesis", UsedAgain ); - kstar_cand.addUserFloat("vtx_x", kstar_cand.vx()); - kstar_cand.addUserFloat("vtx_y", kstar_cand.vy()); - kstar_cand.addUserFloat("vtx_z", kstar_cand.vz()); + cand.addUserInt("second_mass_hypothesis", UsedAgain ); + cand.addUserFloat("vtx_x", cand.vx()); + cand.addUserFloat("vtx_y", cand.vy()); + cand.addUserFloat("vtx_z", cand.vz()); + cand.addUserFloat("deltaR_postfit", reco::deltaR(fitter.daughter_p4(0), fitter.daughter_p4(1))); + cand.addUserFloat("fitted_k1_pt", fitter.daughter_p4(0).pt()); + cand.addUserFloat("fitted_k2_pt", fitter.daughter_p4(1).pt()); // after fit selection - if ( !post_vtx_selection_(kstar_cand) ) continue; - kstar_out->emplace_back(kstar_cand); + if ( !post_vtx_selection_(cand) ) continue; + vector_candidates.emplace_back(cand); UsedAgain = true; - if (masses.first == masses.second) break; } // end for ( auto & masses: } // end for(size_t trk2_idx = trk1_idx + 1 } //for(size_t trk1_idx = 0 - evt.put(std::move(kstar_out)); + // sort candidate collection in pt + std::sort(vector_candidates.begin(), vector_candidates.end(), + [] (auto & cand1, auto & cand2) -> + bool {return (cand1.pt() > cand2.pt());} + ); + + for (auto & cand: vector_candidates){ + cand_out->emplace_back(cand); + } + evt.put(std::move(cand_out)); } #include "FWCore/Framework/interface/MakerMacros.h" diff --git a/BPHNano/plugins/TrackMerger.cc b/BPHNano/plugins/TrackMerger.cc index 281e2aeb271..c6c10c347ae 100644 --- a/BPHNano/plugins/TrackMerger.cc +++ b/BPHNano/plugins/TrackMerger.cc @@ -27,9 +27,11 @@ #include "CommonTools/Utils/interface/StringCutObjectSelector.h" #include "helper.h" +template class TrackMerger : public edm::global::EDProducer<> { public: + typedef std::vector LeptonCollection; //would it be useful to give this a bit more standard structure? explicit TrackMerger(const edm::ParameterSet &cfg): @@ -37,7 +39,7 @@ class TrackMerger : public edm::global::EDProducer<> { beamSpotSrc_(consumes(cfg.getParameter("beamSpot"))), tracksToken_(consumes(cfg.getParameter("tracks"))), lostTracksToken_(consumes(cfg.getParameter("lostTracks"))), - dileptonToken_(consumes(cfg.getParameter("dileptons"))), + trgmuonToken_(consumes(cfg.getParameter("trgmuons"))), muonToken_(consumes(cfg.getParameter("muons"))), eleToken_(consumes(cfg.getParameter("electrons"))), maxDzDilep_(cfg.getParameter("maxDzDilep")), @@ -61,7 +63,8 @@ class TrackMerger : public edm::global::EDProducer<> { const edm::EDGetTokenT beamSpotSrc_; const edm::EDGetTokenT tracksToken_; const edm::EDGetTokenT lostTracksToken_; - const edm::EDGetTokenT dileptonToken_; + const edm::EDGetTokenT trgmuonToken_; + const edm::EDGetTokenT muonToken_; const edm::EDGetTokenT eleToken_; @@ -72,7 +75,8 @@ class TrackMerger : public edm::global::EDProducer<> { }; -void TrackMerger::produce(edm::StreamID, edm::Event &evt, edm::EventSetup const &stp) const { +template +void TrackMerger::produce(edm::StreamID, edm::Event &evt, edm::EventSetup const &stp) const { //input edm::Handle beamSpotHandle; @@ -87,9 +91,8 @@ void TrackMerger::produce(edm::StreamID, edm::Event &evt, edm::EventSetup const evt.getByToken(tracksToken_, tracks); edm::Handle lostTracks; evt.getByToken(lostTracksToken_, lostTracks); - edm::Handle dileptons; - evt.getByToken(dileptonToken_, dileptons); - + edm::Handle trgmuons; + evt.getByToken(trgmuonToken_, trgmuons); edm::Handle muons; evt.getByToken(muonToken_, muons); edm::Handle pfele; @@ -123,12 +126,12 @@ void TrackMerger::produce(edm::StreamID, edm::Event &evt, edm::EventSetup const bool skipTrack = true; float dzTrg = 0.0; - for (const pat::CompositeCandidate & dilep : *dileptons) { + for (const Lepton & trgmu : *trgmuons) { //if dz is negative it is deactivated - if ( fabs(trk.vz() - dilep.vz()) > maxDzDilep_ && maxDzDilep_ > 0) + if ( fabs(trk.vz() - trgmu.vz()) > maxDzDilep_ && maxDzDilep_ > 0 ) continue; skipTrack = false; - dzTrg = trk.vz() - dilep.vz(); + dzTrg = trk.vz() - trgmu.vz(); break; // at least for one dilepton candidate to pass this cuts } @@ -146,7 +149,6 @@ void TrackMerger::produce(edm::StreamID, edm::Event &evt, edm::EventSetup const float DCASig = (DCABSErr != 0 && float(DCABSErr) == DCABSErr) ? fabs(DCABS / DCABSErr) : -1; if (DCASig > dcaSig_ && dcaSig_ > 0) continue; - // clean tracks wrt to all muons int matchedToMuon = 0; for (const pat::Muon &imutmp : *muons) { @@ -276,6 +278,9 @@ void TrackMerger::produce(edm::StreamID, edm::Event &evt, edm::EventSetup const evt.put(std::move(tracks_out_match), "SelectedTracks"); } +typedef TrackMerger TrackMergerSingleMuon; +typedef TrackMerger TrackMergerDiMuon; //define this as a plug-in -DEFINE_FWK_MODULE(TrackMerger); +DEFINE_FWK_MODULE(TrackMergerSingleMuon); +DEFINE_FWK_MODULE(TrackMergerDiMuon); diff --git a/BPHNano/python/BToKLL_cff.py b/BPHNano/python/BToKLL_cff.py index 7e798bf0602..e58a11a9a04 100644 --- a/BPHNano/python/BToKLL_cff.py +++ b/BPHNano/python/BToKLL_cff.py @@ -6,13 +6,13 @@ BToKmumu = cms.EDProducer( 'BToTrkLLBuilder', dileptons = cms.InputTag("MuMu:SelectedDiLeptons"), - leptonTransientTracks = cms.InputTag('muonBPH', 'SelectedTransientMuons'), + leptonTransientTracks = cms.InputTag('muonBPHDiMuon', 'SelectedTransientMuons'), dileptonKinVtxs = cms.InputTag('MuMu:SelectedDiLeptonKinVtxs'), - kaons = cms.InputTag('tracksBPH', 'SelectedTracks'), - kaonsTransientTracks = cms.InputTag('tracksBPH', 'SelectedTransientTracks'), + kaons = cms.InputTag('tracksBPHDiMuon', 'SelectedTracks'), + kaonsTransientTracks = cms.InputTag('tracksBPHDiMuon', 'SelectedTransientTracks'), trackMass = cms.double(493.677), beamSpot = cms.InputTag("offlineBeamSpot"), - PUtracks = cms.InputTag('tracksBPH', 'SelectedTracks'), + PUtracks = cms.InputTag('tracksBPHDiMuon', 'SelectedTracks'), preVtxSelection = cms.string('pt > 5.0' '&& 4.5 < mass && mass < 6.' '&& userFloat("min_dr") > 0.03'), diff --git a/BPHNano/python/BToKshortLL_cff.py b/BPHNano/python/BToKshortLL_cff.py index 34f2bae70c9..ad184065903 100644 --- a/BPHNano/python/BToKshortLL_cff.py +++ b/BPHNano/python/BToKshortLL_cff.py @@ -6,11 +6,11 @@ BToKshortMuMu = cms.EDProducer( 'BToV0LLBuilder', dileptons = cms.InputTag("MuMu:SelectedDiLeptons"), - leptonTransientTracks = cms.InputTag('muonBPH', 'SelectedTransientMuons'), + leptonTransientTracks = cms.InputTag('muonBPHDiMuon', 'SelectedTransientMuons'), v0s = cms.InputTag('KshortToPiPi','SelectedV0Collection'), v0TransientTracks = cms.InputTag('KshortToPiPi', 'SelectedV0TransientCollection'), tracks = cms.InputTag("packedPFCandidates"), - PUtracks = cms.InputTag('tracksBPH', 'SelectedTracks'), + PUtracks = cms.InputTag('tracksBPHDiMuon', 'SelectedTracks'), beamSpot = cms.InputTag("offlineBeamSpot"), preVtxSelection = cms.string('pt > 5.0 ' '&& 4.5 < mass && mass < 6. ' diff --git a/BPHNano/python/BToKstarLL_cff.py b/BPHNano/python/BToKstarLL_cff.py index 3090f6e225b..42ce98627f5 100644 --- a/BPHNano/python/BToKstarLL_cff.py +++ b/BPHNano/python/BToKstarLL_cff.py @@ -6,10 +6,10 @@ BToKstarMuMu = cms.EDProducer( 'BToTrkTrkLLBuilder', dileptons = cms.InputTag("MuMu:SelectedDiLeptons"), - leptonTransientTracks = cms.InputTag('muonBPH', 'SelectedTransientMuons'), + leptonTransientTracks = cms.InputTag('muonBPHDiMuon', 'SelectedTransientMuons'), ditracks = cms.InputTag('KstarToPiK'), - transientTracks = cms.InputTag('tracksBPH', 'SelectedTransientTracks'), - PUtracks = cms.InputTag('tracksBPH', 'SelectedTracks'), + transientTracks = cms.InputTag('tracksBPHDiMuon', 'SelectedTransientTracks'), + PUtracks = cms.InputTag('tracksBPHDiMuon', 'SelectedTracks'), beamSpot = cms.InputTag("offlineBeamSpot"), preVtxSelection = cms.string('pt > 5.' '&& 4.5 < mass && mass < 6.' diff --git a/BPHNano/python/BsToPhiPhiTo4K_cff.py b/BPHNano/python/BsToPhiPhiTo4K_cff.py new file mode 100644 index 00000000000..60401da700d --- /dev/null +++ b/BPHNano/python/BsToPhiPhiTo4K_cff.py @@ -0,0 +1,180 @@ +import FWCore.ParameterSet.Config as cms +from PhysicsTools.BPHNano.common_cff import * + + +PhiToKK = cms.EDProducer( + 'DiTrackBuilder', + tracks = cms.InputTag('tracksBPHSingleMuon', 'SelectedTracks'), + transientTracks = cms.InputTag('tracksBPHSingleMuon', 'SelectedTransientTracks'), + trk1Selection = cms.string(''), + trk2Selection = cms.string(''), + trk1Mass = cms.double(0.493677), + trk2Mass = cms.double(0.493677), + preVtxSelection = cms.string(' && '.join([ + 'abs(mass-1.0195)<0.05', + 'userFloat("trk_deltaR")<0.5', + 'charge()==0', + ]) + ), + postVtxSelection = cms.string(' && '.join([ + 'abs(userFloat("fitted_mass")-1.0195)<0.015', + 'userFloat("fitted_k1_pt")>0.8', + 'userFloat("fitted_k2_pt")>0.7', + 'userFloat("deltaR_postfit")<0.25', + 'userFloat("sv_prob")>0.01', + ]) + ), +) + +BsToPhiPhiTo4K = cms.EDProducer( + 'BTo4TrkBuilder', + phis = cms.InputTag('PhiToKK'), + phisTransientTracks = cms.InputTag('tracksBPHSingleMuon', 'SelectedTransientTracks'), + genParticles = cms.InputTag("finalGenParticlesBPark"), + beamSpot = cms.InputTag("offlineBeamSpot"), + pre_vtx_selection = cms.string('abs(mass-5.367)<3'), + post_vtx_selection = cms.string(' && '.join([ + 'abs(userFloat("phi1_fitted_mass") - 1.0195) < 0.012', + 'abs(userFloat("phi2_fitted_mass") - 1.0195) < 0.012', + 'userFloat("phi1_fitted_pt") > 2.5', + 'userFloat("phi2_fitted_pt") > 1.8', + '(userFloat("phi1_fitted_pt") * userFloat("phi1_fitted_pt")) > 6', + 'userFloat("Bs_fitted_pt") > 1.5', + 'abs(userFloat("Bs_fitted_eta")) < 2.5', + 'userFloat("deltaR_min") < 0.15', + 'userFloat("deltaR_max") < 2.5', + 'userFloat("Bs_lxy_sig") > 1', + 'userFloat("Bs_sv_prob") > 0.001', + 'abs(userFloat("Bs_fitted_mass")-5.367)<0.3', + ]) + ), +) + +PhiToKKTable = cms.EDProducer( + 'SimpleCompositeCandidateFlatTableProducer', + src = cms.InputTag("PhiToKK"), + cut = cms.string(""), + name = cms.string("PhiToKK"), + doc = cms.string("PhiToKK Variable"), + singleton=cms.bool(False), + extension=cms.bool(False), + variables=cms.PSet( + sv_chi2 = ufloat('sv_chi2'), + sv_ndof = ufloat('sv_ndof'), + sv_prob = ufloat('sv_prob'), + mass = ufloat('fitted_mass'), + pt = ufloat('fitted_pt'), + eta = ufloat('fitted_eta'), + phi = ufloat('fitted_phi'), + k1_idx = uint('trk1_idx'), + k2_idx = uint('trk2_idx'), + k1_pt = ufloat('fitted_k1_pt'), + k2_pt = ufloat('fitted_k2_pt'), + deltaR_prefit = ufloat('trk_deltaR'), + deltaR_postfit = ufloat('deltaR_postfit'), + ) +) + +BsToPhiPhiTo4KTable = cms.EDProducer( + 'SimpleCompositeCandidateFlatTableProducer', + src = cms.InputTag("BsToPhiPhiTo4K"), + cut = cms.string(""), + name = cms.string("BsToPhiPhiTo4K"), + doc = cms.string("BsToPhiPhiTo4K Variable"), + singleton=cms.bool(False), + extension=cms.bool(False), + variables=cms.PSet( + Bs_vx = ufloat('Bs_vx'), + Bs_vy = ufloat('Bs_vy'), + Bs_vz = ufloat('Bs_vz'), + Bs_cxx = ufloat('Bs_vtx_cxx'), + Bs_cyy = ufloat('Bs_vtx_cyy'), + Bs_czz = ufloat('Bs_vtx_czz'), + Bs_cyx = ufloat('Bs_vtx_cyx'), + Bs_czx = ufloat('Bs_vtx_czx'), + Bs_czy = ufloat('Bs_vtx_czy'), + Bs_sv_chi2 = ufloat('Bs_sv_chi2'), + Bs_sv_ndof = ufloat('Bs_sv_ndof'), + Bs_sv_prob = ufloat('Bs_sv_prob'), + Bs_mass = ufloat('Bs_fitted_mass'), + Bs_mass_corr = ufloat('Bs_fitted_mass_corr'), + Bs_massErr = ufloat('Bs_fitted_massErr'), + Bs_pt = ufloat('Bs_fitted_pt'), + Bs_eta = ufloat('Bs_fitted_eta'), + Bs_phi = ufloat('Bs_fitted_phi'), + Bs_charge = ufloat('Bs_charge'), + Bs_cos2D = ufloat('Bs_cos_theta_2D'), + Bs_lxy = ufloat('Bs_lxy'), + Bs_lxy_sig = ufloat('Bs_lxy_sig'), + + k1_idx = uint('k1_idx'), + k2_idx = uint('k2_idx'), + k3_idx = uint('k3_idx'), + k4_idx = uint('k4_idx'), + phi1_idx = uint('phi1_idx'), + phi2_idx = uint('phi2_idx'), + + deltaR_phi1phi2 = ufloat('deltaR_phi1phi2'), + deltaR_k1k3 = ufloat('deltaR_k1k3'), + deltaR_k1k4 = ufloat('deltaR_k1k4'), + deltaR_k2k3 = ufloat('deltaR_k2k3'), + deltaR_k2k4 = ufloat('deltaR_k2k4'), + deltaR_k1k2 = ufloat('deltaR_k1k2'), + deltaR_k3k4 = ufloat('deltaR_k3k4'), + deltaR_max = ufloat('deltaR_max'), + deltaR_min = ufloat('deltaR_min'), + + k1k3_mass = ufloat('k1k3_mass'), + k1k4_mass = ufloat('k1k4_mass'), + k2k3_mass = ufloat('k2k3_mass'), + k2k4_mass = ufloat('k2k4_mass'), + k1k3_pt = ufloat('k1k3_pt'), + k1k4_pt = ufloat('k1k4_pt'), + k2k3_pt = ufloat('k2k3_pt'), + k2k4_pt = ufloat('k2k4_pt'), + + phi1_mass = ufloat('phi1_fitted_mass'), + phi1_pt = ufloat('phi1_fitted_pt'), + phi1_eta = ufloat('phi1_fitted_eta'), + phi1_phi = ufloat('phi1_fitted_phi'), + phi2_mass = ufloat('phi2_fitted_mass'), + phi2_pt = ufloat('phi2_fitted_pt'), + phi2_eta = ufloat('phi2_fitted_eta'), + phi2_phi = ufloat('phi2_fitted_phi'), + + k1_mass = ufloat('k1_fitted_mass'), + k1_pt = ufloat('k1_fitted_pt'), + k1_eta = ufloat('k1_fitted_eta'), + k1_phi = ufloat('k1_fitted_phi'), + k2_mass = ufloat('k2_fitted_mass'), + k2_pt = ufloat('k2_fitted_pt'), + k2_eta = ufloat('k2_fitted_eta'), + k2_phi = ufloat('k2_fitted_phi'), + k3_mass = ufloat('k3_fitted_mass'), + k3_pt = ufloat('k3_fitted_pt'), + k3_eta = ufloat('k3_fitted_eta'), + k3_phi = ufloat('k3_fitted_phi'), + k4_mass = ufloat('k4_fitted_mass'), + k4_pt = ufloat('k4_fitted_pt'), + k4_eta = ufloat('k4_fitted_eta'), + k4_phi = ufloat('k4_fitted_phi'), + ) +) + +CountPhiToKK = cms.EDFilter("PATCandViewCountFilter", + minNumber = cms.uint32(1), + maxNumber = cms.uint32(999999), + src = cms.InputTag("PhiToKK") +) + +CountBsToPhiPhiTo4K = cms.EDFilter("PATCandViewCountFilter", + minNumber = cms.uint32(1), + maxNumber = cms.uint32(999999), + src = cms.InputTag("BsToPhiPhiTo4K") +) + + +PhiToKKSequence = cms.Sequence(PhiToKK) +PhiToKKTables = cms.Sequence(PhiToKKTable) +BsToPhiPhiTo4KSequence = cms.Sequence(BsToPhiPhiTo4K) +BsToPhiPhiTo4KTables = cms.Sequence(BsToPhiPhiTo4KTable) diff --git a/BPHNano/python/KshortToPiPi_cff.py b/BPHNano/python/KshortToPiPi_cff.py index 7656042e5b1..b9cba6e6d2d 100644 --- a/BPHNano/python/KshortToPiPi_cff.py +++ b/BPHNano/python/KshortToPiPi_cff.py @@ -11,7 +11,7 @@ postVtxSelection = cms.string('0.3 < mass && mass < 0.7' '&& userFloat("sv_prob") > 0.0001'), beamSpot = cms.InputTag("offlineBeamSpot"), - track_match = cms.InputTag('tracksBPH', 'SelectedTracks') + track_match = cms.InputTag('tracksBPHDiMuon', 'SelectedTracks') ) ########################### Tables ########################### diff --git a/BPHNano/python/KstarToKPi_cff.py b/BPHNano/python/KstarToKPi_cff.py index 02360b9329d..3ea5a9b030d 100644 --- a/BPHNano/python/KstarToKPi_cff.py +++ b/BPHNano/python/KstarToKPi_cff.py @@ -3,8 +3,8 @@ KstarToPiK = cms.EDProducer( 'DiTrackBuilder', - tracks = cms.InputTag('tracksBPH', 'SelectedTracks'), - transientTracks = cms.InputTag('tracksBPH', 'SelectedTransientTracks'), + tracks = cms.InputTag('tracksBPHDiMuon', 'SelectedTracks'), + transientTracks = cms.InputTag('tracksBPHDiMuon', 'SelectedTransientTracks'), trk1Selection = cms.string(''), trk2Selection = cms.string(''), trk1Mass = cms.double(0.139), diff --git a/BPHNano/python/MuMu_cff.py b/BPHNano/python/MuMu_cff.py index eac8fc64aa8..a2e8b3ca947 100644 --- a/BPHNano/python/MuMu_cff.py +++ b/BPHNano/python/MuMu_cff.py @@ -5,8 +5,8 @@ MuMu = cms.EDProducer( 'DiMuonBuilder', - src = cms.InputTag('muonBPH', 'SelectedMuons'), - transientTracksSrc = cms.InputTag('muonBPH', 'SelectedTransientMuons'), + src = cms.InputTag('muonBPHDiMuon', 'SelectedMuons'), + transientTracksSrc = cms.InputTag('muonBPHDiMuon', 'SelectedTransientMuons'), lep1Selection = cms.string('pt > 4.0 && abs(eta) < 2.4 && isLooseMuon && isGlobalMuon'), lep2Selection = cms.string('pt > 3.0 && abs(eta) < 2.4 && isLooseMuon && isGlobalMuon'), preVtxSelection = cms.string('abs(userCand("l1").vz - userCand("l2").vz) <= 1.' diff --git a/BPHNano/python/muons_cff.py b/BPHNano/python/muons_cff.py index 8d1b010278c..dc65d284599 100644 --- a/BPHNano/python/muons_cff.py +++ b/BPHNano/python/muons_cff.py @@ -1,30 +1,43 @@ import FWCore.ParameterSet.Config as cms from PhysicsTools.NanoAOD.common_cff import * -Path=["HLT_DoubleMu4_LowMass_Displaced", "HLT_DoubleMu4_3_LowMass"] +HLT_paths_dimuon=["HLT_DoubleMu4_LowMass_Displaced", "HLT_DoubleMu4_3_LowMass"] +HLT_paths_singlemuon=["HLT_Mu7_IP4", "HLT_Mu8_IP6", "HLT_Mu8_IP5", "HLT_Mu8_IP3", "HLT_Mu8p5_IP3p5", "HLT_Mu9_IP6", "HLT_Mu9_IP5", "HLT_Mu9_IP4", "HLT_Mu10p5_IP3p5", "HLT_Mu12_IP6"] +#FIXME add HLT paths for the 2025 data -muonBPH = cms.EDProducer("MuonTriggerSelector", +muonBPHDiMuon = cms.EDProducer("MuonTriggerSelector", muonCollection = cms.InputTag("slimmedMuons"), #same collection as in NanoAOD bits = cms.InputTag("TriggerResults", "", "HLT"), prescales = cms.InputTag("patTrigger"), objects = cms.InputTag("slimmedPatTrigger"), maxdR_matching = cms.double(0.3), ##for the output trigger matched collection muonSelection = cms.string("pt > 2 && abs(eta) < 2.4"), ## on the fly selection - HLTPaths = cms.vstring(Path), ### comma to the softMuonsOnly + HLTPaths = cms.vstring(HLT_paths_dimuon), ### comma to the softMuonsOnly + ) + +muonBPHSingleMuon = muonBPHDiMuon.clone( + muonSelection = cms.string("pt > 2 && abs(eta) < 2.4"), ## on the fly selection + HLTPaths = cms.vstring(HLT_paths_singlemuon), ### comma to the softMuonsOnly ) #cuts minimun number in B both mu and e, min number of trg, dz muon, dz and dr track, -countTrgMuons = cms.EDFilter("PATCandViewCountFilter", +countTrgDiMuons = cms.EDFilter("PATCandViewCountFilter", minNumber = cms.uint32(2), maxNumber = cms.uint32(999999), - src = cms.InputTag("muonBPH", "SelectedMuons") + src = cms.InputTag("muonBPHDiMuon", "SelectedMuons") +) + +countTrgSingleMuons = cms.EDFilter("PATCandViewCountFilter", + minNumber = cms.uint32(1), + maxNumber = cms.uint32(999999), + src = cms.InputTag("muonBPHSingleMuon", "SelectedMuons") ) -muonBPHTable = cms.EDProducer("SimpleCandidateFlatTableProducer", - src = cms.InputTag("muonBPH:SelectedMuons"), +muonBPHDiMuonTable = cms.EDProducer("SimpleCandidateFlatTableProducer", + src = cms.InputTag("muonBPHDiMuon:SelectedMuons"), cut = cms.string(""), #we should not filter on cross linked collections name = cms.string("Muon"), - doc = cms.string("slimmedMuons after basic selection"), + doc = cms.string("slimmedMuons matched to a trigger HLT object after basic selection"), singleton = cms.bool(False), # the number of entries is variable extension = cms.bool(False), # this is the main table for the muons variables = cms.PSet( @@ -67,8 +80,13 @@ ), ) -muonBPHMCMatch = cms.EDProducer("MCMatcher", # cut on deltaR, deltaPt/Pt; pick best by deltaR - src = muonBPHTable.src, # final reco collection + +muonBPHSingleMuonTable = muonBPHDiMuonTable.clone( + src = cms.InputTag("muonBPHSingleMuon:SelectedMuons"), +) + +muonBPHDiMuonMCMatch = cms.EDProducer("MCMatcher", # cut on deltaR, deltaPt/Pt; pick best by deltaR + src = muonBPHDiMuonTable.src, # final reco collection matched = cms.InputTag("finalGenParticlesBPH"), # final mc-truth particle collection mcPdgId = cms.vint32(13), # one or more PDG ID (13 = mu); absolute values (see below) checkCharge = cms.bool(False), # True = require RECO and MC objects to have the same charge @@ -79,30 +97,53 @@ resolveByMatchQuality = cms.bool(True), # False = just match input in order; True = pick lowest deltaR pair first ) -muonBPHMCTable = cms.EDProducer("CandMCMatchTableProducerBPH", - recoObjects = muonBPHTable.src, +muonBPHSingleMuonMCMatch = muonBPHDiMuonMCMatch.clone( + src = muonBPHSingleMuonTable.src, +) + +muonBPHDiMuonMCTable = cms.EDProducer("CandMCMatchTableProducerBPH", + recoObjects = muonBPHDiMuonTable.src, genParts = cms.InputTag("finalGenParticlesBPH"), - mcMap = cms.InputTag("muonBPHMCMatch"), - objName = muonBPHTable.name, - objType = muonBPHTable.name, + mcMap = cms.InputTag("muonBPHDiMuonMCMatch"), + objName = muonBPHDiMuonTable.name, + objType = muonBPHDiMuonTable.name, objBranchName = cms.string("genPart"), genBranchName = cms.string("muon"), docString = cms.string("MC matching to status==1 muons"), ) -allMuonTable = muonBPHTable.clone( - src = cms.InputTag("muonBPH:AllMuons"), +muonBPHSingleMuonMCTable = muonBPHDiMuonMCTable.clone( + recoObjects = muonBPHSingleMuonTable.src, + objName = muonBPHSingleMuonTable.name, + objType = muonBPHSingleMuonTable.name, +) + +allDiMuonTable = muonBPHDiMuonTable.clone( + src = cms.InputTag("muonBPHDiMuon:AllMuons"), name = cms.string("AllMuon"), - doc = cms.string("HLT Muons matched with reco muons"), #reco muon matched to triggering muon"), + doc = cms.string("All the slimmed muons passing basic selection"), variables = cms.PSet( - CandVars, - vx = Var("vx()", float, doc="x coordinate of vertex position [cm]"), - vy = Var("vy()", float, doc="y coordinate of vertex position [cm]"), - vz = Var("vz()", float, doc="z coordinate of vertex position [cm]") + muonBPHDiMuonTable.variables, ) ) -muonBPHSequence = cms.Sequence(muonBPH) -muonBPHSequenceMC = cms.Sequence(muonBPH + muonBPHMCMatch) -muonBPHTables = cms.Sequence(muonBPHTable) -muonBPHTablesMC = cms.Sequence(muonBPHTable + muonBPHMCTable) +allSingleMuonTable = muonBPHSingleMuonTable.clone( + src = cms.InputTag("muonBPHSingleMuon:AllMuons"), + name = cms.string("AllMuon"), + doc = cms.string("All the slimmed muons passing basic selection"), + variables = cms.PSet( + muonBPHSingleMuonTable.variables, + ) +) + + +muonBPHDiMuonSequence = cms.Sequence(muonBPHDiMuon) +muonBPHDiMuonSequenceMC = cms.Sequence(muonBPHDiMuon + muonBPHDiMuonMCMatch) +muonBPHDiMuonTables = cms.Sequence(muonBPHDiMuonTable) +muonBPHDiMuonTablesMC = cms.Sequence(muonBPHDiMuonTable + muonBPHDiMuonMCTable) + +muonBPHSingleMuonSequence = cms.Sequence(muonBPHSingleMuon) +muonBPHSingleMuonSequenceMC = cms.Sequence(muonBPHSingleMuon + muonBPHSingleMuonMCMatch) +muonBPHSingleMuonTables = cms.Sequence(muonBPHSingleMuonTable) +muonBPHSingleMuonTablesMC = cms.Sequence(muonBPHSingleMuonTable + muonBPHSingleMuonMCTable) + diff --git a/BPHNano/python/nanoBPH_cff.py b/BPHNano/python/nanoBPH_cff.py index b4b94549e77..79137ec0e37 100644 --- a/BPHNano/python/nanoBPH_cff.py +++ b/BPHNano/python/nanoBPH_cff.py @@ -22,6 +22,7 @@ from PhysicsTools.BPHNano.BToKLL_cff import * from PhysicsTools.BPHNano.BToKstarLL_cff import * from PhysicsTools.BPHNano.BToKshortLL_cff import * +from PhysicsTools.BPHNano.BsToPhiPhiTo4K_cff import * vertexTable.svSrc = cms.InputTag("slimmedSecondaryVertices") @@ -42,33 +43,39 @@ def nanoAOD_customizeMC(process): return process - -def nanoAOD_customizeMuonBPH(process,isMC): +def nanoAOD_customizeSingleMuonBPH(process, isMC): if isMC: - process.nanoSequence = cms.Sequence( process.nanoSequence + muonBPHSequenceMC + muonBPHTablesMC) + process.nanoSequence = cms.Sequence( process.nanoSequence + muonBPHSingleMuonSequenceMC + muonBPHSingleMuonTablesMC ) else: - process.nanoSequence = cms.Sequence( process.nanoSequence + muonBPHSequence + countTrgMuons + muonBPHTables) + process.nanoSequence = cms.Sequence( process.nanoSequence + muonBPHSingleMuonSequence + countTrgSingleMuons + muonBPHSingleMuonTables ) return process def nanoAOD_customizeDiMuonBPH(process, isMC): if isMC: - process.nanoSequence = cms.Sequence( process.nanoSequence + MuMuSequence + MuMuTables ) + process.nanoSequence = cms.Sequence( process.nanoSequence + muonBPHDiMuonSequenceMC + muonBPHDiMuonTablesMC + MuMuSequence + MuMuTables ) else: - process.nanoSequence = cms.Sequence( process.nanoSequence + MuMuSequence + CountDiMuonBPH + MuMuTables) + process.nanoSequence = cms.Sequence( process.nanoSequence + muonBPHDiMuonSequence + countTrgDiMuons + muonBPHDiMuonTables + MuMuSequence + CountDiMuonBPH + MuMuTables ) return process -def nanoAOD_customizeTrackBPH(process,isMC): +def nanoAOD_customizeTrackBPHSingleMuon(process,isMC): if isMC: - process.nanoSequence = cms.Sequence( process.nanoSequence + tracksBPHSequenceMC + tracksBPHTablesMC) + process.nanoSequence = cms.Sequence( process.nanoSequence + tracksBPHSequenceMCSingleMuon + tracksBPHSingleMuonTablesMC ) else: - process.nanoSequence = cms.Sequence( process.nanoSequence + tracksBPHSequence + tracksBPHTables) + process.nanoSequence = cms.Sequence( process.nanoSequence + tracksBPHSequenceSingleMuon + tracksBPHSingleMuonTables ) return process +def nanoAOD_customizeTrackBPHDiMuon(process,isMC): + if isMC: + process.nanoSequence = cms.Sequence( process.nanoSequence + tracksBPHSequenceMCDiMuon + tracksBPHDiMuonTablesMC ) + else: + process.nanoSequence = cms.Sequence( process.nanoSequence + tracksBPHSequenceDiMuon + tracksBPHDiMuonTables ) + return process + def nanoAOD_customizeBToKLL(process,isMC): if isMC: @@ -107,3 +114,13 @@ def nanoAOD_customizeBToXLL(process,isMC): return process + +def nanoAOD_customizeBsToPhiPhiTo4K(process, isMC): + if isMC: + process.nanoSequence = cms.Sequence( process.nanoSequence + PhiToKKSequence + BsToPhiPhiTo4KSequence + PhiToKKTables + BsToPhiPhiTo4KTable ) #FIXME is it correct? + else: + process.nanoSequence = cms.Sequence( process.nanoSequence + PhiToKKSequence + BsToPhiPhiTo4KSequence + PhiToKKTables + BsToPhiPhiTo4KTable + CountPhiToKK + CountBsToPhiPhiTo4K ) + return process + + + diff --git a/BPHNano/python/tracks_cff.py b/BPHNano/python/tracks_cff.py index a5efc682f94..5f0782bab41 100644 --- a/BPHNano/python/tracks_cff.py +++ b/BPHNano/python/tracks_cff.py @@ -1,10 +1,11 @@ import FWCore.ParameterSet.Config as cms from PhysicsTools.NanoAOD.common_cff import * -tracksBPH = cms.EDProducer( - "TrackMerger", + +tracksBPHDiMuon = cms.EDProducer( + "TrackMergerDiMuon", beamSpot = cms.InputTag("offlineBeamSpot"), - dileptons = cms.InputTag("MuMu:SelectedDiLeptons"), + trgmuons = cms.InputTag("MuMu:SelectedDiLeptons"), tracks = cms.InputTag("packedPFCandidates"), lostTracks = cms.InputTag("lostTracks"), trackSelection = cms.string("pt>1.0 && abs(eta)<2.4"), # We need all tracks for tagging, no cuts here for now @@ -14,10 +15,22 @@ dcaSig = cms.double(-100000), ) +tracksBPHSingleMuon = cms.EDProducer( + "TrackMergerSingleMuon", + beamSpot = cms.InputTag("offlineBeamSpot"), + trgmuons = cms.InputTag('muonBPHSingleMuon', 'SelectedMuons'), + tracks = cms.InputTag("packedPFCandidates"), + lostTracks = cms.InputTag("lostTracks"), + trackSelection = cms.string("pt>0.6 && abs(eta)<2.5"), + muons = cms.InputTag("slimmedMuons"), + electrons = cms.InputTag("slimmedElectrons"), + maxDzDilep = cms.double(-1.0), + dcaSig = cms.double(-100000), +) -trackBPHTable = cms.EDProducer( +trackBPHDiMuonTable = cms.EDProducer( "SimpleCompositeCandidateFlatTableProducer", - src = cms.InputTag("tracksBPH:SelectedTracks"), + src = cms.InputTag("tracksBPHDiMuon:SelectedTracks"), cut = cms.string(""), name = cms.string("Track"), doc = cms.string("track collection"), @@ -56,8 +69,13 @@ ) -tracksBPHMCMatch = cms.EDProducer("MCMatcher", # cut on deltaR, deltaPt/Pt; pick best by deltaR - src = trackBPHTable.src, # final reco collection +trackBPHSingleMuonTable = trackBPHDiMuonTable.clone( + src = cms.InputTag("tracksBPHSingleMuon:SelectedTracks"), +) + + +tracksBPHMCMatchDiMuon = cms.EDProducer("MCMatcher", # cut on deltaR, deltaPt/Pt; pick best by deltaR + src = trackBPHDiMuonTable.src, matched = cms.InputTag("finalGenParticlesBPH"), # final mc-truth particle collection mcPdgId = cms.vint32(321, 211), # one or more PDG ID (321 = charged kaon, 211 = charged pion); absolute values (see below) checkCharge = cms.bool(False), # True = require RECO and MC objects to have the same charge @@ -68,20 +86,38 @@ resolveByMatchQuality = cms.bool(True), # False = just match input in order; True = pick lowest deltaR pair first ) +tracksBPHMCMatchSingleMuon = tracksBPHMCMatchDiMuon.clone( + src = trackBPHSingleMuonTable.src, +) -tracksBPHMCTable = cms.EDProducer("CandMCMatchTableProducerBPH", - recoObjects = tracksBPHMCMatch.src, + +tracksBPHMCDiMuonTable = cms.EDProducer("CandMCMatchTableProducerBPH", + recoObjects = tracksBPHMCMatchDiMuon.src, + objName = trackBPHDiMuonTable.name, + objType = trackBPHDiMuonTable.name, genParts = cms.InputTag("finalGenParticlesBPH"), - mcMap = cms.InputTag("tracksBPHMCMatch"), - objName = trackBPHTable.name, - objType = trackBPHTable.name, + mcMap = cms.InputTag("tracksBPHMCMatchDiMuon"), objBranchName = cms.string("genPart"), genBranchName = cms.string("track"), docString = cms.string("MC matching to status==1 kaons or pions"), ) -tracksBPHSequence = cms.Sequence(tracksBPH) -tracksBPHSequenceMC = cms.Sequence(tracksBPH + tracksBPHMCMatch) -tracksBPHTables = cms.Sequence(trackBPHTable) -tracksBPHTablesMC = cms.Sequence(trackBPHTable + tracksBPHMCTable) +tracksBPHMCSingleMuonTable = tracksBPHMCDiMuonTable.clone( + recoObjects = tracksBPHMCMatchSingleMuon.src, + objName = trackBPHSingleMuonTable.name, + objType = trackBPHSingleMuonTable.name, + mcMap = cms.InputTag("tracksBPHMCMatchSingleMuon"), +) + + +tracksBPHSequenceDiMuon = cms.Sequence(tracksBPHDiMuon) +tracksBPHSequenceMCDiMuon = cms.Sequence(tracksBPHDiMuon + tracksBPHMCMatchDiMuon) +tracksBPHDiMuonTables = cms.Sequence(trackBPHDiMuonTable) +tracksBPHDiMuonTablesMC = cms.Sequence(trackBPHDiMuonTable + tracksBPHMCDiMuonTable) + +tracksBPHSequenceSingleMuon = cms.Sequence(tracksBPHSingleMuon) +tracksBPHSequenceMCSingleMuon = cms.Sequence(tracksBPHSingleMuon + tracksBPHMCMatchSingleMuon) +tracksBPHSingleMuonTables = cms.Sequence(trackBPHSingleMuonTable) +tracksBPHSingleMuonTablesMC = cms.Sequence(trackBPHSingleMuonTable + tracksBPHMCSingleMuonTable) + diff --git a/BPHNano/test/run_bphNano_cfg.py b/BPHNano/test/run_bphNano_cfg.py index 13034f2db9a..a1926659885 100644 --- a/BPHNano/test/run_bphNano_cfg.py +++ b/BPHNano/test/run_bphNano_cfg.py @@ -22,8 +22,9 @@ def Defaultsamples(isMC,decay): 'root://cms-xrd-global.cern.ch//store/mc/Run3Summer22EEMiniAODv4/BdToJpsiKstar_BMuonFilter_SoftQCDnonD_TuneCP5_13p6TeV_pythia8-evtgen/MINIAODSIM/130X_mcRun3_2022_realistic_postEE_v6-v2/2540000/04415d2e-62f7-4c64-aa43-27cd63a43243.root',\ 'root://cms-xrd-global.cern.ch//store/mc/Run3Summer23MiniAODv4/B0ToJpsiK0s_JpsiFilter_MuFilter_K0sFilter_TuneCP5_13p6TeV_pythia8-evtgen/MINIAODSIM/130X_mcRun3_2023_realistic_v14-v3/2820000/02555ce8-49a9-485f-9d46-3c5c49a8359c.root'] else: - #return ['root://cms-xrd-global.cern.ch//store/data/Run2023B/ParkingDoubleMuonLowMass0/MINIAOD/PromptReco-v1/000/366/729/00000/27addd1b-2dfd-422e-9ee6-32540a1680c7.root'] - return ['root://cms-xrd-global.cern.ch//store/data/Run2022D/ParkingDoubleMuonLowMass0/MINIAOD/10Dec2022-v2/25610000/79a953fb-ecee-457c-a06a-41352cf1ec10.root'] + return [ + 'root://cms-xrd-global.cern.ch//store/data/Run2022D/ParkingDoubleMuonLowMass0/MINIAOD/10Dec2022-v2/25610000/79a953fb-ecee-457c-a06a-41352cf1ec10.root', + ] @@ -69,7 +70,7 @@ def Defaultsamples(isMC,decay): options.register('decay', 'all', VarParsing.multiplicity.singleton, VarParsing.varType.string, - "Options: all KLL KshortLL KstarLL" + "Options: all KLL KshortLL KstarLL BsToPhiPhi" ) @@ -185,10 +186,20 @@ def Defaultsamples(isMC,decay): if options.isMC: process = nanoAOD_customizeMC(process) -process = nanoAOD_customizeMuonBPH(process,options.isMC) -process = nanoAOD_customizeDiMuonBPH(process,options.isMC) -process = nanoAOD_customizeTrackBPH(process,options.isMC) +# process muons and tracks +if options.decay in ["KLL", "KstarLL", "KshortLL", "all"]: # dilepton triggers + process = nanoAOD_customizeDiMuonBPH(process=process, isMC=options.isMC) + process = nanoAOD_customizeTrackBPHDiMuon(process=process, isMC=options.isMC) + +elif options.decay == "BsToPhiPhi": # single-lepton triggers + process = nanoAOD_customizeSingleMuonBPH(process=process, isMC=options.isMC) + process = nanoAOD_customizeTrackBPHSingleMuon(process=process, isMC=options.isMC) + +else: + raise RuntimeError("The muon and track processes were not specified for the decay channel '{}'. Please check".format(options.decay)) + +# process signal channels if options.decay == "KLL": process = nanoAOD_customizeBToKLL(process,options.isMC) @@ -198,6 +209,9 @@ def Defaultsamples(isMC,decay): elif options.decay == "KshortLL": process = nanoAOD_customizeBToKshortLL(process,options.isMC) +elif options.decay == "BsToPhiPhi": + process = nanoAOD_customizeBsToPhiPhiTo4K(process,options.isMC) + elif options.decay == "all": process = nanoAOD_customizeBToXLL(process,options.isMC)