ROOT Analysis for the Inclusive Detachted Dilepton Trigger Lines
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

367 lines
15 KiB

7 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
7 months ago
7 months ago
7 months ago
7 months ago
6 months ago
7 months ago
7 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
  1. #include <string>
  2. #include <iostream>
  3. #include <cmath>
  4. #include <algorithm>
  5. #include <filesystem>
  6. #include <string_view>
  7. #include <ctime>
  8. #include <fstream>
  9. #include "TH1D.h"
  10. #include "TH2D.h"
  11. #include "THStack.h"
  12. #include "TGraph.h"
  13. #include "TTree.h"
  14. #include "TChain.h"
  15. #include "TFile.h"
  16. #include "TCanvas.h"
  17. #include "TROOT.h"
  18. #include "TStyle.h"
  19. #include "TColor.h"
  20. #include "TLorentzVector.h"
  21. #include "TRandom3.h"
  22. #include "TLegend.h"
  23. #include "RooDataHist.h"
  24. #include "RooRealVar.h"
  25. #include "RooPlot.h"
  26. #include "RooGaussian.h"
  27. #include "RooExponential.h"
  28. #include "RooRealConstant.h"
  29. #include "RooAddPdf.h"
  30. #include "RooFitResult.h"
  31. #include "RooProduct.h"
  32. #include "RooCrystalBall.h"
  33. #include "RooBreitWigner.h"
  34. #include "RooArgSet.h"
  35. #include "RooFFTConvPdf.h"
  36. #include "RooNovosibirsk.h"
  37. #include "constants.h"
  38. #include "basic_analysis.h"
  39. #include "hlt1_decision_analysis.h"
  40. #include "bdt_classification.h"
  41. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Inclusive :: B0 To Hp Hm Mu Mu %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  42. int new_analysis_b02hphmmumu()
  43. {
  44. const char *analysis_name = "B0ToHpHmMuMu";
  45. const char *data_tree_name = "SpruceRD_B0ToHpHmMuMu";
  46. const char *sim_tree_name = "B0ToHpHmMuMu_noPID_mapped";
  47. const char *end_state_mass_literal = "m(#pi^{+}#pi^{-}_{(#rightarrow K^{-})}#mu^{+}#mu^{-} & #pi^{+}_{(#rightarrow K^{+})}#pi^{-}#mu^{+}#mu^{-}) [MeV]";
  48. const bool retrain_bdt = false;
  49. const bool skip_fit = false;
  50. TChain *data_chain = new TChain(TString::Format("%s/DecayTree", data_tree_name));
  51. data_chain->Add("/auto/data/pfeiffer/inclusive_detached_dilepton/data_samples/Collision23_Beam6800GeV-VeloClosed-MagDown-Excl-UT_RealData_Sprucing23r1_90000000_RD.root");
  52. // data_chain->Add("/auto/data/pfeiffer/inclusive_detached_dilepton/data_samples/Comm23_B6800GeV-VeCl-MgDo-Excl-UT_RealD_SprPass23r1_94000000_RD_45.root");
  53. FourVect *l14v_data = FourVect::Init(data_chain, "muminus");
  54. FourVect *l24v_data = FourVect::Init(data_chain, "muplus");
  55. FourVect *hp4v_data = FourVect::Init(data_chain, "Kplus");
  56. FourVect *hm4v_data = FourVect::Init(data_chain, "piminus");
  57. Double_t piminus_PID_K;
  58. data_chain->SetBranchAddress("piminus_PID_K", &piminus_PID_K);
  59. TChain *sim_chain = new TChain(TString::Format("%s/DecayTree", sim_tree_name));
  60. sim_chain->Add("/auto/data/pfeiffer/inclusive_detached_dilepton/MC/B0ToHpHmMuMu_mapped_mc.root");
  61. FourVect *l14v_sim = FourVect::Init(sim_chain, "muminus");
  62. FourVect *l24v_sim = FourVect::Init(sim_chain, "muplus");
  63. FourVect *hp4v_sim = FourVect::Init(sim_chain, "Kplus");
  64. FourVect *hm4v_sim = FourVect::Init(sim_chain, "piminus");
  65. Double_t B_Mass_jpsi_var, B_Mass_psi2s_var, B_Mass_sim_var;
  66. TString B_Mass_jpsi_var_name = "B_Mass_jpsi_var";
  67. TString B_Mass_psi2s_var_name = "B_Mass_psi2s_var";
  68. TString B_Mass_sim_var_name = "B_Mass_sim_var";
  69. TTree *tree_B_Mass_jpsi = new TTree("tree_B_Mass_jpsi", TString::Format("B^{0} Mass, J/#psi Mode (%s)", analysis_name));
  70. TTree *tree_B_Mass_psi2s = new TTree("tree_B_Mass_psi2s", TString::Format("B^{0} Mass, #psi(2S) Mode (%s)", analysis_name));
  71. TTree *tree_B_Mass_sim = new TTree("tree_B_Mass_sim", TString::Format("B^{0} Mass, Simualted (%s)", analysis_name));
  72. tree_B_Mass_jpsi->Branch(B_Mass_jpsi_var_name, &B_Mass_jpsi_var);
  73. tree_B_Mass_psi2s->Branch(B_Mass_psi2s_var_name, &B_Mass_psi2s_var);
  74. tree_B_Mass_sim->Branch(B_Mass_sim_var_name, &B_Mass_sim_var);
  75. 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);
  76. 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);
  77. 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.);
  78. 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.);
  79. TH1D *h1_bdt_probs = new TH1D("h1_bdt_probs", "BDT Probabilities", 100, -1, 1);
  80. h1_B_Mass_unf->GetXaxis()->SetTitle(end_state_mass_literal);
  81. h1_B_Mass_bdtf->GetXaxis()->SetTitle(end_state_mass_literal);
  82. h2_Hlt1_flags_B_Mass->GetXaxis()->SetTitle(end_state_mass_literal);
  83. h2_Hlt1_flags_excl_B_Mass->GetXaxis()->SetTitle(end_state_mass_literal);
  84. ConnectHlt1Decisions(data_chain, h2_Hlt1_flags_B_Mass, h2_Hlt1_flags_excl_B_Mass);
  85. auto hlt1_decision_histos = CreateHlt1DecisionHistos(analysis_name);
  86. std::map<std::string, int> exclusive_hits{};
  87. TV *kplus_pid_k_var = TV::Double("Kplus_PID_K", "Kplus_PID_K");
  88. std::vector<TV *> vars{
  89. TV::Float("B0_PT", "B0_PT"),
  90. TV::Float("B0_BPVFDCHI2", "B0_BPVFDCHI2"),
  91. TV::Float("B0_BPVDIRA", "B0_BPVDIRA"),
  92. TV::Double("B0_CHI2", "B0_CHI2"),
  93. TV::Float("Jpsi_BPVIPCHI2", "Jpsi_BPVIPCHI2"),
  94. TV::Float("Jpsi_PT", "Jpsi_PT"),
  95. TV::Double("Jpsi_CHI2", "Jpsi_CHI2"),
  96. TV::Float("Kst0_BPVIPCHI2", "Kst0_BPVIPCHI2"),
  97. TV::Float("Kst0_PT", "Kst0_PT"),
  98. TV::Float("Kplus_BPVIPCHI2", "Kplus_BPVIPCHI2"),
  99. TV::Float("Kplus_PT", "Kplus_PT"),
  100. TV::Float("piminus_BPVIPCHI2", "piminus_BPVIPCHI2"),
  101. TV::Float("piminus_PT", "piminus_PT"),
  102. kplus_pid_k_var,
  103. //TV::Float("muminus_BPVIPCHI2", "muminus_BPVIPCHI2"),
  104. TV::Float("muminus_PT", "muminus_PT"),
  105. //TV::Float("muplus_BPVIPCHI2", "muplus_BPVIPCHI2"),
  106. TV::Float("muplus_PT", "muplus_PT"),
  107. };
  108. TTree *sig_tree = new TTree("TreeS", "tree containing signal data");
  109. TTree *bkg_tree = new TTree("TreeB", "tree containing background data");
  110. ConnectVarsToData(vars, data_chain, sim_chain, sig_tree, bkg_tree);
  111. unsigned int data_entries = data_chain->GetEntries();
  112. unsigned int sim_entries = sim_chain->GetEntries();
  113. unsigned int bkg_events = 0;
  114. unsigned int sig_events = 0;
  115. if (retrain_bdt)
  116. {
  117. std::cout << "# Starting with BDT retrain." << std::endl;
  118. for (unsigned int i = 0; i < data_entries; i++)
  119. {
  120. data_chain->GetEntry(i);
  121. TLorentzVector reconstructed_Kstar = hp4v_data->LorentzVector() + hm4v_data->LorentzVector();
  122. TLorentzVector dimuon = l14v_data->LorentzVector() + l24v_data->LorentzVector();
  123. Double_t reconstructed_B_Mass = (reconstructed_Kstar + dimuon).M();
  124. if (std::all_of(vars.begin(), vars.end(), [](TV *v)
  125. { return v->IsDataFinite(); }))
  126. {
  127. if (reconstructed_B_Mass > 5500. && ((TMath::Abs(dimuon.M() - JPSI_MASS) < 100.) || (TMath::Abs(dimuon.M() - PSI2S_MASS) < 100.))
  128. && kplus_pid_k_var->GetDataDouble() > -3 && (kplus_pid_k_var->GetDataDouble() - piminus_PID_K) > 0)
  129. {
  130. bkg_tree->Fill();
  131. bkg_events++;
  132. }
  133. }
  134. PrintProgress(TString::Format("%s BKG Collection", analysis_name), data_entries, 10000, i);
  135. }
  136. std::cout << "# Added " << bkg_events << " background events." << std::endl;
  137. }
  138. else
  139. {
  140. std::cout << "# Starting without BDT retrain." << std::endl;
  141. bkg_events = data_entries;
  142. }
  143. for (unsigned int i = 0; i < sim_entries; i++)
  144. {
  145. sim_chain->GetEntry(i);
  146. TLorentzVector reconstructed_Kstar = hp4v_sim->LorentzVector() + hm4v_sim->LorentzVector();
  147. Double_t reconstructed_B_Mass = (reconstructed_Kstar + l14v_sim->LorentzVector() + l24v_sim->LorentzVector()).M();
  148. if (sig_events < bkg_events)
  149. {
  150. if (retrain_bdt && std::all_of(vars.begin(), vars.end(), [](TV *v)
  151. { return v->IsMCFinite(); }))
  152. {
  153. sig_tree->Fill();
  154. sig_events++;
  155. }
  156. }
  157. B_Mass_sim_var = reconstructed_B_Mass;
  158. tree_B_Mass_sim->Fill();
  159. PrintProgress(TString::Format("%s SIG Collection", analysis_name), sim_entries, 10000, i);
  160. }
  161. if (retrain_bdt)
  162. {
  163. std::cout << "# Added " << sig_events << " signal events." << std::endl;
  164. TrainBDT(vars, analysis_name, sig_tree, bkg_tree);
  165. std::cout << "# Finished BDT retrain." << std::endl;
  166. }
  167. if (skip_fit) {
  168. std::cout << "# Skipping evaluation of data." << std::endl;
  169. return 0;
  170. }
  171. std::cout << "# Starting evaluation of data." << std::endl;
  172. Float_t *train_vars = new Float_t[vars.size()];
  173. auto reader = SetupReader(vars, train_vars, analysis_name);
  174. const double mva_cut_value = 0.0;
  175. for (unsigned int i = 0; i < data_entries; i++)
  176. {
  177. data_chain->GetEntry(i);
  178. TLorentzVector dimuon = l14v_data->LorentzVector() + l24v_data->LorentzVector();
  179. TLorentzVector reconstructed_Kstar = hp4v_data->LorentzVector() + hm4v_data->LorentzVector();
  180. Double_t reconstructed_B_Mass = (reconstructed_Kstar + dimuon).M();
  181. if (std::all_of(vars.begin(), vars.end(), [](TV *v)
  182. { return v->IsDataFinite(); }))
  183. {
  184. for (size_t j = 0; j < vars.size(); j++)
  185. {
  186. if (vars[j]->IsDouble())
  187. {
  188. train_vars[j] = vars[j]->GetDataDouble();
  189. }
  190. else if (vars[j]->IsFloat())
  191. {
  192. train_vars[j] = vars[j]->GetDataFloat();
  193. }
  194. }
  195. }
  196. if (TMath::Abs(dimuon.M() - JPSI_MASS) < 100.)
  197. {
  198. CheckHlt1Decisioins(h2_Hlt1_flags_B_Mass, h2_Hlt1_flags_excl_B_Mass, exclusive_hits, reconstructed_B_Mass);
  199. FillHlt1DecisionHistos(hlt1_decision_histos, reconstructed_B_Mass);
  200. }
  201. h1_B_Mass_unf->Fill(reconstructed_B_Mass);
  202. 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.)))
  203. {
  204. double mva_response = reader->EvaluateMVA("BDT");
  205. h1_bdt_probs->Fill(mva_response);
  206. if (mva_response > mva_cut_value)
  207. {
  208. h1_B_Mass_bdtf->Fill(reconstructed_B_Mass);
  209. if (TMath::Abs(dimuon.M() - JPSI_MASS) < 100.)
  210. {
  211. B_Mass_jpsi_var = reconstructed_B_Mass;
  212. tree_B_Mass_jpsi->Fill();
  213. }
  214. else if (TMath::Abs(dimuon.M() - PSI2S_MASS) < 100.)
  215. {
  216. B_Mass_psi2s_var = reconstructed_B_Mass;
  217. tree_B_Mass_psi2s->Fill();
  218. }
  219. }
  220. }
  221. PrintProgress(TString::Format("%s BDT Evaluation", analysis_name), data_entries, 10000, i);
  222. }
  223. std::cout << "# Exclusive Hits" << std::endl;
  224. for (const auto &[line, hits] : exclusive_hits)
  225. {
  226. std::cout << line << ": " << hits << std::endl;
  227. }
  228. DrawInDefaultCanvas(h2_Hlt1_flags_B_Mass, analysis_name, 0.16, "COLZ");
  229. DrawInDefaultCanvas(h2_Hlt1_flags_excl_B_Mass, analysis_name, 0.16, "COLZ");
  230. DrawInDefaultCanvas(h1_B_Mass_unf, analysis_name, 0.1);
  231. DrawInDefaultCanvas(h1_B_Mass_bdtf, analysis_name, 0.1);
  232. 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));
  233. auto roofit_hist_sim = CreateRooDataSetAndFitCB(tree_B_Mass_sim, B_Mass_sim_var_name, end_state_mass_literal, false, false, ShapeParamters{});
  234. 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);
  235. roofit_hist_sim.shape_parameters.sigma_lr = roofit_hist_jpsi_fitsum.shape_parameters.sigma_lr;
  236. 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);
  237. DrawInDefaultCanvas(roofit_hist_jpsi_fitsum, analysis_name);
  238. DrawInDefaultCanvas(roofit_hist_psi2s_fitsum, analysis_name);
  239. DrawInDefaultCanvas(roofit_hist_sim, analysis_name);
  240. // DrawHlt1DecisionHistos(analysis_name, hlt1_decision_histos);
  241. DrawBDTProbs(h1_bdt_probs, mva_cut_value, analysis_name);
  242. 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);
  243. std::time_t t = std::time(nullptr);
  244. std::tm tm = *std::localtime(&t);
  245. ofstream res_file;
  246. res_file.open(TString::Format("%s_results.txt", analysis_name).Data(), ios::out | ios::trunc);
  247. 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);
  248. 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);
  249. auto mumu_br_frac = DivWithErr(BRF_JPSI_MUMU_VAL, BRF_JPSI_MUMU_ERR, BRF_PSI2S_MUMU_VAL, BRF_PSI2S_MUMU_ERR);
  250. res_file << "#### " << analysis_name << " @ " << std::put_time(&tm, "%c") << " ####" << std::endl;
  251. res_file << "J/Psi Mode: " << ErrToStr(roofit_hist_jpsi_fitsum.signal_yield, 0) << " / " << ErrToStr(roofit_hist_jpsi_fitsum.background_yield, 0) << std::endl;
  252. res_file << " Sig/Bkg: " << ErrToStr(jpsi_sigobkg, 2) << std::endl;
  253. res_file << "Psi(2S) Mode: " << ErrToStr(roofit_hist_psi2s_fitsum.signal_yield, 0) << " / " << ErrToStr(roofit_hist_psi2s_fitsum.background_yield, 0) << std::endl;
  254. res_file << " Sig/Bkg: " << ErrToStr(psi2s_sigobkg, 2) << std::endl;
  255. res_file << "Mode Yield Ratio: " << ErrToStr(signal_ratio, 3) << std::endl;
  256. res_file << "Rel Br Frac MuMu: " << ErrToStr(mumu_br_frac, 3) << std::endl;
  257. auto br_frac = MultWithErr(signal_ratio.first, signal_ratio.second, mumu_br_frac.first, mumu_br_frac.second);
  258. res_file << "Rel Br Frac: " << ErrToStr(br_frac, 3) << std::endl
  259. << std::endl;
  260. res_file << std::endl
  261. << "Fitted Parameters: Simulation" << std::endl
  262. << std::endl;
  263. for (const auto &par : roofit_hist_sim.fitted_params)
  264. {
  265. res_file << par.ToString(true).c_str() << std::endl;
  266. }
  267. res_file << std::endl
  268. << "Fitted Parameters: J/PSI" << std::endl
  269. << std::endl;
  270. for (const auto &par : roofit_hist_jpsi_fitsum.fitted_params)
  271. {
  272. res_file << par.ToString(true).c_str() << std::endl;
  273. }
  274. res_file << std::endl
  275. << "Fitted Parameters: PSI(2S)" << std::endl
  276. << std::endl;
  277. for (const auto &par : roofit_hist_psi2s_fitsum.fitted_params)
  278. {
  279. res_file << par.ToString(true).c_str() << std::endl;
  280. }
  281. auto print_table = [&res_file](std::string name, std::pair<double, double> sig, std::pair<double, double> bkg)
  282. {
  283. res_file << std::endl;
  284. res_file << "# " << name << std::endl;
  285. res_file << "\\begin{tabular}{c|c}" << std::endl;
  286. res_file << "$N_{Sig}$ & $N_{Bkg}$\\\\\\hline" << std::endl;
  287. res_file << TString::Format("$%.0f \\pm %.0f$ & $%.0f \\pm %.0f$", sig.first, sig.second, bkg.first, bkg.second).Data() << std::endl;
  288. res_file << "\\end{tabular}" << std::endl;
  289. };
  290. print_table("J/psi", roofit_hist_jpsi_fitsum.signal_yield, roofit_hist_jpsi_fitsum.background_yield);
  291. print_table("psi(2S)", roofit_hist_psi2s_fitsum.signal_yield, roofit_hist_psi2s_fitsum.background_yield);
  292. res_file.close();
  293. return 0;
  294. }