/** * @file * @author Caleb Fangmeier * @version 0.1 * * @section LICENSE * * * MIT License * * Copyright (c) 2017 Caleb Fangmeier * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * @section DESCRIPTION * Main analysis routine file. This file declares the Histogram/Graph objects * that will end up in the final root file. It also declares the values that * are used to populate the histogram, as well as how these values are * calculated. See the Fil-Val documentation for how the system works. */ #include #include #include #include #include "filval/filval.hpp" #include "filval_root/filval_root.hpp" #include "MiniTreeDataSet.hpp" #include #define PI 3.14159 #define W_MASS 80.385 // GeV/c^2 #define Z_MASS 91.188 // GeV/c^2 #define T_MASS 172.44 // GeV/c^2 using namespace std; using namespace fv; using namespace fv::root; void enable_branches(MiniTreeDataSet& mt){ mt.fChain->SetBranchStatus("*", false); mt.track_branch("nLepGood"); mt.track_branch_vec< int >("nLepGood", "LepGood_pdgId"); mt.track_branch_vec("nLepGood", "LepGood_pt"); mt.track_branch_vec("nLepGood", "LepGood_eta"); mt.track_branch_vec("nLepGood", "LepGood_phi"); mt.track_branch_vec("nLepGood", "LepGood_mass"); mt.track_branch_vec< int >("nLepGood", "LepGood_charge"); mt.track_branch_vec< int >("nLepGood", "LepGood_mcMatchId"); mt.track_branch_vec< int >("nLepGood", "LepGood_mcMatchPdgId"); mt.track_branch_vec< int >("nLepGood", "LepGood_mcMatchAny"); mt.track_branch_vec< int >("nLepGood", "LepGood_mcMatchTau"); mt.track_branch_vec< int >("nLepGood", "LepGood_mcPt"); mt.track_branch("nJet"); mt.track_branch_vec("nJet", "Jet_pt"); mt.track_branch_vec("nJet", "Jet_eta"); mt.track_branch_vec("nJet", "Jet_phi"); mt.track_branch_vec("nJet", "Jet_mass"); mt.track_branch_vec("nJet", "Jet_btagCMVA"); mt.track_branch_vec< int >("nJet", "Jet_mcMatchFlav"); mt.track_branch_vec< int >("nJet", "Jet_mcMatchId"); mt.track_branch_vec< int >("nJet", "Jet_mcFlavour"); mt.track_branch("nGenPart"); mt.track_branch_vec< int >("nGenPart", "GenPart_pdgId"); mt.track_branch_vec< int >("nGenPart", "GenPart_motherIndex"); mt.track_branch_vec< int >("nGenPart", "GenPart_motherId"); mt.track_branch_vec("nGenPart", "GenPart_pt"); mt.track_branch_vec("nGenPart", "GenPart_eta"); mt.track_branch_vec("nGenPart", "GenPart_phi"); mt.track_branch_vec("nGenPart", "GenPart_mass"); mt.track_branch_vec< int >("nGenPart", "GenPart_status"); mt.track_branch("nBJetLoose40"); mt.track_branch("nBJetMedium40"); mt.track_branch("nBJetTight40"); mt.track_branch("nVert"); mt.track_branch< int >("run" ); mt.track_branch< int >("lumi"); mt.track_branch< int >("evt" ); mt.track_branch("xsec"); } struct Jet{ TLorentzVector v; int idx; int pdgid; float b_cmva; Jet() { } Jet(const TLorentzVector& v, int idx, int pdgid, float b_cmva) :v(v),idx(idx),pdgid(pdgid),b_cmva(b_cmva) { } static Jet reco(const TLorentzVector& v, int idx, float b_cmva){ return Jet(v, idx, 0, b_cmva); } static Jet mc(const TLorentzVector& v, int idx, int pdgid){ return Jet(v, idx, pdgid, 0); } }; void declare_values(MiniTreeDataSet& mt){ // Define Lorentz Vector(TLorentzVector) object from fields in ntuple lorentz_vectors("LepGood_pt", "LepGood_eta", "LepGood_phi", "LepGood_mass", "LepGood_4v"); lorentz_vectors("GenPart_pt", "GenPart_eta", "GenPart_phi", "GenPart_mass", "GenPart_4v"); lorentz_vectors("Jet_pt", "Jet_eta", "Jet_phi", "Jet_mass", "Jet_4v" ); energies("GenPart_4v", "GenPart_energy"); // Define a couple selections to be used in the top-mass reconstruction. auto& b_mva_filter = GenFunction::register_function("b_mva_filter", FUNC(([cut=0.0](const Jet& j){ return j.b_cmva > cut; }))); auto& b_pdgid_filter = GenFunction::register_function("b_pdgid_filter", FUNC(([](const Jet& j){ return j.pdgid == 5 || j.pdgid==-5; }))); auto& w_mass_filter = GenFunction::register_function("w_mass_filter", FUNC(([win_l=W_MASS-10, win_h=W_MASS+10](const Jet& j1, const Jet& j2){ float inv_mass = (j1.v + j2.v).M(); return inv_mass > win_l && inv_mass < win_h; }))); auto& dup_filter = GenFunction::register_function,Jet)>("dup_filter", FUNC(([](const std::tuple& w, const Jet& b){ int j0 = b.idx; int j1 = std::get<0>(w).idx; int j2 = std::get<1>(w).idx; return (j0 != j1) && (j0 != j2) && (j1 != j2); }))); auto& qg_id_filter = GenFunction::register_function("qg_id_filter", FUNC(([](const Jet& j1, const Jet& j2){ // require both particles be either quarks(not Top) or gluons int id1 = abs(j1.pdgid); int id2 = abs(j2.pdgid); return ((id1 >=1 && id1 <= 5) || id1 == 21) && ((id2 >=1 && id2 <= 5) || id2 == 21); }))); // Here is the calculation of the Top Reconstructed Mass from Jets auto jets = apply(GenFunction::register_function(std::vector,std::vector)>("build_reco_jets", FUNC(([](const std::vector& vs, const std::vector& b_cmvas){ std::vector jets; for(int i=0; i>("Jet_4v"), lookup>("Jet_btagCMVA")), "reco_jets"); auto b_jets = filter(b_mva_filter, jets, "reco_b_jets"); auto w_dijets = tup_filter(w_mass_filter, combinations(jets, "reco_dijets")); auto top_cands = cart_product, Jet>(w_dijets, b_jets); top_cands = tup_filter(dup_filter, top_cands); auto& t_mass = GenFunction::register_function,Jet)>("t_mass", FUNC(([](const std::tuple& w, const Jet& b){ return (std::get<0>(w).v+std::get<1>(w).v+b.v).M(); }))); fv::map(t_mass, top_cands, "reco_top_mass"); // Here is the calculation of the Top Reconstructed Mass from Generator-Level objects jets = apply(GenFunction::register_function(std::vector,std::vector)>("build_mcjets", FUNC(([](const std::vector& vs, const std::vector& pdgid){ std::vector jets; for(int i=0; i>("GenPart_4v"), lookup>("GenPart_pdgId")), "mcjets"); b_jets = filter(b_pdgid_filter, jets); w_dijets = tup_filter(qg_id_filter, combinations(jets)); w_dijets = tup_filter(w_mass_filter, w_dijets); top_cands = cart_product, Jet>(w_dijets, b_jets); top_cands = tup_filter(dup_filter, top_cands); fv::map(t_mass, top_cands, "mc_top_mass"); // calculation of di-jet inv-mass spectrum auto& inv_mass2 = GenFunction::register_function("inv_mass2", FUNC(([] (const Jet& j1, const Jet& j2){ TLorentzVector sum = j1.v + j2.v; return (float)sum.M(); }))); fv::map(inv_mass2, lookup>>("reco_dijets"), "dijet_inv_mass"); count(GenFunction::register_function("bJet_Selection", FUNC(([](float x){ return x>0; }))), "Jet_btagCMVA", "b_jet_count"); auto &is_electron = GenFunction::register_function("is_electron", FUNC(([](int pdgId) { return abs(pdgId) == 11; }))); auto &is_muon = GenFunction::register_function("is_muon", FUNC(([](int pdgId) { return abs(pdgId) == 13; }))); auto &is_lepton = GenFunction::register_function("is_lepton", FUNC(([ie=&is_electron, im=&is_muon](int pdgId) { return (*ie)(pdgId) || (*im)(pdgId); }))); count(is_electron, "GenPart_pdgId", "genEle_count"); count(is_muon, "GenPart_pdgId", "genMu_count"); count(is_lepton, "GenPart_pdgId", "genLep_count"); count(is_electron, "LepGood_pdgId", "recEle_count"); count(is_muon, "LepGood_pdgId", "recMu_count"); count(is_lepton, "LepGood_pdgId", "recLep_count"); fv::pair("genEle_count", "recEle_count", "genEle_count_v_recEle_count"); fv::pair("genMu_count", "recMu_count", "genMu_count_v_recMu_count"); fv::pair("genLep_count", "recLep_count", "genLep_count_v_recLep_count"); obs_filter("trilepton", FUNC(([nLepGood=lookup("nLepGood")]() { return dynamic_cast*>(nLepGood)->get_value() == 3; }))); obs_filter("os-dilepton", FUNC(([LepGood_charge=lookup>("LepGood_charge")]() { auto& charges = LepGood_charge->get_value(); return charges.size()==2 && (charges[0] != charges[1]); }))); obs_filter("ss-dilepton", FUNC(([LepGood_charge=lookup>("LepGood_charge")]() { auto& charges = LepGood_charge->get_value(); return charges.size()==2 && (charges[0] == charges[1]); }))); } void declare_containers(MiniTreeDataSet& mt){ mt.register_container>("lepton_count", "Lepton Multiplicity", lookup("nLepGood"), 8, 0, 8); mt.register_container>("Jet_pt_dist", "Jet P_T", lookup>("Jet_pt"), 50, 0, 500, "Jet P_T"); mt.register_container>("Jet_eta_dist", "Jet Eta", lookup>("Jet_eta"), 50, -3, 3, "Jet Eta"); mt.register_container>("Jet_phi_dist", "Jet Phi", lookup>("Jet_phi"), 20, -PI, PI, "Jet Phi"); mt.register_container>("Jet_mass_dist", "Jet Mass", lookup>("Jet_mass"), 50, 0, 200, "Jet Mass"); mt.register_container>("dijet_inv_mass", "Di-Jet Inv. Mass - All", lookup>("dijet_inv_mass"), 100, 0, 500, "Di-Jet Mass"); mt.register_container>("dijet_inv_mass_osdilepton", "Di-Jet Inv. Mass - OS Dilepton", lookup>("dijet_inv_mass"), 100, 0, 500, "Di-Jet Mass")->add_filter(lookup_obs_filter("os-dilepton")); mt.register_container>("dijet_inv_mass_ssdilepton", "Di-Jet Inv. Mass - SS Dilepton", lookup>("dijet_inv_mass"), 100, 0, 500, "Di-Jet Mass")->add_filter(lookup_obs_filter("ss-dilepton")); mt.register_container>("dijet_inv_mass_trilepton", "Di-Jet Inv. Mass - Trilepton", lookup>("dijet_inv_mass"), 100, 0, 500, "Di-Jet Mass")->add_filter(lookup_obs_filter("trilepton")); mt.register_container>("reco_top_mass", "Reconstructed Top mass", lookup>("reco_top_mass"), 100, 0, 500, "Tri-jet invarient mass"); /* mt.register_container>("reco_top_pt", "Reconstructed Top Pt", */ /* lookup>("reco_top_pt"), 100, 0, 500, */ /* "Tri-jet Pt"); */ mt.register_container>("mc_top_mass", "Reconstructed MC Top mass", lookup>("mc_top_mass"), 100, 0, 500, "Tri-jet invarient mass"); mt.register_container>("nLepvsnJet", "Number of Leptons vs Number of Jets", fv::pair("nLepGood", "nJet"), 7, 0, 7, 20, 0, 20, "Number of Leptons", "Number of Jets"); mt.register_container>("genEle_count_v_recEle_count", "Number of Generated Electrons v. Number of Reconstructed Electrons", lookup>("genEle_count_v_recEle_count"), 10, 0, 10, 10, 0, 10, "Generated Electrons","Reconstructed Electrons"); mt.register_container>("genMu_count_v_recMu_count", "Number of Generated Muons v. Number of Reconstructed Muons", lookup>("genMu_count_v_recMu_count"), 10, 0, 10, 10, 0, 10, "Generated Muons","Reconstructed Muons"); mt.register_container>("genLep_count_v_recLep_count", "Number of Generated Leptons v. Number of Reconstructed Leptons (e & mu only)", lookup>("genLep_count_v_recLep_count"), 10, 0, 10, 10, 0, 10, "Generated Leptons","Reconstructed Leptons"); mt.register_container>("b_jet_count", "B-Jet Multiplicity", lookup("b_jet_count"), 10, 0, 10); mt.register_container>("jet_count_os_dilepton", "Jet Multiplicity - OS Dilepton Events", lookup("nJet"), 14, 0, 14)->add_filter(lookup_obs_filter("os-dilepton")); mt.register_container>("jet_count_ss_dilepton", "Jet Multiplicity - SS Dilepton Events", lookup("nJet"), 14, 0, 14)->add_filter(lookup_obs_filter("ss-dilepton")); mt.register_container>("jet_count_trilepton", "Jet Multiplicity - Trilepton Events", lookup("nJet"), 14, 0, 14)->add_filter(lookup_obs_filter("trilepton")); mt.register_container>("nVert", "Number of Primary Vertices", lookup("nVert"), 50, 0, 50); mt.register_container>("GenPart_pdgId_counter", lookup>("GenPart_pdgId")); mt.register_container>>("GenPart_pdgId", lookup>("GenPart_pdgId")); mt.register_container>>("GenPart_motherIndex", lookup>("GenPart_motherIndex")); mt.register_container>>("GenPart_motherId", lookup>("GenPart_motherId")); mt.register_container>>("GenPart_pt", lookup>("GenPart_pt")); mt.register_container>>("GenPart_eta", lookup>("GenPart_eta")); mt.register_container>>("GenPart_phi", lookup>("GenPart_phi")); mt.register_container>>("GenPart_mass", lookup>("GenPart_mass")); mt.register_container>>("GenPart_energy", lookup>("GenPart_energy")); mt.register_container>>("GenPart_status", lookup>("GenPart_status")); mt.register_container>>("LepGood_mcMatchId", lookup>("LepGood_mcMatchId")); mt.register_container>>("LepGood_mcMatchPdgId", lookup>("LepGood_mcMatchPdgId")); mt.register_container>("run", lookup< int >("run") ); mt.register_container>("lumi", lookup< int >("lumi")); mt.register_container>("evt", lookup< int >("evt") ); mt.register_container>("xsec", lookup("xsec")); mt.register_container>>("Jet_mcMatchFlav", lookup>("Jet_mcMatchFlav")); mt.register_container>>("Jet_mcMatchId", lookup>("Jet_mcMatchId")); mt.register_container>>("Jet_mcFlavour", lookup>("Jet_mcFlavour")); mt.register_container>>("Jet_pt", lookup>("Jet_pt")); mt.register_container>>("Jet_eta", lookup>("Jet_eta")); mt.register_container>>("Jet_phi", lookup>("Jet_phi")); mt.register_container>>("Jet_mass", lookup>("Jet_mass")); } void run_analysis(const std::string& input_filename, bool silent){ gSystem->Load("libfilval.so"); auto replace_suffix = [](const std::string& input, const std::string& new_suffix){ return input.substr(0, input.find_last_of(".")) + new_suffix; }; string log_filename = replace_suffix(input_filename, "_result.log"); fv::util::Log::init_logger(log_filename, fv::util::LogPriority::kLogDebug); string output_filename = replace_suffix(input_filename, "_result.root"); MiniTreeDataSet mt(input_filename, output_filename); enable_branches(mt); declare_values(mt); declare_containers(mt); mt.process(silent); mt.save_all(); } int main(int argc, char * argv[]) { fv::util::ArgParser args(argc, argv); if(!args.cmdOptionExists("-f")) { cout << "Usage: ./main (-s) -f input_minitree.root" << endl; return -1; } bool silent = args.cmdOptionExists("-s"); string input_filename = args.getCmdOption("-f"); run_analysis(input_filename, silent); }