#include #include #include #include #include #include #include #include #include "TH1D.h" #include "TH2D.h" #include "THStack.h" #include "TGraph.h" #include "TTree.h" #include "TChain.h" #include "TFile.h" #include "TCanvas.h" #include "TROOT.h" #include "TStyle.h" #include "TColor.h" #include "TLorentzVector.h" #include "TRandom3.h" #include "TLegend.h" #include "RooDataHist.h" #include "RooRealVar.h" #include "RooPlot.h" #include "RooGaussian.h" #include "RooExponential.h" #include "RooRealConstant.h" #include "RooAddPdf.h" #include "RooFitResult.h" #include "RooProduct.h" #include "RooCrystalBall.h" #include "RooBreitWigner.h" #include "RooArgSet.h" #include "RooFFTConvPdf.h" #include "RooNovosibirsk.h" #include "constants.h" #include "basic_analysis.h" #include "hlt1_decision_analysis.h" #include "bdt_classification.h" // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Inclusive :: B0 To Hp Hm Mu Mu %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% int new_analysis_b02hphmmumu() { const char *analysis_name = "B0ToHpHmMuMu"; const char *data_tree_name = "SpruceRD_B0ToHpHmMuMu"; const char *sim_tree_name = "B0ToHpHmMuMu_noPID_mapped"; const char *end_state_mass_literal = "m(#pi^{+}#pi^{-}_{(#rightarrow K^{-})}#mu^{+}#mu^{-} & #pi^{+}_{(#rightarrow K^{+})}#pi^{-}#mu^{+}#mu^{-}) [MeV]"; const bool retrain_bdt = true; TChain *data_chain = new TChain(TString::Format("%s/DecayTree", data_tree_name)); data_chain->Add("/auto/data/pfeiffer/inclusive_detached_dilepton/data_samples/Collision23_Beam6800GeV-VeloClosed-MagDown-Excl-UT_RealData_Sprucing23r1_90000000_RD.root"); // data_chain->Add("/auto/data/pfeiffer/inclusive_detached_dilepton/data_samples/Comm23_B6800GeV-VeCl-MgDo-Excl-UT_RealD_SprPass23r1_94000000_RD_45.root"); FourVect *l14v_data = FourVect::Init(data_chain, "muminus"); FourVect *l24v_data = FourVect::Init(data_chain, "muplus"); FourVect *hp4v_data = FourVect::Init(data_chain, "Kplus"); FourVect *hm4v_data = FourVect::Init(data_chain, "piminus"); Double_t piminus_PID_K; data_chain->SetBranchAddress("piminus_PID_K", &piminus_PID_K); TChain *sim_chain = new TChain(TString::Format("%s/DecayTree", sim_tree_name)); sim_chain->Add("/auto/data/pfeiffer/inclusive_detached_dilepton/MC/B0ToHpHmMuMu_mapped_mc.root"); FourVect *l14v_sim = FourVect::Init(sim_chain, "muminus"); FourVect *l24v_sim = FourVect::Init(sim_chain, "muplus"); FourVect *hp4v_sim = FourVect::Init(sim_chain, "Kplus"); FourVect *hm4v_sim = FourVect::Init(sim_chain, "piminus"); Double_t B_Mass_jpsi_var, B_Mass_psi2s_var, B_Mass_sim_var; TString B_Mass_jpsi_var_name = "B_Mass_jpsi_var"; TString B_Mass_psi2s_var_name = "B_Mass_psi2s_var"; TString B_Mass_sim_var_name = "B_Mass_sim_var"; TTree *tree_B_Mass_jpsi = new TTree("tree_B_Mass_jpsi", TString::Format("B^{0} Mass, J/#psi Mode (%s)", analysis_name)); TTree *tree_B_Mass_psi2s = new TTree("tree_B_Mass_psi2s", TString::Format("B^{0} Mass, #psi(2S) Mode (%s)", analysis_name)); TTree *tree_B_Mass_sim = new TTree("tree_B_Mass_sim", TString::Format("B^{0} Mass, Simualted (%s)", analysis_name)); tree_B_Mass_jpsi->Branch(B_Mass_jpsi_var_name, &B_Mass_jpsi_var); tree_B_Mass_psi2s->Branch(B_Mass_psi2s_var_name, &B_Mass_psi2s_var); tree_B_Mass_sim->Branch(B_Mass_sim_var_name, &B_Mass_sim_var); TH1D *h1_B_Mass_unf = new TH1D("h1_B_Mass_unf", TString::Format("B^{0} Mass (%s), Unfiltered", analysis_name), B_MASS_HIST_BINS, B_MASS_VAR_MIN, B_MASS_VAR_MAX); TH1D *h1_B_Mass_bdtf = new TH1D("h1_B_Mass_bdtf", TString::Format("B^{0} Mass (%s), BDT Filter", analysis_name), B_MASS_HIST_BINS, B_MASS_VAR_MIN, B_MASS_VAR_MAX); TH2D *h2_Hlt1_flags_B_Mass = new TH2D("h2_Hlt1_flags_B_Mass", "Hlt1 Decision vs B^{0} Mass", 50, 5100, 5400, 13, 1., 14.); TH2D *h2_Hlt1_flags_excl_B_Mass = new TH2D("h2_Hlt1_flags_excl_B_Mass", "Excl Hlt1 Decision vs B^{0} Mass", 50, 5100, 5400, 13, 1., 14.); TH1D *h1_bdt_probs = new TH1D("h1_bdt_probs", "BDT Probabilities", 100, -1, 1); h1_B_Mass_unf->GetXaxis()->SetTitle(end_state_mass_literal); h1_B_Mass_bdtf->GetXaxis()->SetTitle(end_state_mass_literal); h2_Hlt1_flags_B_Mass->GetXaxis()->SetTitle(end_state_mass_literal); h2_Hlt1_flags_excl_B_Mass->GetXaxis()->SetTitle(end_state_mass_literal); ConnectHlt1Decisions(data_chain, h2_Hlt1_flags_B_Mass, h2_Hlt1_flags_excl_B_Mass); auto hlt1_decision_histos = CreateHlt1DecisionHistos(analysis_name); std::map exclusive_hits{}; TV *kplus_pid_k_var = TV::Double("Kplus_PID_K", "Kplus_PID_K"); std::vector vars{ TV::Float("B0_PT", "B0_PT"), TV::Float("B0_BPVFDCHI2", "B0_BPVFDCHI2"), TV::Float("B0_BPVDIRA", "B0_BPVDIRA"), TV::Float("Jpsi_BPVIPCHI2", "Jpsi_BPVIPCHI2"), TV::Float("Jpsi_PT", "Jpsi_PT"), TV::Float("Kst0_BPVIPCHI2", "Kst0_BPVIPCHI2"), TV::Float("Kst0_PT", "Kst0_PT"), TV::Float("Kplus_BPVIPCHI2", "Kplus_BPVIPCHI2"), TV::Float("Kplus_PT", "Kplus_PT"), TV::Float("piminus_BPVIPCHI2", "piminus_BPVIPCHI2"), TV::Float("piminus_PT", "piminus_PT"), kplus_pid_k_var, TV::Float("muminus_BPVIPCHI2", "muminus_BPVIPCHI2"), // TV::Float("muminus_PT", "muminus_PT"), TV::Float("muplus_BPVIPCHI2", "muplus_BPVIPCHI2"), // TV::Float("muplus_PT", "muplus_PT"), }; TTree *sig_tree = new TTree("TreeS", "tree containing signal data"); TTree *bkg_tree = new TTree("TreeB", "tree containing background data"); ConnectVarsToData(vars, data_chain, sim_chain, sig_tree, bkg_tree); unsigned int data_entries = data_chain->GetEntries(); unsigned int sim_entries = sim_chain->GetEntries(); unsigned int bkg_events = 0; unsigned int sig_events = 0; if (retrain_bdt) { std::cout << "# Starting with BDT retrain." << std::endl; for (unsigned int i = 0; i < data_entries; i++) { data_chain->GetEntry(i); TLorentzVector reconstructed_Kstar = hp4v_data->LorentzVector() + hm4v_data->LorentzVector(); TLorentzVector dimuon = l14v_data->LorentzVector() + l24v_data->LorentzVector(); Double_t reconstructed_B_Mass = (reconstructed_Kstar + dimuon).M(); if (std::all_of(vars.begin(), vars.end(), [](TV *v) { return v->IsDataFinite(); })) { if (reconstructed_B_Mass > 5500. && ((TMath::Abs(dimuon.M() - JPSI_MASS) < 100.) || (TMath::Abs(dimuon.M() - PSI2S_MASS) < 100.))) { bkg_tree->Fill(); bkg_events++; } } PrintProgress(TString::Format("%s BKG Collection", analysis_name), data_entries, 10000, i); } std::cout << "# Added " << bkg_events << " background events." << std::endl; } else { std::cout << "# Starting without BDT retrain." << std::endl; bkg_events = data_entries; } for (unsigned int i = 0; i < sim_entries; i++) { sim_chain->GetEntry(i); TLorentzVector reconstructed_Kstar = hp4v_sim->LorentzVector() + hm4v_sim->LorentzVector(); Double_t reconstructed_B_Mass = (reconstructed_Kstar + l14v_sim->LorentzVector() + l24v_sim->LorentzVector()).M(); if (sig_events < bkg_events) { if (retrain_bdt && std::all_of(vars.begin(), vars.end(), [](TV *v) { return v->IsMCFinite(); })) { sig_tree->Fill(); sig_events++; } } B_Mass_sim_var = reconstructed_B_Mass; tree_B_Mass_sim->Fill(); PrintProgress(TString::Format("%s SIG Collection", analysis_name), sim_entries, 10000, i); } if (retrain_bdt) { std::cout << "# Added " << sig_events << " signal events." << std::endl; TrainBDT(vars, analysis_name, sig_tree, bkg_tree); std::cout << "# Finished BDT retrain." << std::endl; } std::cout << "# Starting evaluation of data." << std::endl; Float_t *train_vars = new Float_t[vars.size()]; auto reader = SetupReader(vars, train_vars, analysis_name); const double mva_cut_value = 0.0; for (unsigned int i = 0; i < data_entries; i++) { data_chain->GetEntry(i); TLorentzVector dimuon = l14v_data->LorentzVector() + l24v_data->LorentzVector(); TLorentzVector reconstructed_Kstar = hp4v_data->LorentzVector() + hm4v_data->LorentzVector(); Double_t reconstructed_B_Mass = (reconstructed_Kstar + dimuon).M(); if (std::all_of(vars.begin(), vars.end(), [](TV *v) { return v->IsDataFinite(); })) { for (size_t j = 0; j < vars.size(); j++) { if (vars[j]->IsDouble()) { train_vars[j] = vars[j]->GetDataDouble(); } else if (vars[j]->IsFloat()) { train_vars[j] = vars[j]->GetDataFloat(); } } } if (TMath::Abs(dimuon.M() - JPSI_MASS) < 100.) { CheckHlt1Decisioins(h2_Hlt1_flags_B_Mass, h2_Hlt1_flags_excl_B_Mass, exclusive_hits, reconstructed_B_Mass); FillHlt1DecisionHistos(hlt1_decision_histos, reconstructed_B_Mass); } h1_B_Mass_unf->Fill(reconstructed_B_Mass); if (kplus_pid_k_var->GetDataDouble() > -3 && (kplus_pid_k_var->GetDataDouble() - piminus_PID_K) > 0 && TMath::Abs(reconstructed_Kstar.M() - KSTAR_MASS) < 100. && ((TMath::Abs(dimuon.M() - JPSI_MASS) < 100.) || (TMath::Abs(dimuon.M() - PSI2S_MASS) < 100.))) { double mva_response = reader->EvaluateMVA("BDT"); h1_bdt_probs->Fill(mva_response); if (mva_response > mva_cut_value) { h1_B_Mass_bdtf->Fill(reconstructed_B_Mass); if (TMath::Abs(dimuon.M() - JPSI_MASS) < 100.) { B_Mass_jpsi_var = reconstructed_B_Mass; tree_B_Mass_jpsi->Fill(); } else if (TMath::Abs(dimuon.M() - PSI2S_MASS) < 100.) { B_Mass_psi2s_var = reconstructed_B_Mass; tree_B_Mass_psi2s->Fill(); } } } PrintProgress(TString::Format("%s BDT Evaluation", analysis_name), data_entries, 10000, i); } std::cout << "# Exclusive Hits" << std::endl; for (const auto &[line, hits] : exclusive_hits) { std::cout << line << ": " << hits << std::endl; } DrawInDefaultCanvas(h2_Hlt1_flags_B_Mass, analysis_name, 0.16, "COLZ"); DrawInDefaultCanvas(h2_Hlt1_flags_excl_B_Mass, analysis_name, 0.16, "COLZ"); DrawInDefaultCanvas(h1_B_Mass_unf, analysis_name, 0.1); DrawInDefaultCanvas(h1_B_Mass_bdtf, analysis_name, 0.1); DrawInDefaultCanvasStacked({h1_B_Mass_unf, h1_B_Mass_bdtf}, {kRed, kBlue}, {0, 3003}, analysis_name, TString::Format("B^{0} Mass (%s) Before/After BDT Selection", analysis_name)); auto roofit_hist_sim = CreateRooDataSetAndFitCB(tree_B_Mass_sim, B_Mass_sim_var_name, end_state_mass_literal, false, false, ShapeParamters{}); auto roofit_hist_jpsi_fitsum = CreateRooDataSetAndFitCB(tree_B_Mass_jpsi, B_Mass_jpsi_var_name, end_state_mass_literal, true, true, roofit_hist_sim.shape_parameters); roofit_hist_sim.shape_parameters.sigma_lr = roofit_hist_jpsi_fitsum.shape_parameters.sigma_lr; auto roofit_hist_psi2s_fitsum = CreateRooDataSetAndFitCB(tree_B_Mass_psi2s, B_Mass_psi2s_var_name, end_state_mass_literal, true, true, roofit_hist_sim.shape_parameters, true); DrawInDefaultCanvas(roofit_hist_jpsi_fitsum, analysis_name); DrawInDefaultCanvas(roofit_hist_psi2s_fitsum, analysis_name); DrawInDefaultCanvas(roofit_hist_sim, analysis_name); // DrawHlt1DecisionHistos(analysis_name, hlt1_decision_histos); DrawBDTProbs(h1_bdt_probs, mva_cut_value, analysis_name); auto signal_ratio = DivWithErr(roofit_hist_psi2s_fitsum.signal_yield.first, roofit_hist_psi2s_fitsum.signal_yield.second, roofit_hist_jpsi_fitsum.signal_yield.first, roofit_hist_jpsi_fitsum.signal_yield.second); std::time_t t = std::time(nullptr); std::tm tm = *std::localtime(&t); ofstream res_file; res_file.open(TString::Format("%s_results.txt", analysis_name).Data(), ios::out | ios::trunc); auto jpsi_sigobkg = DivWithErr(roofit_hist_jpsi_fitsum.signal_yield.first, roofit_hist_jpsi_fitsum.signal_yield.second, roofit_hist_jpsi_fitsum.background_yield.first, roofit_hist_jpsi_fitsum.background_yield.second); auto psi2s_sigobkg = DivWithErr(roofit_hist_psi2s_fitsum.signal_yield.first, roofit_hist_psi2s_fitsum.signal_yield.second, roofit_hist_psi2s_fitsum.background_yield.first, roofit_hist_psi2s_fitsum.background_yield.second); auto mumu_br_frac = DivWithErr(BRF_JPSI_MUMU_VAL, BRF_JPSI_MUMU_ERR, BRF_PSI2S_MUMU_VAL, BRF_PSI2S_MUMU_ERR); res_file << "#### " << analysis_name << " @ " << std::put_time(&tm, "%c") << " ####" << std::endl; res_file << "J/Psi Mode: " << ErrToStr(roofit_hist_jpsi_fitsum.signal_yield, 0) << " / " << ErrToStr(roofit_hist_jpsi_fitsum.background_yield, 0) << std::endl; res_file << " Sig/Bkg: " << ErrToStr(jpsi_sigobkg, 2) << std::endl; res_file << "Psi(2S) Mode: " << ErrToStr(roofit_hist_psi2s_fitsum.signal_yield, 0) << " / " << ErrToStr(roofit_hist_psi2s_fitsum.background_yield, 0) << std::endl; res_file << " Sig/Bkg: " << ErrToStr(psi2s_sigobkg, 2) << std::endl; res_file << "Mode Yield Ratio: " << ErrToStr(signal_ratio, 3) << std::endl; res_file << "Rel Br Frac MuMu: " << ErrToStr(mumu_br_frac, 3) << std::endl; auto br_frac = MultWithErr(signal_ratio.first, signal_ratio.second, mumu_br_frac.first, mumu_br_frac.second); res_file << "Rel Br Frac: " << ErrToStr(br_frac, 3) << std::endl << std::endl; res_file << std::endl << "Fitted Parameters: Simulation" << std::endl << std::endl; for (const auto &par : roofit_hist_sim.fitted_params) { res_file << par.ToString(true).c_str() << std::endl; } res_file << std::endl << "Fitted Parameters: J/PSI" << std::endl << std::endl; for (const auto &par : roofit_hist_jpsi_fitsum.fitted_params) { res_file << par.ToString(true).c_str() << std::endl; } res_file << std::endl << "Fitted Parameters: PSI(2S)" << std::endl << std::endl; for (const auto &par : roofit_hist_psi2s_fitsum.fitted_params) { res_file << par.ToString(true).c_str() << std::endl; } auto print_table = [&res_file](std::string name, std::pair sig, std::pair bkg) { res_file << std::endl; res_file << "# " << name << std::endl; res_file << "\\begin{tabular}{c|c}" << std::endl; res_file << "$N_{Sig}$ & $N_{Bkg}$\\\\\\hline" << std::endl; res_file << TString::Format("$%.0f \\pm %.0f$ & $%.0f \\pm %.0f$", sig.first, sig.second, bkg.first, bkg.second).Data() << std::endl; res_file << "\\end{tabular}" << std::endl; }; print_table("J/psi", roofit_hist_jpsi_fitsum.signal_yield, roofit_hist_jpsi_fitsum.background_yield); print_table("psi(2S)", roofit_hist_psi2s_fitsum.signal_yield, roofit_hist_psi2s_fitsum.background_yield); res_file.close(); return 0; }