293 lines
12 KiB
C++
293 lines
12 KiB
C++
#include <string>
|
|
#include <iostream>
|
|
#include <cmath>
|
|
#include <algorithm>
|
|
#include <filesystem>
|
|
#include <string_view>
|
|
#include <ctime>
|
|
#include <fstream>
|
|
|
|
#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^{-})";
|
|
const bool retrain_bdt = false;
|
|
|
|
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");
|
|
|
|
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");
|
|
|
|
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 Mass, J/#psi Mode (%s)", analysis_name));
|
|
TTree *tree_B_Mass_psi2s = new TTree("tree_B_Mass_psi2s", TString::Format("B Mass, #psi(2S) Mode (%s)", analysis_name));
|
|
TTree *tree_B_Mass_sim = new TTree("tree_B_Mass_sim", TString::Format("B Mass, Simualted (%s_noPID)", 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 Mass (%s), Unfiltered", data_tree_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 Mass (%s), BDT Filter", data_tree_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 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 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<std::string, int> exclusive_hits{};
|
|
|
|
std::vector<TV *> 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("Kplus_BPVIPCHI2", "Kplus_BPVIPCHI2"),
|
|
TV::Float("Kplus_PT", "Kplus_PT"),
|
|
TV::Float("piminus_BPVIPCHI2", "piminus_BPVIPCHI2"),
|
|
TV::Float("piminus_PT", "piminus_PT"),
|
|
TV::Double("Kplus_PROBNN_K", "Kplus_PROBNN_K"),
|
|
TV::Float("muminus_BPVIPCHI2", "muminus_BPVIPCHI2"),
|
|
TV::Float("muplus_BPVIPCHI2", "muplus_BPVIPCHI2"),
|
|
};
|
|
|
|
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;
|
|
|
|
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);
|
|
}
|
|
|
|
double mva_response = reader->EvaluateMVA("BDT");
|
|
h1_bdt_probs->Fill(mva_response);
|
|
|
|
h1_B_Mass_unf->Fill(reconstructed_B_Mass);
|
|
|
|
if (mva_response > mva_cut_value)
|
|
{
|
|
h1_B_Mass_bdtf->Fill(reconstructed_B_Mass);
|
|
if (TMath::Abs(reconstructed_Kstar.M() - KSTAR_MASS) < 100.)
|
|
{
|
|
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);
|
|
|
|
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);
|
|
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);
|
|
|
|
res_file << "#### " << std::put_time(&tm, "%c") << " ####"<< std::endl;
|
|
res_file << "J/Psi Mode: " << roofit_hist_jpsi_fitsum.signal_yield.first << " +- " << roofit_hist_jpsi_fitsum.signal_yield.second << std::endl;
|
|
res_file << "Psi(2S) Mode: " << roofit_hist_psi2s_fitsum.signal_yield.first << " +- " << roofit_hist_psi2s_fitsum.signal_yield.second << std::endl;
|
|
res_file << "Mode Yield Ratio: " << signal_ratio.first << " +- " << signal_ratio.second << std::endl;
|
|
res_file << "Rel Br Frac MuMu: " << (BRF_JPSI_MUMU_VAL / BRF_PSI2S_MUMU_VAL) << std::endl;
|
|
res_file << "Rel Br Frac: " << signal_ratio.first * (BRF_JPSI_MUMU_VAL / BRF_PSI2S_MUMU_VAL) << std::endl;
|
|
|
|
res_file.close();
|
|
|
|
return 0;
|
|
} |