Angular analysis of B+->K*+(K+pi0)mumu
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.
 
 
 
 

1217 lines
44 KiB

//Renata Kopecna
#include <helpers.hh>
#include <fstream> //Needed to remove/copy files
#include <bu2kstarmumu_parameters.hh>
#include <sstream>
#include <iostream>
#include <options.hh>
#include <parameters.hh>
#include <constants.hh>
#include <spdlog.h>
#include <fmt/ostr.h>
#include <TFile.h>
#include <TTree.h>
#include <paths.hh>
#include <numeric> //includes accumulate
#include <parse.hh>
#include <event.hh>
#include <spdlog.h>
//----------------------//
// Print utils //
//----------------------//
std::string boolToString(bool isTrue){
if (isTrue) return "TRUE";
else return "FALSE";
}
void reset_spdlog(){
spdlog::set_pattern("[%^%l%$]\t %v");
}
void set_spdlog_level(int verboseLvl){
switch(verboseLvl) {
case 0:
spdlog::set_level(spdlog::level::trace);
break;
case 1:
spdlog::set_level(spdlog::level::debug);
break;
case 2:
spdlog::set_level(spdlog::level::info);
break;
case 3:
spdlog::set_level(spdlog::level::warn);
break;
case 4:
spdlog::set_level(spdlog::level::err);
break;
case 5:
spdlog::set_level(spdlog::level::critical);
break;
}
return;
}
bool spdlog_trace(){
return (spdlog::default_logger_raw()->level()<=spdlog::level::trace);
}
bool spdlog_debug(){
return (spdlog::default_logger_raw()->level()<=spdlog::level::debug);
}
bool spdlog_info(){
return (spdlog::default_logger_raw()->level()<=spdlog::level::info);
}
bool spdlog_warn(){
return (spdlog::default_logger_raw()->level()<=spdlog::level::warn);
}
bool spdlog_error(){
return (spdlog::default_logger_raw()->level()<=spdlog::level::err);
}
std::string get_sample_from_jobID(int job_id){
if(job_id == 0) return "DATA";
else if(job_id == 1) return "SIGNAL MC";
else if(job_id == 2) return "REFERENCE MC ";
else if(job_id == 3) return "PHSP MC ";
else if(job_id == 4) return "GenLevel PHSP MC";
else if(job_id == 5) return "GenLevel MC";
else {
spdlog::error("Invalid index for conversion function given: {0:d}", job_id);
assert(0);
}
}
std::string format_double(double value, unsigned int digits){
std::stringstream out;
out << std::fixed << std::setprecision(digits) << value;
return out.str();
};
std::string format_value(double value, double error, unsigned int digits){
//format value such that the relevant number of digits is given back
//determine first "digits" significant places of error
if (error == 0.0){
std::stringstream out; //to_string(value) returns something else than this.... I hate c++
out << value;
return out.str();
}
else{
int first_significant = floor(log10(error));
if (first_significant > 0) first_significant = 0;
//ln(e^x)=x log10(c*10^x)=x+log10(c) with log10(c) < 1
return format_double(value,fabs(first_significant)+digits-1);
}
};
std::string format_error(double error, unsigned int digits){
return (format_value(error,error,digits));
};
//----------------------//
// Year utils //
//----------------------//
//generate vector with years for every run option
//notation for usage of runs:
//1 : Run 1
//2 : Run 2
//12: Run 1+2
//21: 'Run 2.1' = 2015+2016
//22: 'Run 2.2' = 2017+2018
std::vector<int> get_years(int Run, bool MCsig, bool MCref){
std::vector<int>years;
if(Run == 1 || Run == 12){
years.push_back(2011);
years.push_back(2012);
}
if(Run== 2 || Run == 12 || Run== 21){
if (!MCsig) years.push_back(2015); //No MC for 2015
years.push_back(2016);
}
if (!MCref){ //No RefMC for 2017+2018
if(Run == 2 || Run == 12 || Run == 22){
years.push_back(2017);
years.push_back(2018);
}
}
return years;
}
//Check if year is a run year
void check_year(int year){
std::set<int> yearSet = {2011,2012,2015,2016,2017,2018};
//Check if year is in a set, if not, throw exception
assert(yearSet.find(year)!= yearSet.end());
return;
}
int MC_dataset(bool Reference, bool PHSP){
if (PHSP) return 3; //PHSP
else if (Reference) return 2; //Ref MC
else return 1; //Sig MC
}
int get_yearFromRun(int year){
if (year == 2011 || year == 2012) return 1;
if (year == 2015 || year == 2016 || year == 2017 || year == 2018) return 2;
spdlog::error("Year not recognized!");
assert(0);
}
//--------------------------------------//
// General helpers //
//--------------------------------------//
//Copy file
int copyFile(std::string from, std::string to){
std::ifstream src(from);
std::ofstream dst(to);
dst << src.rdbuf();
return 0;
}
//Check if file exists
//https://stackoverflow.com/questions/12774207/fastest-way-to-check-if-a-file-exist-using-standard-c-c11-c
bool existsTest (const std::string& name) {
struct stat buffer;
return (stat (name.c_str(), &buffer) == 0);
}
//https://stackoverflow.com/questions/50960492/creating-folders-in-c
//Create parent folders if needed
void makeFolder (const std::string& name) {
std::string parentfolder = name.substr(0, name.find_last_of("/\\"));
if(!existsTest(parentfolder))makeFolder(parentfolder);
spdlog::info("Creating folder '"+name+"'");
mkdir(name.c_str(), 0755);
return;
}
//Convert vector into number-space-number... string
std::string convert_vector_to_string(std::vector<int> myVector){
std::stringstream ss;
copy(myVector.begin(), myVector.end(), std::ostream_iterator<int>(ss, " "));
std::string s = ss.str();
return s.substr(0, s.length()-1); // get rid of the trailing space
}
std::string convert_vector_to_string(std::vector<double> myVector){
std::stringstream ss;
copy(myVector.begin(), myVector.end(), std::ostream_iterator<double>(ss, " "));
std::string s = ss.str();
return s.substr(0, s.length()-1); // get rid of the trailing space
}
std::string convert_vector_to_string(std::vector<std::string> myVector){
std::stringstream ss;
copy(myVector.begin(), myVector.end(), std::ostream_iterator<std::string>(ss, " "));
std::string s = ss.str();
return s.substr(0, s.length()-1); // get rid of the trailing space
}
std::vector<double> merge_two_vecs(std::vector<double> one, std::vector<double> two){
std::vector<double> merged_vec;
merged_vec.insert(merged_vec.end(), one.begin(), one.end());
merged_vec.insert(merged_vec.end(), two.begin(), two.end());
return merged_vec;
}
std::vector<int> merge_two_vecs(std::vector<int> one, std::vector<int> two){
std::vector<int> merged_vec;
merged_vec.insert(merged_vec.end(), one.begin(), one.end());
merged_vec.insert(merged_vec.end(), two.begin(), two.end());
return merged_vec;
}
std::vector<std::string> merge_two_vecs(std::vector<std::string> one, std::vector<std::string> two){ //TODO: I bet there is a way to avoid overloading
std::vector<std::string> merged_vec;
merged_vec.insert(merged_vec.end(), one.begin(), one.end());
merged_vec.insert(merged_vec.end(), two.begin(), two.end());
return merged_vec;
}
bool replace(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = str.find(from);
if(start_pos == std::string::npos)
return false;
while ( (start_pos = str.find(from,start_pos)) != std::string::npos){
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
}
return true;
}
//Sum a vector of ints
int sum_vector(std::vector<int> vec){
return std::accumulate(vec.begin(), vec.end(), 0);
}
//Sum a vector of doubles
double sum_vector(std::vector<double> vec){
return std::accumulate(vec.begin(), vec.end(), 0.0);
}
//Return the center of a bin
double bin_center(double low, double high){
return (high+low)/2.0;
}
//Return the center of a q2 bin
double bin_center_q2(fcnc::options opts, int b){
return bin_center(opts.TheQ2binsmin.at(b),opts.TheQ2binsmax.at(b));
}
double bin_center_q2(fcnc::options *opts, int b){
return bin_center(opts->TheQ2binsmin.at(b),opts->TheQ2binsmax.at(b));
}
double bin_center_q2(std::vector<double> q2min, std::vector<double> q2max , int b){
return bin_center(q2min.at(b),q2max.at(b));
}
//Return half of the width (useful for errors)
double bin_halfWidth(double low, double high){
return (high-low)/2.0;
}
double bin_halfWidth_q2(std::vector<double> q2min, std::vector<double> q2max, int b){
return (q2max.at(b)-q2min.at(b))/2.0;
}
double bin_halfWidth_q2(fcnc::options opts, int b){
return (opts.TheQ2binsmax.at(b)-opts.TheQ2binsmin.at(b))/2.0;
}
double bin_halfWidth_q2(fcnc::options *opts, int b){
return (opts->TheQ2binsmax.at(b)-opts->TheQ2binsmin.at(b))/2.0;
}
//Check if the angles are in the correct range given by options
bool isEvtInAngleRange(fcnc::event *evt, fcnc::options *opts){
if (evt->costhetal > opts->ctl_max) return false;
if (evt->costhetal < opts->ctl_min) return false;
if (evt->costhetak > opts->ctk_max) return false;
if (evt->costhetak < opts->ctk_min) return false;
if (evt->phi > opts->phi_max) return false;
if (evt->phi < opts->phi_min) return false;
if (evt->q2 > opts->TheQ2binsmax.back()) return false;
if (evt->q2 < opts->TheQ2binsmin.front()) return false;
return true;
}
//Check if the angles are in the correct range given by default
bool isEvtInAngleRange(fcnc::event *evt){
if (evt->costhetal > CTL_MAX){
spdlog::trace("ctl of event:\t{0:f}",evt->costhetal);
return false;
}
if (evt->costhetal < CTL_MIN){
spdlog::trace("ctl of event:\t{0:f}",evt->costhetal);
return false;
}
if (evt->costhetak > CTK_MAX) {
spdlog::trace("ctk of event:\t{0:f}",evt->costhetak);
return false;
}
if (evt->costhetak < CTK_MIN) {
spdlog::trace("ctk of event:\t{0:f}",evt->costhetak);
return false;
}
if (evt->phi > PHI_MAX){
spdlog::trace("phi of event:\t{0:f}",evt->phi);
return false;
}
if (evt->phi < PHI_MIN) {
spdlog::trace("phi of event:\t{0:f}",evt->phi);
return false;
}
if (evt->q2 < Q2_MIN_RANGE) return false;
if (evt->q2 > Q2_MAX_RANGE) return false;
return true;
}
//For now filter out events that are dumb dumb for folding four
bool filterFldFour(fcnc::event *evt, fcnc::options *opts){
if (opts->folding==4){
//TODO: this is idiotic and will cause trouble if one cuts on ctl. Unfortunatelly, otherwise it cuts the folded parameters too, which is not very beneficial
// SO this if (!isEvtInAngleRange(&evt,&opts)) continue; is not possible
if (evt->costhetak > opts->ctk_max) return false;
if (evt->costhetak < opts->ctk_min) return false;
}
return true;
}
//Check if value is in a vector
bool isInVec(int key, std::vector<int>vec){
return (std::find(vec.begin(), vec.end(), key)!= vec.end());
}
bool isInVec(double key, std::vector<double>vec){
return (std::find(vec.begin(), vec.end(), key)!= vec.end());
}
bool isInVec(std::string key, std::vector<std::string>vec){
return (std::find(vec.begin(), vec.end(), key)!= vec.end());
}
//--------------------------------------//
// Helpers for converting the tuples //
//--------------------------------------//
//Returns the correct tree name as Data/MC and genLvl have different tree names
std::string get_inputTree_name(int job_id){
if(job_id == 0) return "DecayTree";
else if(job_id == 1) return "DecayTreeTruthMatched";
else if(job_id == 2) return "DecayTreeTruthMatched";
else if(job_id == 3) return "DecayTreeTruthMatched";
else if(job_id == 4) return "DecayTree";
else if(job_id == 5) return "DecayTree";
else {
spdlog::error("Invalid index for conversion function given: {0:d}", job_id);
assert(0);
}
}
//--------------------------------------//
// Helpers for angular corrections //
//--------------------------------------//
TF1 *fitStraightLine(TH1D* hist, std::string lineName, double lowEdge, double highEdge){
//Define the fit line
TF1 *fitLine= new TF1(lineName.c_str(), "[0]*x+[1]", lowEdge, highEdge);
fitLine->SetParameters(0.0, 1.0);
fitLine->SetParLimits(0,-0.5,0.5);
fitLine->SetParLimits(1,0.5,1.5);
fitLine->SetParNames("a","b");
std::string fitOption = spdlog_debug() ? "R" : "RQ"; //C turns off chi2 calculation, faster, Q=quiet
hist->Fit(lineName.c_str(), fitOption.c_str());
spdlog::debug("Fitted value is:\t{0:f}+-{1:f}",fitLine->GetParameter(0), fitLine->GetParError(0));
return fitLine;
}
//--------------------------------------//
// Helpers for bu2kstarmumu_pdf //
//--------------------------------------//
const std::vector<std::vector<std::string>> get_angObser_withTeX_vec(){
return {
{"1s","#xi_{1}^{s}"},
{"1c","#xi_{1}^{c}"},
{"2s","#xi_{2}^{s}"},
{"2c","#xi_{2}^{c}"},
{"3","#xi_{3}"},
{"4", "#xi_{4}"},
{"5","#xi_{5}"},
{"6s","#xi_{6}^{s}"},
{"6c","#xi_{6}^{c}"},
{"7","#xi_{7}"},
{"8","#xi_{8}"},
{"9","#xi_{9}"}
};
}
std::vector<std::string> get_angObser_vec(){
std::vector<std::string> tmp;
for (auto obs: get_angObser_withTeX_vec()){
tmp.push_back(obs[0]);
}
return tmp;
}
std::vector<std::string> get_angObserTeX_vec(){
std::vector<std::string> tmp;
for (auto obs: get_angObser_withTeX_vec()){
tmp.push_back(obs[1]);
}
return tmp;
}
//--------------------------------------//
// Helpers for time measuring //
//--------------------------------------//
void runTime::start(){
sw->Reset();
sw->Start();
return;
}
void runTime::stop(time_t startTime){
sw->Stop();
real_times.push_back(sw->RealTime());
cpu_times.push_back(sw->CpuTime());
cpp_times.push_back(Double_t(time(0) - startTime));
return;
}
void runTime::print(unsigned int nBins){
spdlog::info("");
spdlog::info("==========================================");
spdlog::info("|| TIME OF FIT ||");
spdlog::info("==========================================");
spdlog::info("|| BIN\t\tCPU time[s]\treal time[s]\tC++ time[s]\t||");
for(unsigned int b = 0; b < nBins; b++){
Int_t CpuHours = Int_t(cpu_times.at(b) / 3600);
cpu_times.at(b) -= CpuHours * 3600;
Int_t CpuMinutes = Int_t(cpu_times.at(b) / 60);
cpu_times.at(b) -= CpuMinutes * 60;
Int_t CpuSeconds = Int_t(cpu_times.at(b));
Int_t RealHours = Int_t(real_times.at(b) / 3600);
real_times.at(b) -= RealHours * 3600;
Int_t RealMinutes = Int_t(real_times.at(b) / 60);
real_times.at(b) -= RealMinutes * 60;
Int_t RealSeconds = Int_t(real_times.at(b));
Int_t CppHours = Int_t(cpp_times.at(b) / 3600);
cpp_times.at(b) -= CppHours * 3600;
Int_t CppMinutes = Int_t(cpp_times.at(b) / 60);
cpp_times.at(b) -= CppMinutes * 60;
Int_t CppSeconds = Int_t(cpp_times.at(b));
spdlog::info("|| {0:d}\t\t{1:d}:{2:02d}:{3:02d}\t\t{4:d}:{5:02d}:{6:02d}\t\t{7:d}:{8:02d}:{9:02d} \t||", b, CpuHours, CpuMinutes, CpuSeconds, RealHours, RealMinutes, RealSeconds, CppHours, CppMinutes, CppSeconds);
}
}
//--------------------------------------//
// Helpers for fit scripts //
//--------------------------------------//
std::vector<std::string> param_string_pPrimes(bool fitFL){
std::vector<std::string> params;
if(fitFL) params.push_back("Fl");
else params.push_back("S1s");
params.push_back("P1");
params.push_back("P4");
params.push_back("P5");
params.push_back("P2");
params.push_back("P6");
params.push_back("P8");
params.push_back("P3");
return params;
}
std::vector<std::string> param_string_pPrimes(bool fitFL, int folding){
std::vector<std::string> params;
if(fitFL) params.push_back("Fl");
else params.push_back("S1s");
if(folding == 0){
params.push_back("P2");
params.push_back("P3");
return params;
}
else if(folding == 1)params.push_back("P4"); //could be a switch, but meh
else if(folding == 2)params.push_back("P5");
else if(folding == 3)params.push_back("P6");
else if(folding == 4)params.push_back("P8");
return params;
}
std::vector<std::string> param_string_s(bool fitFL, bool fitAFB){
std::vector<std::string> params;
if(fitFL) params.push_back("Fl");
else params.push_back("S1s");
params.push_back("S3");
params.push_back("S4");
params.push_back("S5");
if (fitAFB) params.push_back("Afb");
else params.push_back("S6s");
params.push_back("S7");
params.push_back("S8");
params.push_back("S9");
return params;
}
std::vector<std::string> param_string_s(bool fitFL, bool fitAFB, int folding){
std::vector<std::string> params;
if(fitFL) params.push_back("Fl");
else params.push_back("S1s");
params.push_back("S3");
if(folding == 0){
if(fitAFB) params.push_back("Afb");
else params.push_back("S6s");
params.push_back("S9");
return params;
}
else if(folding == 1)params.push_back("S4");
else if(folding == 2)params.push_back("S5");
else if(folding == 3)params.push_back("S7");
else if(folding == 4)params.push_back("S8");
return params;
}
std::vector<std::string> param_string_sWave(){
std::vector<std::string> params;
params.push_back("FS");
params.push_back("SS1");
params.push_back("SS2");
params.push_back("SS3");
params.push_back("SS4");
params.push_back("SS5");
return params;
}
std::vector<std::string> param_string_sWave(int folding){
std::vector<std::string> params;
params.push_back("FS");
if(folding == 1) params.push_back("SS2");
if(folding == 2) params.push_back("SS3");
if(folding > 2) params.push_back("SS4");
if(folding < 4) params.push_back("SS1");
return params;
}
//TODO: merge with parNamesWithTex
std::vector<std::string> param_string_bkg(){
std::vector<std::string> str;
for (auto ang: ANGLES){
for (int i = 1; i < 5; i++){
str.push_back("cbkg"+ang+std::to_string(i));
}
}
return str;
}
std::vector<std::string> param_string_bkg_mkpi(){
std::vector<std::string> str;
for (int i = 1; i < 2; i++){
str.push_back("cbkgmkpi"+std::to_string(i));
}
return str;
}
std::vector<std::string> param_string(fcnc::options opts, bool MC){
std::vector<std::string> params;
//This is suboptimal but I feel it is easier for the reader
if (opts.full_angular){
if(opts.fit_pprimes) params = param_string_pPrimes(opts.fit_fl);
else params = param_string_s(opts.fit_fl, opts.fit_afb);
if(opts.swave){
std::vector<std::string> sWave = param_string_sWave();
params.insert(params.end(), sWave.begin(), sWave.end());
}
if(!MC){
std::vector<std::string> bkg = PAR_BKG_STRING(-1,opts.bkg_order_costhetal,opts.bkg_order_costhetak); //Returns only varied parameters
params.insert(params.end(), bkg.begin(), bkg.end());
}
return params;
}
else{
if(opts.fit_pprimes) params = param_string_pPrimes(opts.fit_fl,opts.folding);
else params = param_string_s(opts.fit_fl, opts.fit_afb,opts.folding);
if(opts.swave){
std::vector<std::string> sWave = param_string_sWave(opts.folding);
params.insert(params.end(), sWave.begin(), sWave.end());
}
if(!MC){
std::vector<std::string> bkg = PAR_BKG_STRING(opts.folding,opts.bkg_order_costhetal,opts.bkg_order_costhetak);
params.insert(params.end(), bkg.begin(), bkg.end());
}
return params;
}
}
std::vector<std::string> params_string_mass(fcnc::options opts){
std::vector<std::string> params;
params.push_back("m_b");
if (!opts.twotailedcrystalball) params.push_back("m_res_1");
params.push_back("m_sigma_1");
if (!opts.twotailedcrystalball) params.push_back("m_sigma_2");
params.push_back("alpha_1");
params.push_back("alpha_2");
params.push_back("n_1");
params.push_back("n_2");
return params;
}
fcnc::parameter* par_with_correct_name(int pos, std::string parname, fcnc::parameters* theParams){
//pos is the position of the parameter I want to save
fcnc::parameter* par = theParams->get_parameter(pos);
//I am not sure, but from the code it seems the parameters should be at the same spot for all pdfs
//Therefore first check if the name on the spot is correct
if (par->get_name() == parname.c_str()) return par;
unsigned int paridx = 0;
while(paridx != theParams->nparameters()){
par = theParams->get_parameter(paridx);
if (par->get_name() == parname.c_str()) return par;
paridx++;
}
spdlog::warn("Parameter "+parname+" not found in PDF {0:d}. Continue with next PDF.");
return NULL;
}
double get_sigmaRatio_fromMC(basic_params params, int nBins, int bin, int pdf){
std::string sigma_name = "m_sigma_1"; //In case one needs m_sigma or m_sigma_2 or so
std::string fileName_sig = final_result_name_MC(params, nBins, false, false, true, false, false);
std::string fileName_ref = final_result_name_MC(params, 1, true, false, true, false, true);
return double(get_param_value_from_rootfile(fileName_sig,sigma_name,pdf,bin))/ double(get_param_value_from_rootfile(fileName_ref,sigma_name,pdf,0));
}
//--------------------------------------//
// Helpers for printing fit results //
//--------------------------------------//
void print_all_parameters(unsigned int nBins, fcnc::bu2kstarmumu_parameters *theParams[],
int spdlog_level, std::string savePath){
//Check whether the desired level >= current level
if (spdlog_level >= spdlog::default_logger_raw()->level()){
//If yes, print the parameters at info level
//Save current level of spdlog
spdlog::level::level_enum tmp_log_level = spdlog::default_logger_raw()->level();
//Set the level to info so it is printed for sure
spdlog::set_level(spdlog::level::info);
spdlog::info("");
spdlog::info("==========================================");
spdlog::info("|| PARAMETERS ||");
spdlog::info("==========================================");
for(unsigned int b = 0; b < nBins; b++){
spdlog::info("|| BIN {0:d}", b);
if(spdlog::default_logger_raw()->level()<=spdlog_level){
theParams[b]->print_parameters(false);
}
if (savePath != ""){
std::string saveBinPath = savePath + "_bin" + std::to_string(b) + ".txt";
theParams[b]->save_param_values(saveBinPath + "");
}
theParams[b]->print_parameters(false);
}
//Reset the level back where it was
spdlog::set_level(tmp_log_level);
}
else return;
}
void print_all_parameters(unsigned int nBins, std::vector<UInt_t> pdf_idx,
std::vector<fcnc::parameters*> theParams[],
int spdlog_level){
//Check whether the desired level >= current level
if (spdlog_level >= spdlog::default_logger_raw()->level()){
//If yes, print the parameters at info level
//Save current level of spdlog
spdlog::level::level_enum tmp_log_level = spdlog::default_logger_raw()->level();
//Set the level to trace so it is printed for sure
//Pritn_parameters needs trace
spdlog::set_level(spdlog::level::trace);
spdlog::info("");
spdlog::info("==========================================");
spdlog::info("|| PARAMETERS ||");
spdlog::info("==========================================");
for(unsigned int b = 0; b < nBins; b++){
for(UInt_t i = 0; i < pdf_idx.size(); i++){
spdlog::info("|| BIN {0:d}\tPDF {1:d}", b, pdf_idx.at(i));
theParams[b].at(i)->print_parameters(false);
}
}
//Reset the level back where it was
spdlog::set_level(tmp_log_level);
}
else return;
}
void tex_all_parameters(unsigned int nBins, std::vector<UInt_t> pdf_idx,
std::vector<fcnc::parameters*> theParams[]){
std::ofstream myFile;
open_Latex_noteFile(latex_params(), myFile); //open file with parameters
for(unsigned int b = 0; b < nBins; b++){
for(UInt_t i = 0; i < pdf_idx.size(); i++){
myFile << "\\captionof{table}{PDF " << i << " bin " << b<< "}" << std::endl;
theParams[b].at(i)->print_parameters(true);
}
}
return;
}
void tex_all_parameters(unsigned int nBins, int n_pdf, fcnc::bu2kstarmumu_parameters **theParams){
std::ofstream myFile;
open_Latex_noteFile(latex_params(), myFile); //open file with parameters
for(unsigned int b = 0; b < nBins; b++){
myFile << "\\captionof{table}{PDF " << n_pdf<< " bin " << b<< "}" << std::endl;
theParams[b]->print_parameters(true);
}
return;
}
void print_fit_results(unsigned int nBins,std::vector<Int_t> fitresults){
spdlog::info("==========================================");
spdlog::info("|| FIT RESULTS ||");
spdlog::info("==========================================");
if(spdlog_info()){
spdlog::info("|| BIN\t\tfit result ||");
for(UInt_t b = 0; b < nBins; b++){
spdlog::info("|| {0:d}\t\t{1:d}\t||", b, fitresults.at(b));
}
}
return;
}
void print_fit_results(unsigned int nBins, std::vector<UInt_t> pdf_idx, std::vector<Int_t> fitresults[], bool simFit){
spdlog::info("==========================================");
spdlog::info("|| FIT RESULTS ||");
spdlog::info("==========================================");
if(spdlog_info()){
spdlog::info("|| BIN\t\tPDF\t\tfit result ||");
for(UInt_t b = 0; b < nBins; b++){
if(!simFit){
for_indexed(auto idx: pdf_idx){
spdlog::info("|| {0:d}\t\t{1:d}\t\t{2:d} \t||\n", b, idx, fitresults[b].at(i));
}
}
else{
spdlog::info("|| {0:d}\t\t All PDFs\t\t{1:d} \t||\n", b, fitresults[b].at(0)); //TODO
}
}
}
return;
}
void print_sig_yields(unsigned int nBins, std::vector<UInt_t> pdf_idx,
std::vector<UInt_t> *evts_cntr, std::vector<double> *f_sigs, std::vector<double> *f_sigserr){
spdlog::info("");
spdlog::info("==========================================");
spdlog::info("|| SIGNAL YIELDS ||");
spdlog::info("==========================================");
spdlog::info("|| BIN\t\tPDF\tsignal yield ||");
for(unsigned int b = 0; b < nBins; b++){
for(UInt_t i = 0; i < pdf_idx.size(); i++){
spdlog::info("|| {0:d}\t\t{1:d}\t{2:f}+/-{3:f}\t||", b, pdf_idx.at(i), evts_cntr[b].at(i)*f_sigs[b].at(i), evts_cntr[b].at(i)*f_sigserr[b].at(i));
}
}
spdlog::info("");
}
void print_bkg_yields(unsigned int nBins, std::vector<UInt_t> pdf_idx,
std::vector<UInt_t> *evts_cntr, std::vector<double> *f_sigs, std::vector<double> *f_sigserr){
spdlog::info("");
spdlog::info("==========================================");
spdlog::info("|| BACKGROUND YIELDS ||");
spdlog::info("==========================================");
spdlog::info("|| BIN\t\tPDF\tbkg yield ||");
for(unsigned int b = 0; b < nBins; b++){
for(UInt_t i = 0; i < pdf_idx.size(); i++){
spdlog::info("|| {0:d}\t\t{1:d}\t{2:.1f}+/-{3:.1f}\t ||", b, pdf_idx.at(i), evts_cntr[b].at(i)*(1 - f_sigs[b].at(i)), evts_cntr[b].at(i)*f_sigserr[b].at(i));
}
}
spdlog::info("");
}
void print_bkgOnly_yields(unsigned int nBins, std::vector<UInt_t> pdf_idx,
std::vector<fcnc::bu2kstarmumu_parameters*> theParams[],
std::vector<double> bkg_int_full_range[], std::vector<UInt_t> *evts_cntr){
spdlog::info("");
spdlog::info("==========================================");
spdlog::info("|| BACKGROUND YIELDS ||");
spdlog::info("==========================================");
spdlog::info("|| BIN\t\tPDF\tbkg yield ||");
for(unsigned int b = 0; b < nBins; b++){
for(UInt_t i = 0; i < pdf_idx.size(); i++){
spdlog::info("[BIN{0:d}]\tBckgnd est.: {1:.4f}\tBkg prob: {2:.4f}\tBkg iac: {3:.4f}\tExpCoeff: {4:.4f}",
i,
evts_cntr[b].at(i) * bkg_int_full_range[i].at(b) * (1 - theParams[b].at(i)->f_sig.get_value()),
bkg_int_full_range[b].at(i),
1 - theParams[b].at(i)->f_sig.get_value(),
theParams[b].at(i)->m_lambda.get_value());
}
}
spdlog::info("");
}
void print_sig_yields_tex(std::string texFiletag, unsigned int nBins, std::vector<UInt_t> pdf_idx,
fcnc::options *theOptions,
std::vector<UInt_t> *evts_cntr, std::vector<double> *f_sigs, std::vector<double> *f_sigserr){
//Open texFile
std::ofstream myFile;
open_Latex_noteFile(texFiletag, myFile);
double yield[nBins], yielderr[nBins];
myFile << "\\begin{tabular}{|l|"; //TODO: have a function for this
for(UInt_t i = 0; i < pdf_idx.size(); i++) myFile << "r";
myFile << "|r|}\\hline" << std::endl;
myFile << "\\qsq bin";
for(UInt_t i = 0; i < pdf_idx.size(); i++){
myFile << "\t& Run" << theOptions[i].run;
}
myFile << "\\\\" << std::endl;
myFile << "\\hline\\hline" << std::endl;
for(unsigned int b = 0; b < nBins; b++){
myFile << b << "\t&";
yield[b] = 0.0; yielderr[b] = 0.0;
for(UInt_t i = 0; i < pdf_idx.size(); i++){
myFile << "$" << std::setprecision(1) << std::fixed << evts_cntr[b].at(i)*f_sigs[b].at(i) << "\\pm" << evts_cntr[b].at(i)*f_sigserr[b].at(i) << "$ \t&";
yield[b] += evts_cntr[b].at(i)*f_sigs[b].at(i);
yielderr[b] += evts_cntr[b].at(i)*f_sigserr[b].at(i)*evts_cntr[b].at(i)*f_sigserr[b].at(i);
}
myFile << "$" << yield[b] << "\\pm" << TMath::Sqrt(yielderr[b]) << "$\\\\" << std::endl;
}
myFile << "\\hline\\end{tabular}" << std::endl << std::endl << std::endl << std::endl;
myFile << "\\begin{tabular}{|l|r|}\\hline" << std::endl;
myFile << "\\qsq bin \t& signal yield\\\\" << std::endl;
myFile << "\\hline\\hline" << std::endl;
for(unsigned int b = 0; b < nBins; b++) myFile << b << "\t& $" << yield[b] << "\\pm" << TMath::Sqrt(yielderr[b]) << "$\\\\" << std::endl;
myFile << "\\hline\\end{tabular}" << std::endl << std::endl;
myFile.close();
}
int save_results(std::string results_file, unsigned int nBins, std::vector<UInt_t> pdf_idx, std::vector<int>*fit_results, std::vector<fcnc::parameters*> *theParams, bool simFit, fcnc::options *opts){
//Open the root file
spdlog::info("[SAVE]\t\tSaving result values to file " + results_file);
TFile* fout = new TFile(results_file.c_str(), "RECREATE");
fout->cd();
int param_index = 0;
//loop over parameters:
for(UInt_t p = 0; p < theParams[0].at(0)->nparameters(); p++){
fcnc::parameter* param = theParams[0].at(0)->get_parameter(p);
//if(param->get_step_size() == 0.0) continue; //skip fixed parameters
std::string parname(param->get_name());
std::string pardesc(param->get_description());
spdlog::trace("Creating new TTree for parameter:" + parname);
TTree* t = new TTree(parname.c_str(), pardesc.c_str());
int pdf = DEFAULT_TREE_INT;
int bin = DEFAULT_TREE_INT;
int migrad = DEFAULT_TREE_INT;
int status_cov = DEFAULT_TREE_INT;
int totBins = DEFAULT_TREE_INT;
double q2a = DEFAULT_TREE_VAL;
double q2b = DEFAULT_TREE_VAL;
double value = DEFAULT_TREE_VAL;
double error = DEFAULT_TREE_ERR;
double error_up = DEFAULT_TREE_ERR;
double error_down = DEFAULT_TREE_ERR;
double start_value = DEFAULT_TREE_VAL;
double prev_value = DEFAULT_TREE_VAL;
double prev_error = DEFAULT_TREE_ERR;
const unsigned int corr_max = param->correlations.size();
double tmp_corr[corr_max];
t->Branch("pdf",&pdf,"pdf/I");
t->Branch("bin",&bin,"bin/I");
t->Branch("totBins",&totBins,"totBins/I");
t->Branch("migrad",&migrad,"migrad/I");
t->Branch("status_cov",&status_cov,"status_cov/I");
t->Branch("value",&value,"value/D");
t->Branch("q2min",&q2a,"q2min/D");
t->Branch("q2max",&q2b,"q2max/D");
t->Branch("error",&error,"error/D");
t->Branch("error_up",&error_up,"error_up/D");
t->Branch("error_down",&error_down,"error_down/D");
t->Branch("start_value",&start_value,"start_value/D");
t->Branch("prev_value",&prev_value,"prev_value/D");
t->Branch("prev_error",&prev_error,"prev_error/D");
t->Branch("index",&param_index, "index/I");
t->Branch("correlations",&tmp_corr,("correlations["+std::to_string(corr_max)+"]/D").c_str());
//loop over PDFs
for_indexed(auto n_pdf: pdf_idx){
for(unsigned int b = 0; b < nBins; b++){
fcnc::parameter* par = par_with_correct_name(p, parname, theParams[b].at(i));
if (par == NULL) break;
totBins = nBins;
bin = b;
pdf = n_pdf;
migrad = fit_results[b].at(simFit ? 0 : i) % 100;
status_cov = fit_results[b].at(simFit ? 0 : i) / 100;
q2a = opts->TheQ2binsmin[b];
q2b = opts->TheQ2binsmax[b];
value = par->get_value();
error = par->get_error();
error_up = par->get_error_up();
error_down = par->get_error_down();
if (opts->minos_errors){
if (error_up==0.0 && value < par->get_max()) error_up = par->get_max() - value;
if (error_down==0.0 && value > par->get_min()) error_down = par->get_min() - value;//needs to be negative
}
start_value = par->get_start_value();
prev_value = par->get_previous_measurement();
prev_error = par->get_previous_error();
for (unsigned int l = 0; l < corr_max; l++) tmp_corr[l] = 0.0; //Fill with zeroes
for (unsigned int l = 0; l < par->correlations.size(); l++){
tmp_corr[l] = par->correlations.at(l);
}
t->Fill();
}
} //end loop over pdfs
//Write the parameter tree
t->Write();
delete t;
param_index++;
}
//Close the root file
spdlog::info("Finished saving the parameters into the file {0:s}.",fout->GetName());
fout->Close();
delete fout;
//Delete the tex file with parameters
clear_Latex_noteFile(latex_params());
//Copy the parameter in TeX format into the same place as the final results file
tex_all_parameters(nBins,pdf_idx,theParams);
replace(results_file,".root",".tex");
copyFile(get_Latex_noteFile(latex_params()),results_file);
return 0;
}
int save_results(std::string results_file, unsigned int nBins, int n_pdf, std::vector<int> fit_results, fcnc::bu2kstarmumu_parameters **theParams, fcnc::options *opts){
//Open the root file
spdlog::info("[SAVE]\t\tSaving result values to file " + results_file);
TFile* fout = new TFile(results_file.c_str(), "RECREATE");
fout->cd();
int param_index = 0;
//loop over parameters:
for(UInt_t p = 0; p < theParams[0]->nparameters(); p++){
fcnc::parameter* param = theParams[0]->get_parameter(p);
//if(param->get_step_size() == 0.0) continue; //skip fixed parameters
std::string parname(param->get_name());
std::string pardesc(param->get_description());
spdlog::trace("Creating new TTree for parameter:" + parname);
TTree* t = new TTree(parname.c_str(), pardesc.c_str());
int pdf = DEFAULT_TREE_INT;
int bin = DEFAULT_TREE_INT;
int migrad = DEFAULT_TREE_INT;
int status_cov = DEFAULT_TREE_INT;
int totBins = DEFAULT_TREE_INT;
double q2a = DEFAULT_TREE_VAL;
double q2b = DEFAULT_TREE_VAL;
double value = DEFAULT_TREE_VAL;
double error = DEFAULT_TREE_ERR;
double error_up = DEFAULT_TREE_ERR;
double error_down = DEFAULT_TREE_ERR;
double start_value = DEFAULT_TREE_VAL;
double prev_value = DEFAULT_TREE_VAL;
double prev_error = DEFAULT_TREE_ERR;
const unsigned int corr_max = param->correlations.size();
double tmp_corr[corr_max];
t->Branch("pdf",&pdf,"pdf/I");
t->Branch("bin",&bin,"bin/I");
t->Branch("totBins",&totBins,"totBins/I");
t->Branch("migrad",&migrad,"migrad/I");
t->Branch("status_cov",&status_cov,"status_cov/I");
t->Branch("value",&value,"value/D");
t->Branch("q2min",&q2a,"q2min/D");
t->Branch("q2max",&q2b,"q2max/D");
t->Branch("error",&error,"error/D");
t->Branch("error_up",&error_up,"error_up/D");
t->Branch("error_down",&error_down,"error_down/D");
t->Branch("start_value",&start_value,"start_value/D");
t->Branch("prev_value",&prev_value,"prev_value/D");
t->Branch("prev_error",&prev_error,"prev_error/D");
t->Branch("index",&param_index, "index/I");
t->Branch("correlations",&tmp_corr,("correlations["+std::to_string(corr_max)+"]/D").c_str());
//loop over nBins
for(unsigned int b = 0; b < nBins; b++){
fcnc::parameter* par = par_with_correct_name(p, parname, theParams[b]);
if (par == NULL) break;
totBins = nBins;
bin = b;
pdf = n_pdf;
migrad = fit_results[b] % 100;
status_cov = fit_results[b] / 100;
q2a = opts->TheQ2binsmin[b];
q2b = opts->TheQ2binsmax[b];
value = par->get_value();
error = par->get_error();
error_up = par->get_error_up();
error_down = par->get_error_down();
if (opts->minos_errors){
if (error_up==0.0 && value < par->get_max()) error_up = par->get_max() - value;
if (error_down==0.0 && value > par->get_min()) error_down = par->get_min() - value;//needs to be negative
}
start_value = par->get_start_value();
prev_value = par->get_previous_measurement();
prev_error = par->get_previous_error();
for (unsigned int l = 0; l < corr_max; l++) tmp_corr[l] = 0.0; //Fill with zeroes
for (unsigned int l = 0; l < par->correlations.size(); l++){
tmp_corr[l] = par->correlations.at(l);
}
t->Fill();
}
//Write the parameter tree
t->Write();
delete t;
param_index++;
} //End loop over names
//Close the root file
spdlog::info("Finished saving the parameters into the file {0:s}.",fout->GetName());
fout->Close();
//Delete the tex file with parameters
clear_Latex_noteFile(latex_params());
//Copy the parameter in TeX format into the same place as the final results file
tex_all_parameters(nBins,n_pdf,theParams);
replace(results_file,".root",".tex");
copyFile(get_Latex_noteFile(latex_params()),results_file);
delete fout;
return 0;
}
//--------------------------------------//
// Helpers for writting latex stuff //
//--------------------------------------//
int clear_Latex_noteFile(std::string tag){
if( remove(get_Latex_noteFile(tag).c_str()) != 0 ) spdlog::warn( "Unable to delete file " + get_Latex_noteFile(tag) ); //Do not return an error status cause the file might just not exist, which is ok
else spdlog::trace( "Latex noteFile successfully deleted" );
return 0;
}
int open_Latex_noteFile(std::string tag, std::ofstream &myfile){
//This is not working cause this thing is for whatever efin reason stuck with gcc 4.
myfile.open (get_Latex_noteFile(tag), std::ios::out | std::ios::app);
if (!myfile.is_open()){
spdlog::error("Latex noteFile" + get_Latex_noteFile(tag) + " is not opened.");
return 404;
}
else{
spdlog::trace("Latex noteFile successfully deleted");
return 0;
}
}
//--------------------------------------//
// Helpers for reading the parameters //
//--------------------------------------//
//Checks if the observable is in the TFile
//If required Fl and there is S1s, it returns 11, ...
//Modulo 10 then returns whether the observable actually exists
//Example usage: if (try_getObservable(paramName, file)%10==0) assert(0)
int try_getObservable(std::string observable, TFile* file){
if (!file->GetListOfKeys()->Contains(observable.c_str())){
//Also check if Fl<->S1s and A_FB<->S6s is available
if (observable == "Fl") return 10+try_getObservable("S1s",file);
if (observable == "S1s") return 20+try_getObservable("Fl",file);
if (observable == "Afb") return 30+try_getObservable("S6s",file);
if (observable == "S6s") return 40+try_getObservable("Afb",file);
return 0;
}
else return 1;
}
std::vector<double> load_param_values_into_vector(std::string paramName, std::string fileName){
//There is a function for this in bu2kstarmumu_parameters.cc, but that is inherited from parameters, therefore a parameter class needs to be created for this
//That would be tedious, so there is a new class that opens the root file with results and reads it from a tree directly into an array
//Create the vector that will be returned
std::vector<double> output;
//Open file
spdlog::info("Opening " + fileName);
TFile* file = new TFile(fileName.c_str(), "READ");
int isFoundFlag = try_getObservable(paramName, file);
if (!(isFoundFlag%10)){
spdlog::critical("Wrong tree name " + paramName + "! Returning an empty vector!");
//It should not crash here as it might be desired to init some observables but not use them
return {};
}
else{
switch(isFoundFlag){
case 11: //Need Fl, have S1s
paramName = "S1s";
break;
case 21: //Need S1s, have FL
paramName = "Fl";
break;
case 31: //Need Afb, have S6s
paramName = "S6s";
break;
case 41: //Need S6s, have Afb
paramName = "Afb";
break;
}
//case 1: all good, move one
}
//Get the tree
TTree* tree = (TTree*)file->Get(paramName.c_str());
//Activate only needed branches
tree->SetBranchStatus("*",0);
tree->SetBranchStatus("value",1);
double value = DEFAULT_TREE_VAL;
tree->SetBranchAddress("value", &value);
//Loop over nBins that are saved in the tree
for (int b = 0; b < tree->GetEntries(); b++){
tree->GetEntry(b);
//There are not many bins so just do a switch and fill accordingly
switch(isFoundFlag){
case 1:
output.push_back(value);
case 11: //Need Fl, have S1s
output.push_back(1-4.0/3.0*value);
break;
case 21: //Need S1s, have FL
output.push_back(3.0/4.0*(1-value));
break;
case 31: //Need Afb, have S6s
output.push_back(3.0/4.0*value);
break;
case 41: //Need S6s, have Afb
output.push_back(4.0/3.0*value);
break;
}
}
spdlog::debug(convert_vector_to_string(output));
return output;
}