422 lines
16 KiB
C++
422 lines
16 KiB
C++
//Renata Kopecna
|
|
|
|
#include <backgroundfit.hh>
|
|
|
|
#include <fstream>
|
|
#include <sstream> // std::istringstream
|
|
|
|
#include <bu2kstarmumu_parameters.hh>
|
|
#include <bu2kstarmumu_plotter.hh>
|
|
#include <bu2kstarmumu_pdf.hh>
|
|
#include <folder.hh>
|
|
#include <fitter.hh>
|
|
#include <paths.hh>
|
|
#include <design.hh>
|
|
#include <helpers.hh>
|
|
#include <event.hh>
|
|
|
|
#include <spdlog.h>
|
|
|
|
#include <TStyle.h>
|
|
#include <TH2D.h>
|
|
#include <TLatex.h>
|
|
#include <TCanvas.h>
|
|
#include <TROOT.h>
|
|
|
|
//Do the actuall background fit
|
|
int backgroundfit(fcnc::options opts,
|
|
bool fitReference, bool LowMassFit, bool HighMassFit, bool fitKpi,
|
|
bool Use2DAngularBins, basic_params params){
|
|
//params now only used to tag nBins in the names
|
|
|
|
//Technically, this should be simFit between Run 1 and 2, but since we need it only for the toys atm, no need for it
|
|
|
|
gROOT->SetBatch(kTRUE);
|
|
gROOT->SetStyle("Plain");
|
|
set_gStyle();
|
|
|
|
//Open texFile
|
|
std::ofstream myFile;
|
|
open_Latex_noteFile(latex_bkgFit(), myFile);
|
|
|
|
spdlog::info("[FIT]\t\tFit only angular and m(Kpi) background");
|
|
|
|
|
|
//Used to check whether the background is "correlated" between each other
|
|
//TODO: not needed atm, maybe fix later
|
|
/* 1D angular bins
|
|
1: ctl < -0.5
|
|
2: -0.5 < ctl < 0.0
|
|
3: 0.0 < ctl < 0.5
|
|
4: 0.5 < ctl
|
|
5: ctk < -0.5
|
|
6: -0.5 < ctk < 0.0
|
|
7: 0.0 < ctk < 0.5
|
|
8: 0.5 < ctk
|
|
*/
|
|
/* 2D angular bins
|
|
1: ctl < 0.0 && ctk < 0.0
|
|
2: ctl < 0.0 && ctk > 0.0
|
|
3: ctl > 0.0 && ctk < 0.0
|
|
4: ctl > 0.0 && ctk > 0.0
|
|
*/
|
|
|
|
double HighBpeakCut = fitReference ? B_MASS_HIGH_BKG_REF : B_MASS_HIGH_BKG;
|
|
double LowBpeakCut = fitReference ? B_MASS_LOW_BKG_REF : B_MASS_LOW_BKG;
|
|
|
|
assert(!(HighMassFit && LowMassFit));
|
|
|
|
opts.fit_full_angular_bkg = true;
|
|
|
|
opts.only_angles = !(HighMassFit || LowMassFit); //Fit mass only if one sideband is selected
|
|
opts.only_Bmass = false;
|
|
opts.only_mkpi = false;
|
|
|
|
opts.swave = false;
|
|
|
|
opts.bkg_order_costhetak = 5;
|
|
opts.shift_lh = false; //keep it, it was there before
|
|
opts.weighted_fit = true;
|
|
opts.squared_hesse = true;
|
|
opts.minos_errors = false;
|
|
opts.asymptotic = false;
|
|
|
|
opts.flat_bkg = false;
|
|
|
|
opts.fit_mkpi = false; //set to true only later
|
|
opts.use_mkpi = false;
|
|
opts.simple_mkpi = false; //S-wave model
|
|
opts.isobar = false; //S-wave model
|
|
|
|
//Plotting options
|
|
opts.plot_chi2 = false;
|
|
opts.plots_m_bins = 20;
|
|
opts.plots_mkpi_bins = 20;
|
|
|
|
//load events from data tuple
|
|
std::vector<std::vector<fcnc::event>>events;
|
|
std::vector<int> run_idx;
|
|
|
|
if (opts.run == 1 || opts.run == 12){
|
|
std::vector<fcnc::event> tmp = fcnc::load_events(get_theFCNCpath(0,1), "Events", -1);
|
|
if (!fitReference) events.push_back(fcnc::filterResonances(tmp));
|
|
else events.push_back(tmp);
|
|
run_idx.push_back(1);
|
|
}
|
|
if (opts.run == 2 || opts.run == 12){
|
|
std::vector<fcnc::event> tmp = fcnc::load_events(get_theFCNCpath(0,2), "Events", -1);
|
|
if (!fitReference) events.push_back(fcnc::filterResonances(tmp));
|
|
else events.push_back(tmp);
|
|
run_idx.push_back(2);
|
|
}
|
|
|
|
std::vector<int> fitresults;
|
|
|
|
//determine number of bins:
|
|
const UInt_t nBins = opts.TheQ2binsmin.size();
|
|
|
|
//current fitter, plotter, parameteres and pdfs:
|
|
fcnc::fitter f(&opts);
|
|
fcnc::folder fldr(&opts);
|
|
fcnc::bu2kstarmumu_plotter thePlotter(&opts);
|
|
|
|
fcnc::bu2kstarmumu_parameters * theParams[nBins];
|
|
fcnc::bu2kstarmumu_pdf * theProb[nBins];
|
|
std::vector<fcnc::event> * theEvents[nBins];
|
|
|
|
|
|
for(UInt_t b = 0; b < nBins; b++){
|
|
|
|
theParams[b] = new fcnc::bu2kstarmumu_parameters(&opts);
|
|
theProb[b] = new fcnc::bu2kstarmumu_pdf(&opts, theParams[b]);
|
|
theEvents[b] = new std::vector<fcnc::event>();
|
|
|
|
//Init parameters
|
|
theParams[b]->f_sig.init_fixed(0.0);
|
|
theParams[b]->m_b.init(PDGMASS_B, HighMassFit ? HighBpeakCut : B_MASS_LOW, LowMassFit ? LowBpeakCut : B_MASS_HIGH, 0.0);
|
|
//The rest of the mass parameters can be left to default values
|
|
//They are defined in bu2kstamumu_parameters
|
|
|
|
//Init the bkg shape
|
|
theParams[b]->init_angular_background_parameters(fitReference,0.1);
|
|
|
|
//Init the mass bkg shape
|
|
theParams[b]->init_mass_background_parameters(nBins,b,true);
|
|
//theParams[b]->cbkgctk3.init_fixed(-2.5);
|
|
|
|
//Select events
|
|
for_indexed(auto evts: events){
|
|
//update weights according to sub-set for all events
|
|
opts.run = run_idx.at(i);
|
|
opts.update_efficiencies = true;
|
|
|
|
theProb[b]->load_coeffs_eff_phsp_4d();
|
|
theProb[b]->update_cached_normalization(theParams[b]);
|
|
theProb[b]->update_cached_efficiencies(theParams[b], &evts);
|
|
opts.update_angle_ranges(); //Update angles to get rid of events that cannot be folded
|
|
//select events
|
|
spdlog::debug("Loop over {0:d} events and select the suitable ones", evts.size());
|
|
for(auto meas: evts){
|
|
|
|
if(meas.q2 < opts.TheQ2binsmin.at(b) || meas.q2 > opts.TheQ2binsmax.at(b)) continue;
|
|
if(meas.m < opts.m_low || meas.m > opts.m_high) continue;
|
|
|
|
if(LowMassFit && meas.m > LowBpeakCut) continue;
|
|
else if(HighMassFit && meas.m < HighBpeakCut) continue;
|
|
else if(meas.m > LowBpeakCut && meas.m < HighBpeakCut) continue;
|
|
|
|
if(meas.mkpi < opts.mkpi_min || meas.mkpi > opts.mkpi_max) continue;
|
|
|
|
if(params.bin > 1){
|
|
bool keep_event = true;
|
|
if(Use2DAngularBins){
|
|
switch(params.bin){
|
|
case 2:
|
|
if(meas.costhetal > 0.0 || meas.costhetak > 0.0) keep_event = false;
|
|
break;
|
|
case 3:
|
|
if(meas.costhetal > 0.0 || meas.costhetak < 0.0) keep_event = false;
|
|
break;
|
|
case 4:
|
|
if(meas.costhetal < 0.0 || meas.costhetak > 0.0) keep_event = false;
|
|
break;
|
|
case 5:
|
|
if(meas.costhetal < 0.0 || meas.costhetak < 0.0) keep_event = false;
|
|
break;
|
|
}
|
|
}
|
|
else{ //1D angular bins
|
|
switch(params.bin){
|
|
case 2:
|
|
if(meas.costhetal > -0.5) keep_event = false;
|
|
break;
|
|
case 3:
|
|
if(meas.costhetal < -0.5 || meas.costhetal > 0.0) keep_event = false;;
|
|
break;
|
|
case 4:
|
|
if(meas.costhetal < 0.0 || meas.costhetal > 0.5) keep_event = false;;
|
|
break;
|
|
case 5:
|
|
if(meas.costhetal > 0.5) keep_event = false;;
|
|
break;
|
|
case 6:
|
|
if(meas.costhetak > -0.5) keep_event = false;;
|
|
break;
|
|
case 7:
|
|
if(meas.costhetak < -0.5 || meas.costhetak > 0.0) keep_event = false;;
|
|
break;
|
|
case 8:
|
|
if(meas.costhetak < 0.0 || meas.costhetak > 0.5) keep_event = false;;
|
|
break;
|
|
case 9:
|
|
if(meas.costhetak > 0.5) keep_event = false;;
|
|
break;
|
|
}
|
|
}
|
|
if(!keep_event) continue;
|
|
}
|
|
|
|
if(!filterFldFour(&meas, &opts)) continue;
|
|
fldr.fold(&meas);
|
|
|
|
//only one combined event vector
|
|
theEvents[b]->push_back(meas);
|
|
}
|
|
spdlog::debug("Selected {0:d} events.", theEvents[b]->size());
|
|
}
|
|
spdlog::info("[BIN {0:d}]\tDone!",b);
|
|
}//end loop over bins
|
|
|
|
//do not update cached efficiencies anyomre, to keep individual ones for four sub-sets
|
|
opts.update_efficiencies = false;
|
|
|
|
//create 2D correlation plots for all angles (3) and all bins (8): 3! * 8 = 24
|
|
const unsigned int nANGLES = 3;
|
|
|
|
double hmin[nANGLES] = {CTL_MIN, CTK_MIN, PHI_MIN};
|
|
double hmax[nANGLES] = {CTL_MAX, CTK_MAX, PHI_MAX};
|
|
double corrfactor[nBins][nANGLES][nANGLES];
|
|
const int nCorrBins = 10;
|
|
for(UInt_t b = 0; b < nBins; b++){
|
|
spdlog::info("[START]\tStart the background 2D correlation plotting for bin #{0:d}", b);
|
|
for(UInt_t a = 0; a < nANGLES - 1; a++){
|
|
for(UInt_t aa = a + 1; aa < nANGLES; aa++){
|
|
std::string mainName = "bckgnd_correl_"+ANGLES[a]+"_"+ANGLES[aa]+"_q2bin"+std::to_string(b);
|
|
TCanvas * cAngCorr = new TCanvas(("c"+mainName).c_str(),
|
|
("c"+mainName).c_str(), 1400, 1200);
|
|
cAngCorr->cd()->SetMargin(0.1,0.125,0.125,0.125);
|
|
cAngCorr->cd();
|
|
TH2D * h = new TH2D((mainName).c_str(),
|
|
(mainName+";"+latex_angles[a]+";"+latex_angles[aa]).c_str(),
|
|
nCorrBins, hmin[a], hmax[a], nCorrBins, hmin[aa], hmax[aa]);
|
|
|
|
for(UInt_t e = 0; e < theEvents[b]->size(); e++){
|
|
fcnc::event meas = theEvents[b]->at(e);
|
|
double x=0.0, y=0.0;
|
|
switch(a){ //TODO: make a function in helpers
|
|
case 0:
|
|
x = meas.costhetal;
|
|
break;
|
|
case 1:
|
|
x = meas.costhetak;
|
|
break;
|
|
}
|
|
switch(aa){
|
|
case 1:
|
|
y = meas.costhetak;
|
|
break;
|
|
case 2:
|
|
y = meas.phi;
|
|
break;
|
|
}
|
|
h->Fill(x, y);
|
|
}
|
|
h->GetZaxis()->SetRangeUser(0, fitReference ? 25 : 5);
|
|
h->GetZaxis()->SetTitle("Number of entries");
|
|
|
|
h->GetXaxis()->SetTitleSize(0.05);
|
|
h->GetXaxis()->SetLabelSize(0.05);
|
|
h->GetXaxis()->SetTitleOffset(0.95);
|
|
|
|
h->GetYaxis()->SetTitleSize(0.05);
|
|
h->GetYaxis()->SetLabelSize(0.05);
|
|
h->GetYaxis()->SetTitleOffset(0.75);
|
|
|
|
h->GetZaxis()->SetTitleSize(0.05);
|
|
h->GetZaxis()->SetLabelSize(0.05);
|
|
h->GetZaxis()->SetTitleOffset(0.75);
|
|
|
|
h->SetTitle("");
|
|
h->Draw("COLZ");
|
|
|
|
corrfactor[b][a][aa] = h->GetCorrelationFactor();
|
|
|
|
TLatex * leg = getPrettyTex(0.06,13);
|
|
leg->SetTextColor(kBlack);
|
|
std::ostringstream sCorrout; //TODO: move the path
|
|
sCorrout << std::fixed << std::setprecision(2) << "corr(" << latex_angles[a] << ", " << latex_angles[aa] <<") = " << corrfactor[b][a][aa]*100. << "\%";
|
|
leg->DrawLatex(0.22,0.98, sCorrout.str().c_str());
|
|
leg->SetTextSize(0.04);
|
|
leg->DrawLatex(0.25,0.92, ("Events: "+std::to_string((int) h->GetEntries())).c_str());
|
|
cAngCorr->Print(get_bkgCorrPlot_path(ANGLES[a],ANGLES[aa],b,nBins,fitReference, LowMassFit, HighMassFit, fitKpi, params).c_str(), "eps");
|
|
|
|
}
|
|
}
|
|
|
|
//Save the correlations s
|
|
myFile << "\\begin{tabular}{r|ccc}\\hline" << std::endl;
|
|
myFile << std::fixed << std::setprecision(2) << "[" << opts.TheQ2binsmin.at(b) << ", " << opts.TheQ2binsmax.at(b) << "]";
|
|
for(UInt_t a = 0; a < nANGLES; a++) myFile << "\t&" << latex_2angles[a];
|
|
myFile << "\\\\" << std::endl;
|
|
myFile << "\\hline\\hline" << std::endl;
|
|
for(UInt_t a = 0; a < nANGLES; a++){
|
|
myFile << latex_2angles[a];
|
|
for(UInt_t aa = 0; aa < nANGLES; aa++){
|
|
myFile << "\t&";
|
|
if(aa > a) myFile << std::setprecision(3) << std::fixed << corrfactor[b][a][aa];
|
|
else if(aa == a) myFile << "1.00";
|
|
else if(aa < a) myFile << " ";
|
|
}
|
|
myFile << "\\\\" << std::endl;
|
|
}
|
|
myFile << "\\hline" << std::endl;
|
|
myFile << "\\end{tabular}"<< std::endl;
|
|
myFile << std::endl;
|
|
|
|
}
|
|
|
|
//FIT ANGULAR BACKGROUND + B mass
|
|
opts.update_angle_ranges(); //Just in case
|
|
//fit all bins:
|
|
for(UInt_t b = 0; b < nBins; b++){
|
|
|
|
spdlog::info("[START]\tStart the fit for bin #{0:d}", b);
|
|
|
|
//fit the events:
|
|
int fitresult = f.fit(theProb[b], theParams[b], theEvents[b]);
|
|
fitresults.push_back(fitresult);
|
|
|
|
spdlog::info("[BIN{0:d}]:\tFitresult: {1:d}", b, fitresult);
|
|
|
|
//plot pdf with the data points:
|
|
opts.plot_label = "LHCb data";
|
|
opts.q2_label = q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b));
|
|
|
|
if(opts.write_eps){
|
|
std::string label = get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, false, params);
|
|
spdlog::info("[PLOT]\t" + label);
|
|
thePlotter.plot_data(theProb[b], theParams[b], theEvents[b], get_bkgFitPlot_path(), label, false);
|
|
}
|
|
//print all parameters
|
|
std::string fitResultTxt = get_bkgFitResult_path()+ "fitresult_" + get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, false, params);
|
|
spdlog::debug("Saving into "+fitResultTxt);
|
|
print_all_parameters(nBins, theParams, 2, fitResultTxt);
|
|
}
|
|
|
|
//print all fitresults
|
|
print_fit_results(nBins, fitresults);
|
|
|
|
//Save results to root file
|
|
std::string results_file = final_result_name_bkg(nBins, fitReference, LowMassFit, HighMassFit, false, params);
|
|
save_results(results_file, nBins, params.Run, fitresults, theParams, &opts);
|
|
|
|
//FIT M(KPI) BACKGROUND
|
|
if (!fitKpi){ //first check if you really want to fit M(KPI) :)
|
|
//Close Latex file
|
|
myFile.close();
|
|
return 0;
|
|
}
|
|
|
|
//Reset the options
|
|
opts.only_angles = false;
|
|
opts.only_mkpi = true;
|
|
opts.fit_mkpi = true;
|
|
|
|
|
|
//fit all bins:
|
|
spdlog::info("[BKGFIT]\tFit the Kpi mass");
|
|
for(UInt_t b = 0; b < nBins; b++){
|
|
|
|
theParams[b]->use_default_bkg();
|
|
//null the lambda(s) and taus
|
|
theParams[b]->m_lambda.init_fixed(0.0);
|
|
theParams[b]->m_lambda_2.init_fixed(0.0);
|
|
theParams[b]->m_tau.init_fixed(0.0);
|
|
theParams[b]->m_tau_2.init_fixed(0.0);
|
|
//Init the floating parameters
|
|
theParams[b]->init_kpi_background_parameters(fitReference,0.01);
|
|
|
|
spdlog::info("[START]\tStart the fit for bin #{0:d}", b);
|
|
|
|
//fit the events:
|
|
fitresults.push_back(f.fit(theProb[b], theParams[b], theEvents[b]));
|
|
spdlog::info("[BIN{0:d} ]:\tFitresult: {1:d}",b, fitresults.at(b));
|
|
|
|
//plot pdf with the data points:
|
|
opts.q2_label = q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b));
|
|
|
|
if(opts.write_eps){
|
|
std::string label = get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, false, params);
|
|
spdlog::info("[PLOT]\t" + label);
|
|
thePlotter.plot_data(theProb[b], theParams[b], theEvents[b], get_bkgFitPlot_path(), label, false);
|
|
}
|
|
//Print all parameters, but don't save
|
|
print_all_parameters(nBins, theParams, 2, "");
|
|
|
|
//print all parameters to txt file
|
|
std::string fitResultTxt = get_bkgFitResult_path()+ "fitresult_" + get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, true, params);
|
|
spdlog::debug("Saving into "+fitResultTxt);
|
|
print_all_parameters(nBins, theParams, 2, fitResultTxt);
|
|
}
|
|
spdlog::info("[BKGFIT]\tDone with Kpi fit.");
|
|
//Save results to root file
|
|
results_file = final_result_name_bkg(nBins, fitReference, LowMassFit, HighMassFit, true, params);
|
|
save_results(results_file, nBins, params.Run, fitresults, theParams, &opts);
|
|
|
|
//Close Latex file
|
|
myFile.close();
|
|
|
|
spdlog::info("[BKGFIT]\tFinished.");
|
|
return 0;
|
|
}
|