//Renata Kopecna #include #include //Needed to remove/copy files #include #include #include #include #include #include #include #include #include #include #include #include //includes accumulate #include #include #include //----------------------// // 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 get_years(int Run, bool MCsig, bool MCref){ std::vectoryears; 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 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 myVector){ std::stringstream ss; copy(myVector.begin(), myVector.end(), std::ostream_iterator(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 myVector){ std::stringstream ss; copy(myVector.begin(), myVector.end(), std::ostream_iterator(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 myVector){ std::stringstream ss; copy(myVector.begin(), myVector.end(), std::ostream_iterator(ss, " ")); std::string s = ss.str(); return s.substr(0, s.length()-1); // get rid of the trailing space } std::vector merge_two_vecs(std::vector one, std::vector two){ std::vector 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 merge_two_vecs(std::vector one, std::vector two){ std::vector 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 merge_two_vecs(std::vector one, std::vector two){ //TODO: I bet there is a way to avoid overloading std::vector 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 vec){ return std::accumulate(vec.begin(), vec.end(), 0); } //Sum a vector of doubles double sum_vector(std::vector 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 q2min, std::vector 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 q2min, std::vector 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::vectorvec){ return (std::find(vec.begin(), vec.end(), key)!= vec.end()); } bool isInVec(double key, std::vectorvec){ return (std::find(vec.begin(), vec.end(), key)!= vec.end()); } bool isInVec(std::string key, std::vectorvec){ 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> 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 get_angObser_vec(){ std::vector tmp; for (auto obs: get_angObser_withTeX_vec()){ tmp.push_back(obs[0]); } return tmp; } std::vector get_angObserTeX_vec(){ std::vector 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 param_string_pPrimes(bool fitFL){ std::vector 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 param_string_pPrimes(bool fitFL, int folding){ std::vector 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 param_string_s(bool fitFL, bool fitAFB){ std::vector 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 param_string_s(bool fitFL, bool fitAFB, int folding){ std::vector 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 param_string_sWave(){ std::vector 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 param_string_sWave(int folding){ std::vector 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 param_string_bkg(){ std::vector 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 param_string_bkg_mkpi(){ std::vector str; for (int i = 1; i < 2; i++){ str.push_back("cbkgmkpi"+std::to_string(i)); } return str; } std::vector param_string(fcnc::options opts, bool MC){ std::vector 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 sWave = param_string_sWave(); params.insert(params.end(), sWave.begin(), sWave.end()); } if(!MC){ std::vector 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 sWave = param_string_sWave(opts.folding); params.insert(params.end(), sWave.begin(), sWave.end()); } if(!MC){ std::vector 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 params_string_mass(fcnc::options opts){ std::vector 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 pdf_idx, std::vector 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 pdf_idx, std::vector 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 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 pdf_idx, std::vector 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 pdf_idx, std::vector *evts_cntr, std::vector *f_sigs, std::vector *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 pdf_idx, std::vector *evts_cntr, std::vector *f_sigs, std::vector *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 pdf_idx, std::vector theParams[], std::vector bkg_int_full_range[], std::vector *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 pdf_idx, fcnc::options *theOptions, std::vector *evts_cntr, std::vector *f_sigs, std::vector *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 pdf_idx, std::vector*fit_results, std::vector *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",¶m_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 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",¶m_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 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 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; }