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

  1. //Renata Kopecna
  2. #include <helpers.hh>
  3. #include <fstream> //Needed to remove/copy files
  4. #include <bu2kstarmumu_parameters.hh>
  5. #include <sstream>
  6. #include <iostream>
  7. #include <options.hh>
  8. #include <parameters.hh>
  9. #include <constants.hh>
  10. #include <spdlog.h>
  11. #include <fmt/ostr.h>
  12. #include <TFile.h>
  13. #include <TTree.h>
  14. #include <paths.hh>
  15. #include <numeric> //includes accumulate
  16. #include <parse.hh>
  17. #include <event.hh>
  18. #include <spdlog.h>
  19. //----------------------//
  20. // Print utils //
  21. //----------------------//
  22. std::string boolToString(bool isTrue){
  23. if (isTrue) return "TRUE";
  24. else return "FALSE";
  25. }
  26. void reset_spdlog(){
  27. spdlog::set_pattern("[%^%l%$]\t %v");
  28. }
  29. void set_spdlog_level(int verboseLvl){
  30. switch(verboseLvl) {
  31. case 0:
  32. spdlog::set_level(spdlog::level::trace);
  33. break;
  34. case 1:
  35. spdlog::set_level(spdlog::level::debug);
  36. break;
  37. case 2:
  38. spdlog::set_level(spdlog::level::info);
  39. break;
  40. case 3:
  41. spdlog::set_level(spdlog::level::warn);
  42. break;
  43. case 4:
  44. spdlog::set_level(spdlog::level::err);
  45. break;
  46. case 5:
  47. spdlog::set_level(spdlog::level::critical);
  48. break;
  49. }
  50. return;
  51. }
  52. bool spdlog_trace(){
  53. return (spdlog::default_logger_raw()->level()<=spdlog::level::trace);
  54. }
  55. bool spdlog_debug(){
  56. return (spdlog::default_logger_raw()->level()<=spdlog::level::debug);
  57. }
  58. bool spdlog_info(){
  59. return (spdlog::default_logger_raw()->level()<=spdlog::level::info);
  60. }
  61. bool spdlog_warn(){
  62. return (spdlog::default_logger_raw()->level()<=spdlog::level::warn);
  63. }
  64. bool spdlog_error(){
  65. return (spdlog::default_logger_raw()->level()<=spdlog::level::err);
  66. }
  67. std::string get_sample_from_jobID(int job_id){
  68. if(job_id == 0) return "DATA";
  69. else if(job_id == 1) return "SIGNAL MC";
  70. else if(job_id == 2) return "REFERENCE MC ";
  71. else if(job_id == 3) return "PHSP MC ";
  72. else if(job_id == 4) return "GenLevel PHSP MC";
  73. else if(job_id == 5) return "GenLevel MC";
  74. else {
  75. spdlog::error("Invalid index for conversion function given: {0:d}", job_id);
  76. assert(0);
  77. }
  78. }
  79. std::string format_double(double value, unsigned int digits){
  80. std::stringstream out;
  81. out << std::fixed << std::setprecision(digits) << value;
  82. return out.str();
  83. };
  84. std::string format_value(double value, double error, unsigned int digits){
  85. //format value such that the relevant number of digits is given back
  86. //determine first "digits" significant places of error
  87. if (error == 0.0){
  88. std::stringstream out; //to_string(value) returns something else than this.... I hate c++
  89. out << value;
  90. return out.str();
  91. }
  92. else{
  93. int first_significant = floor(log10(error));
  94. if (first_significant > 0) first_significant = 0;
  95. //ln(e^x)=x log10(c*10^x)=x+log10(c) with log10(c) < 1
  96. return format_double(value,fabs(first_significant)+digits-1);
  97. }
  98. };
  99. std::string format_error(double error, unsigned int digits){
  100. return (format_value(error,error,digits));
  101. };
  102. //----------------------//
  103. // Year utils //
  104. //----------------------//
  105. //generate vector with years for every run option
  106. //notation for usage of runs:
  107. //1 : Run 1
  108. //2 : Run 2
  109. //12: Run 1+2
  110. //21: 'Run 2.1' = 2015+2016
  111. //22: 'Run 2.2' = 2017+2018
  112. std::vector<int> get_years(int Run, bool MCsig, bool MCref){
  113. std::vector<int>years;
  114. if(Run == 1 || Run == 12){
  115. years.push_back(2011);
  116. years.push_back(2012);
  117. }
  118. if(Run== 2 || Run == 12 || Run== 21){
  119. if (!MCsig) years.push_back(2015); //No MC for 2015
  120. years.push_back(2016);
  121. }
  122. if (!MCref){ //No RefMC for 2017+2018
  123. if(Run == 2 || Run == 12 || Run == 22){
  124. years.push_back(2017);
  125. years.push_back(2018);
  126. }
  127. }
  128. return years;
  129. }
  130. //Check if year is a run year
  131. void check_year(int year){
  132. std::set<int> yearSet = {2011,2012,2015,2016,2017,2018};
  133. //Check if year is in a set, if not, throw exception
  134. assert(yearSet.find(year)!= yearSet.end());
  135. return;
  136. }
  137. int MC_dataset(bool Reference, bool PHSP){
  138. if (PHSP) return 3; //PHSP
  139. else if (Reference) return 2; //Ref MC
  140. else return 1; //Sig MC
  141. }
  142. int get_yearFromRun(int year){
  143. if (year == 2011 || year == 2012) return 1;
  144. if (year == 2015 || year == 2016 || year == 2017 || year == 2018) return 2;
  145. spdlog::error("Year not recognized!");
  146. assert(0);
  147. }
  148. //--------------------------------------//
  149. // General helpers //
  150. //--------------------------------------//
  151. //Copy file
  152. int copyFile(std::string from, std::string to){
  153. std::ifstream src(from);
  154. std::ofstream dst(to);
  155. dst << src.rdbuf();
  156. return 0;
  157. }
  158. //Check if file exists
  159. //https://stackoverflow.com/questions/12774207/fastest-way-to-check-if-a-file-exist-using-standard-c-c11-c
  160. bool existsTest (const std::string& name) {
  161. struct stat buffer;
  162. return (stat (name.c_str(), &buffer) == 0);
  163. }
  164. //https://stackoverflow.com/questions/50960492/creating-folders-in-c
  165. //Create parent folders if needed
  166. void makeFolder (const std::string& name) {
  167. std::string parentfolder = name.substr(0, name.find_last_of("/\\"));
  168. if(!existsTest(parentfolder))makeFolder(parentfolder);
  169. spdlog::info("Creating folder '"+name+"'");
  170. mkdir(name.c_str(), 0755);
  171. return;
  172. }
  173. //Convert vector into number-space-number... string
  174. std::string convert_vector_to_string(std::vector<int> myVector){
  175. std::stringstream ss;
  176. copy(myVector.begin(), myVector.end(), std::ostream_iterator<int>(ss, " "));
  177. std::string s = ss.str();
  178. return s.substr(0, s.length()-1); // get rid of the trailing space
  179. }
  180. std::string convert_vector_to_string(std::vector<double> myVector){
  181. std::stringstream ss;
  182. copy(myVector.begin(), myVector.end(), std::ostream_iterator<double>(ss, " "));
  183. std::string s = ss.str();
  184. return s.substr(0, s.length()-1); // get rid of the trailing space
  185. }
  186. std::string convert_vector_to_string(std::vector<std::string> myVector){
  187. std::stringstream ss;
  188. copy(myVector.begin(), myVector.end(), std::ostream_iterator<std::string>(ss, " "));
  189. std::string s = ss.str();
  190. return s.substr(0, s.length()-1); // get rid of the trailing space
  191. }
  192. std::vector<double> merge_two_vecs(std::vector<double> one, std::vector<double> two){
  193. std::vector<double> merged_vec;
  194. merged_vec.insert(merged_vec.end(), one.begin(), one.end());
  195. merged_vec.insert(merged_vec.end(), two.begin(), two.end());
  196. return merged_vec;
  197. }
  198. std::vector<int> merge_two_vecs(std::vector<int> one, std::vector<int> two){
  199. std::vector<int> merged_vec;
  200. merged_vec.insert(merged_vec.end(), one.begin(), one.end());
  201. merged_vec.insert(merged_vec.end(), two.begin(), two.end());
  202. return merged_vec;
  203. }
  204. 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
  205. std::vector<std::string> merged_vec;
  206. merged_vec.insert(merged_vec.end(), one.begin(), one.end());
  207. merged_vec.insert(merged_vec.end(), two.begin(), two.end());
  208. return merged_vec;
  209. }
  210. bool replace(std::string& str, const std::string& from, const std::string& to) {
  211. size_t start_pos = str.find(from);
  212. if(start_pos == std::string::npos)
  213. return false;
  214. while ( (start_pos = str.find(from,start_pos)) != std::string::npos){
  215. str.replace(start_pos, from.length(), to);
  216. start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
  217. }
  218. return true;
  219. }
  220. //Sum a vector of ints
  221. int sum_vector(std::vector<int> vec){
  222. return std::accumulate(vec.begin(), vec.end(), 0);
  223. }
  224. //Sum a vector of doubles
  225. double sum_vector(std::vector<double> vec){
  226. return std::accumulate(vec.begin(), vec.end(), 0.0);
  227. }
  228. //Return the center of a bin
  229. double bin_center(double low, double high){
  230. return (high+low)/2.0;
  231. }
  232. //Return the center of a q2 bin
  233. double bin_center_q2(fcnc::options opts, int b){
  234. return bin_center(opts.TheQ2binsmin.at(b),opts.TheQ2binsmax.at(b));
  235. }
  236. double bin_center_q2(fcnc::options *opts, int b){
  237. return bin_center(opts->TheQ2binsmin.at(b),opts->TheQ2binsmax.at(b));
  238. }
  239. double bin_center_q2(std::vector<double> q2min, std::vector<double> q2max , int b){
  240. return bin_center(q2min.at(b),q2max.at(b));
  241. }
  242. //Return half of the width (useful for errors)
  243. double bin_halfWidth(double low, double high){
  244. return (high-low)/2.0;
  245. }
  246. double bin_halfWidth_q2(std::vector<double> q2min, std::vector<double> q2max, int b){
  247. return (q2max.at(b)-q2min.at(b))/2.0;
  248. }
  249. double bin_halfWidth_q2(fcnc::options opts, int b){
  250. return (opts.TheQ2binsmax.at(b)-opts.TheQ2binsmin.at(b))/2.0;
  251. }
  252. double bin_halfWidth_q2(fcnc::options *opts, int b){
  253. return (opts->TheQ2binsmax.at(b)-opts->TheQ2binsmin.at(b))/2.0;
  254. }
  255. //Check if the angles are in the correct range given by options
  256. bool isEvtInAngleRange(fcnc::event *evt, fcnc::options *opts){
  257. if (evt->costhetal > opts->ctl_max) return false;
  258. if (evt->costhetal < opts->ctl_min) return false;
  259. if (evt->costhetak > opts->ctk_max) return false;
  260. if (evt->costhetak < opts->ctk_min) return false;
  261. if (evt->phi > opts->phi_max) return false;
  262. if (evt->phi < opts->phi_min) return false;
  263. if (evt->q2 > opts->TheQ2binsmax.back()) return false;
  264. if (evt->q2 < opts->TheQ2binsmin.front()) return false;
  265. return true;
  266. }
  267. //Check if the angles are in the correct range given by default
  268. bool isEvtInAngleRange(fcnc::event *evt){
  269. if (evt->costhetal > CTL_MAX){
  270. spdlog::trace("ctl of event:\t{0:f}",evt->costhetal);
  271. return false;
  272. }
  273. if (evt->costhetal < CTL_MIN){
  274. spdlog::trace("ctl of event:\t{0:f}",evt->costhetal);
  275. return false;
  276. }
  277. if (evt->costhetak > CTK_MAX) {
  278. spdlog::trace("ctk of event:\t{0:f}",evt->costhetak);
  279. return false;
  280. }
  281. if (evt->costhetak < CTK_MIN) {
  282. spdlog::trace("ctk of event:\t{0:f}",evt->costhetak);
  283. return false;
  284. }
  285. if (evt->phi > PHI_MAX){
  286. spdlog::trace("phi of event:\t{0:f}",evt->phi);
  287. return false;
  288. }
  289. if (evt->phi < PHI_MIN) {
  290. spdlog::trace("phi of event:\t{0:f}",evt->phi);
  291. return false;
  292. }
  293. if (evt->q2 < Q2_MIN_RANGE) return false;
  294. if (evt->q2 > Q2_MAX_RANGE) return false;
  295. return true;
  296. }
  297. //For now filter out events that are dumb dumb for folding four
  298. bool filterFldFour(fcnc::event *evt, fcnc::options *opts){
  299. if (opts->folding==4){
  300. //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
  301. // SO this if (!isEvtInAngleRange(&evt,&opts)) continue; is not possible
  302. if (evt->costhetak > opts->ctk_max) return false;
  303. if (evt->costhetak < opts->ctk_min) return false;
  304. }
  305. return true;
  306. }
  307. //Check if value is in a vector
  308. bool isInVec(int key, std::vector<int>vec){
  309. return (std::find(vec.begin(), vec.end(), key)!= vec.end());
  310. }
  311. bool isInVec(double key, std::vector<double>vec){
  312. return (std::find(vec.begin(), vec.end(), key)!= vec.end());
  313. }
  314. bool isInVec(std::string key, std::vector<std::string>vec){
  315. return (std::find(vec.begin(), vec.end(), key)!= vec.end());
  316. }
  317. //--------------------------------------//
  318. // Helpers for converting the tuples //
  319. //--------------------------------------//
  320. //Returns the correct tree name as Data/MC and genLvl have different tree names
  321. std::string get_inputTree_name(int job_id){
  322. if(job_id == 0) return "DecayTree";
  323. else if(job_id == 1) return "DecayTreeTruthMatched";
  324. else if(job_id == 2) return "DecayTreeTruthMatched";
  325. else if(job_id == 3) return "DecayTreeTruthMatched";
  326. else if(job_id == 4) return "DecayTree";
  327. else if(job_id == 5) return "DecayTree";
  328. else {
  329. spdlog::error("Invalid index for conversion function given: {0:d}", job_id);
  330. assert(0);
  331. }
  332. }
  333. //--------------------------------------//
  334. // Helpers for angular corrections //
  335. //--------------------------------------//
  336. TF1 *fitStraightLine(TH1D* hist, std::string lineName, double lowEdge, double highEdge){
  337. //Define the fit line
  338. TF1 *fitLine= new TF1(lineName.c_str(), "[0]*x+[1]", lowEdge, highEdge);
  339. fitLine->SetParameters(0.0, 1.0);
  340. fitLine->SetParLimits(0,-0.5,0.5);
  341. fitLine->SetParLimits(1,0.5,1.5);
  342. fitLine->SetParNames("a","b");
  343. std::string fitOption = spdlog_debug() ? "R" : "RQ"; //C turns off chi2 calculation, faster, Q=quiet
  344. hist->Fit(lineName.c_str(), fitOption.c_str());
  345. spdlog::debug("Fitted value is:\t{0:f}+-{1:f}",fitLine->GetParameter(0), fitLine->GetParError(0));
  346. return fitLine;
  347. }
  348. //--------------------------------------//
  349. // Helpers for bu2kstarmumu_pdf //
  350. //--------------------------------------//
  351. const std::vector<std::vector<std::string>> get_angObser_withTeX_vec(){
  352. return {
  353. {"1s","#xi_{1}^{s}"},
  354. {"1c","#xi_{1}^{c}"},
  355. {"2s","#xi_{2}^{s}"},
  356. {"2c","#xi_{2}^{c}"},
  357. {"3","#xi_{3}"},
  358. {"4", "#xi_{4}"},
  359. {"5","#xi_{5}"},
  360. {"6s","#xi_{6}^{s}"},
  361. {"6c","#xi_{6}^{c}"},
  362. {"7","#xi_{7}"},
  363. {"8","#xi_{8}"},
  364. {"9","#xi_{9}"}
  365. };
  366. }
  367. std::vector<std::string> get_angObser_vec(){
  368. std::vector<std::string> tmp;
  369. for (auto obs: get_angObser_withTeX_vec()){
  370. tmp.push_back(obs[0]);
  371. }
  372. return tmp;
  373. }
  374. std::vector<std::string> get_angObserTeX_vec(){
  375. std::vector<std::string> tmp;
  376. for (auto obs: get_angObser_withTeX_vec()){
  377. tmp.push_back(obs[1]);
  378. }
  379. return tmp;
  380. }
  381. //--------------------------------------//
  382. // Helpers for time measuring //
  383. //--------------------------------------//
  384. void runTime::start(){
  385. sw->Reset();
  386. sw->Start();
  387. return;
  388. }
  389. void runTime::stop(time_t startTime){
  390. sw->Stop();
  391. real_times.push_back(sw->RealTime());
  392. cpu_times.push_back(sw->CpuTime());
  393. cpp_times.push_back(Double_t(time(0) - startTime));
  394. return;
  395. }
  396. void runTime::print(unsigned int nBins){
  397. spdlog::info("");
  398. spdlog::info("==========================================");
  399. spdlog::info("|| TIME OF FIT ||");
  400. spdlog::info("==========================================");
  401. spdlog::info("|| BIN\t\tCPU time[s]\treal time[s]\tC++ time[s]\t||");
  402. for(unsigned int b = 0; b < nBins; b++){
  403. Int_t CpuHours = Int_t(cpu_times.at(b) / 3600);
  404. cpu_times.at(b) -= CpuHours * 3600;
  405. Int_t CpuMinutes = Int_t(cpu_times.at(b) / 60);
  406. cpu_times.at(b) -= CpuMinutes * 60;
  407. Int_t CpuSeconds = Int_t(cpu_times.at(b));
  408. Int_t RealHours = Int_t(real_times.at(b) / 3600);
  409. real_times.at(b) -= RealHours * 3600;
  410. Int_t RealMinutes = Int_t(real_times.at(b) / 60);
  411. real_times.at(b) -= RealMinutes * 60;
  412. Int_t RealSeconds = Int_t(real_times.at(b));
  413. Int_t CppHours = Int_t(cpp_times.at(b) / 3600);
  414. cpp_times.at(b) -= CppHours * 3600;
  415. Int_t CppMinutes = Int_t(cpp_times.at(b) / 60);
  416. cpp_times.at(b) -= CppMinutes * 60;
  417. Int_t CppSeconds = Int_t(cpp_times.at(b));
  418. 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);
  419. }
  420. }
  421. //--------------------------------------//
  422. // Helpers for fit scripts //
  423. //--------------------------------------//
  424. std::vector<std::string> param_string_pPrimes(bool fitFL){
  425. std::vector<std::string> params;
  426. if(fitFL) params.push_back("Fl");
  427. else params.push_back("S1s");
  428. params.push_back("P1");
  429. params.push_back("P4");
  430. params.push_back("P5");
  431. params.push_back("P2");
  432. params.push_back("P6");
  433. params.push_back("P8");
  434. params.push_back("P3");
  435. return params;
  436. }
  437. std::vector<std::string> param_string_pPrimes(bool fitFL, int folding){
  438. std::vector<std::string> params;
  439. if(fitFL) params.push_back("Fl");
  440. else params.push_back("S1s");
  441. if(folding == 0){
  442. params.push_back("P2");
  443. params.push_back("P3");
  444. return params;
  445. }
  446. else if(folding == 1)params.push_back("P4"); //could be a switch, but meh
  447. else if(folding == 2)params.push_back("P5");
  448. else if(folding == 3)params.push_back("P6");
  449. else if(folding == 4)params.push_back("P8");
  450. return params;
  451. }
  452. std::vector<std::string> param_string_s(bool fitFL, bool fitAFB){
  453. std::vector<std::string> params;
  454. if(fitFL) params.push_back("Fl");
  455. else params.push_back("S1s");
  456. params.push_back("S3");
  457. params.push_back("S4");
  458. params.push_back("S5");
  459. if (fitAFB) params.push_back("Afb");
  460. else params.push_back("S6s");
  461. params.push_back("S7");
  462. params.push_back("S8");
  463. params.push_back("S9");
  464. return params;
  465. }
  466. std::vector<std::string> param_string_s(bool fitFL, bool fitAFB, int folding){
  467. std::vector<std::string> params;
  468. if(fitFL) params.push_back("Fl");
  469. else params.push_back("S1s");
  470. params.push_back("S3");
  471. if(folding == 0){
  472. if(fitAFB) params.push_back("Afb");
  473. else params.push_back("S6s");
  474. params.push_back("S9");
  475. return params;
  476. }
  477. else if(folding == 1)params.push_back("S4");
  478. else if(folding == 2)params.push_back("S5");
  479. else if(folding == 3)params.push_back("S7");
  480. else if(folding == 4)params.push_back("S8");
  481. return params;
  482. }
  483. std::vector<std::string> param_string_sWave(){
  484. std::vector<std::string> params;
  485. params.push_back("FS");
  486. params.push_back("SS1");
  487. params.push_back("SS2");
  488. params.push_back("SS3");
  489. params.push_back("SS4");
  490. params.push_back("SS5");
  491. return params;
  492. }
  493. std::vector<std::string> param_string_sWave(int folding){
  494. std::vector<std::string> params;
  495. params.push_back("FS");
  496. if(folding == 1) params.push_back("SS2");
  497. if(folding == 2) params.push_back("SS3");
  498. if(folding > 2) params.push_back("SS4");
  499. if(folding < 4) params.push_back("SS1");
  500. return params;
  501. }
  502. //TODO: merge with parNamesWithTex
  503. std::vector<std::string> param_string_bkg(){
  504. std::vector<std::string> str;
  505. for (auto ang: ANGLES){
  506. for (int i = 1; i < 5; i++){
  507. str.push_back("cbkg"+ang+std::to_string(i));
  508. }
  509. }
  510. return str;
  511. }
  512. std::vector<std::string> param_string_bkg_mkpi(){
  513. std::vector<std::string> str;
  514. for (int i = 1; i < 2; i++){
  515. str.push_back("cbkgmkpi"+std::to_string(i));
  516. }
  517. return str;
  518. }
  519. std::vector<std::string> param_string(fcnc::options opts, bool MC){
  520. std::vector<std::string> params;
  521. //This is suboptimal but I feel it is easier for the reader
  522. if (opts.full_angular){
  523. if(opts.fit_pprimes) params = param_string_pPrimes(opts.fit_fl);
  524. else params = param_string_s(opts.fit_fl, opts.fit_afb);
  525. if(opts.swave){
  526. std::vector<std::string> sWave = param_string_sWave();
  527. params.insert(params.end(), sWave.begin(), sWave.end());
  528. }
  529. if(!MC){
  530. std::vector<std::string> bkg = PAR_BKG_STRING(-1,opts.bkg_order_costhetal,opts.bkg_order_costhetak); //Returns only varied parameters
  531. params.insert(params.end(), bkg.begin(), bkg.end());
  532. }
  533. return params;
  534. }
  535. else{
  536. if(opts.fit_pprimes) params = param_string_pPrimes(opts.fit_fl,opts.folding);
  537. else params = param_string_s(opts.fit_fl, opts.fit_afb,opts.folding);
  538. if(opts.swave){
  539. std::vector<std::string> sWave = param_string_sWave(opts.folding);
  540. params.insert(params.end(), sWave.begin(), sWave.end());
  541. }
  542. if(!MC){
  543. std::vector<std::string> bkg = PAR_BKG_STRING(opts.folding,opts.bkg_order_costhetal,opts.bkg_order_costhetak);
  544. params.insert(params.end(), bkg.begin(), bkg.end());
  545. }
  546. return params;
  547. }
  548. }
  549. std::vector<std::string> params_string_mass(fcnc::options opts){
  550. std::vector<std::string> params;
  551. params.push_back("m_b");
  552. if (!opts.twotailedcrystalball) params.push_back("m_res_1");
  553. params.push_back("m_sigma_1");
  554. if (!opts.twotailedcrystalball) params.push_back("m_sigma_2");
  555. params.push_back("alpha_1");
  556. params.push_back("alpha_2");
  557. params.push_back("n_1");
  558. params.push_back("n_2");
  559. return params;
  560. }
  561. fcnc::parameter* par_with_correct_name(int pos, std::string parname, fcnc::parameters* theParams){
  562. //pos is the position of the parameter I want to save
  563. fcnc::parameter* par = theParams->get_parameter(pos);
  564. //I am not sure, but from the code it seems the parameters should be at the same spot for all pdfs
  565. //Therefore first check if the name on the spot is correct
  566. if (par->get_name() == parname.c_str()) return par;
  567. unsigned int paridx = 0;
  568. while(paridx != theParams->nparameters()){
  569. par = theParams->get_parameter(paridx);
  570. if (par->get_name() == parname.c_str()) return par;
  571. paridx++;
  572. }
  573. spdlog::warn("Parameter "+parname+" not found in PDF {0:d}. Continue with next PDF.");
  574. return NULL;
  575. }
  576. double get_sigmaRatio_fromMC(basic_params params, int nBins, int bin, int pdf){
  577. std::string sigma_name = "m_sigma_1"; //In case one needs m_sigma or m_sigma_2 or so
  578. std::string fileName_sig = final_result_name_MC(params, nBins, false, false, true, false, false);
  579. std::string fileName_ref = final_result_name_MC(params, 1, true, false, true, false, true);
  580. 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));
  581. }
  582. //--------------------------------------//
  583. // Helpers for printing fit results //
  584. //--------------------------------------//
  585. void print_all_parameters(unsigned int nBins, fcnc::bu2kstarmumu_parameters *theParams[],
  586. int spdlog_level, std::string savePath){
  587. //Check whether the desired level >= current level
  588. if (spdlog_level >= spdlog::default_logger_raw()->level()){
  589. //If yes, print the parameters at info level
  590. //Save current level of spdlog
  591. spdlog::level::level_enum tmp_log_level = spdlog::default_logger_raw()->level();
  592. //Set the level to info so it is printed for sure
  593. spdlog::set_level(spdlog::level::info);
  594. spdlog::info("");
  595. spdlog::info("==========================================");
  596. spdlog::info("|| PARAMETERS ||");
  597. spdlog::info("==========================================");
  598. for(unsigned int b = 0; b < nBins; b++){
  599. spdlog::info("|| BIN {0:d}", b);
  600. if(spdlog::default_logger_raw()->level()<=spdlog_level){
  601. theParams[b]->print_parameters(false);
  602. }
  603. if (savePath != ""){
  604. std::string saveBinPath = savePath + "_bin" + std::to_string(b) + ".txt";
  605. theParams[b]->save_param_values(saveBinPath + "");
  606. }
  607. theParams[b]->print_parameters(false);
  608. }
  609. //Reset the level back where it was
  610. spdlog::set_level(tmp_log_level);
  611. }
  612. else return;
  613. }
  614. void print_all_parameters(unsigned int nBins, std::vector<UInt_t> pdf_idx,
  615. std::vector<fcnc::parameters*> theParams[],
  616. int spdlog_level){
  617. //Check whether the desired level >= current level
  618. if (spdlog_level >= spdlog::default_logger_raw()->level()){
  619. //If yes, print the parameters at info level
  620. //Save current level of spdlog
  621. spdlog::level::level_enum tmp_log_level = spdlog::default_logger_raw()->level();
  622. //Set the level to trace so it is printed for sure
  623. //Pritn_parameters needs trace
  624. spdlog::set_level(spdlog::level::trace);
  625. spdlog::info("");
  626. spdlog::info("==========================================");
  627. spdlog::info("|| PARAMETERS ||");
  628. spdlog::info("==========================================");
  629. for(unsigned int b = 0; b < nBins; b++){
  630. for(UInt_t i = 0; i < pdf_idx.size(); i++){
  631. spdlog::info("|| BIN {0:d}\tPDF {1:d}", b, pdf_idx.at(i));
  632. theParams[b].at(i)->print_parameters(false);
  633. }
  634. }
  635. //Reset the level back where it was
  636. spdlog::set_level(tmp_log_level);
  637. }
  638. else return;
  639. }
  640. void tex_all_parameters(unsigned int nBins, std::vector<UInt_t> pdf_idx,
  641. std::vector<fcnc::parameters*> theParams[]){
  642. std::ofstream myFile;
  643. open_Latex_noteFile(latex_params(), myFile); //open file with parameters
  644. for(unsigned int b = 0; b < nBins; b++){
  645. for(UInt_t i = 0; i < pdf_idx.size(); i++){
  646. myFile << "\\captionof{table}{PDF " << i << " bin " << b<< "}" << std::endl;
  647. theParams[b].at(i)->print_parameters(true);
  648. }
  649. }
  650. return;
  651. }
  652. void tex_all_parameters(unsigned int nBins, int n_pdf, fcnc::bu2kstarmumu_parameters **theParams){
  653. std::ofstream myFile;
  654. open_Latex_noteFile(latex_params(), myFile); //open file with parameters
  655. for(unsigned int b = 0; b < nBins; b++){
  656. myFile << "\\captionof{table}{PDF " << n_pdf<< " bin " << b<< "}" << std::endl;
  657. theParams[b]->print_parameters(true);
  658. }
  659. return;
  660. }
  661. void print_fit_results(unsigned int nBins,std::vector<Int_t> fitresults){
  662. spdlog::info("==========================================");
  663. spdlog::info("|| FIT RESULTS ||");
  664. spdlog::info("==========================================");
  665. if(spdlog_info()){
  666. spdlog::info("|| BIN\t\tfit result ||");
  667. for(UInt_t b = 0; b < nBins; b++){
  668. spdlog::info("|| {0:d}\t\t{1:d}\t||", b, fitresults.at(b));
  669. }
  670. }
  671. return;
  672. }
  673. void print_fit_results(unsigned int nBins, std::vector<UInt_t> pdf_idx, std::vector<Int_t> fitresults[], bool simFit){
  674. spdlog::info("==========================================");
  675. spdlog::info("|| FIT RESULTS ||");
  676. spdlog::info("==========================================");
  677. if(spdlog_info()){
  678. spdlog::info("|| BIN\t\tPDF\t\tfit result ||");
  679. for(UInt_t b = 0; b < nBins; b++){
  680. if(!simFit){
  681. for_indexed(auto idx: pdf_idx){
  682. spdlog::info("|| {0:d}\t\t{1:d}\t\t{2:d} \t||\n", b, idx, fitresults[b].at(i));
  683. }
  684. }
  685. else{
  686. spdlog::info("|| {0:d}\t\t All PDFs\t\t{1:d} \t||\n", b, fitresults[b].at(0)); //TODO
  687. }
  688. }
  689. }
  690. return;
  691. }
  692. void print_sig_yields(unsigned int nBins, std::vector<UInt_t> pdf_idx,
  693. std::vector<UInt_t> *evts_cntr, std::vector<double> *f_sigs, std::vector<double> *f_sigserr){
  694. spdlog::info("");
  695. spdlog::info("==========================================");
  696. spdlog::info("|| SIGNAL YIELDS ||");
  697. spdlog::info("==========================================");
  698. spdlog::info("|| BIN\t\tPDF\tsignal yield ||");
  699. for(unsigned int b = 0; b < nBins; b++){
  700. for(UInt_t i = 0; i < pdf_idx.size(); i++){
  701. 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));
  702. }
  703. }
  704. spdlog::info("");
  705. }
  706. void print_bkg_yields(unsigned int nBins, std::vector<UInt_t> pdf_idx,
  707. std::vector<UInt_t> *evts_cntr, std::vector<double> *f_sigs, std::vector<double> *f_sigserr){
  708. spdlog::info("");
  709. spdlog::info("==========================================");
  710. spdlog::info("|| BACKGROUND YIELDS ||");
  711. spdlog::info("==========================================");
  712. spdlog::info("|| BIN\t\tPDF\tbkg yield ||");
  713. for(unsigned int b = 0; b < nBins; b++){
  714. for(UInt_t i = 0; i < pdf_idx.size(); i++){
  715. 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));
  716. }
  717. }
  718. spdlog::info("");
  719. }
  720. void print_bkgOnly_yields(unsigned int nBins, std::vector<UInt_t> pdf_idx,
  721. std::vector<fcnc::bu2kstarmumu_parameters*> theParams[],
  722. std::vector<double> bkg_int_full_range[], std::vector<UInt_t> *evts_cntr){
  723. spdlog::info("");
  724. spdlog::info("==========================================");
  725. spdlog::info("|| BACKGROUND YIELDS ||");
  726. spdlog::info("==========================================");
  727. spdlog::info("|| BIN\t\tPDF\tbkg yield ||");
  728. for(unsigned int b = 0; b < nBins; b++){
  729. for(UInt_t i = 0; i < pdf_idx.size(); i++){
  730. spdlog::info("[BIN{0:d}]\tBckgnd est.: {1:.4f}\tBkg prob: {2:.4f}\tBkg iac: {3:.4f}\tExpCoeff: {4:.4f}",
  731. i,
  732. evts_cntr[b].at(i) * bkg_int_full_range[i].at(b) * (1 - theParams[b].at(i)->f_sig.get_value()),
  733. bkg_int_full_range[b].at(i),
  734. 1 - theParams[b].at(i)->f_sig.get_value(),
  735. theParams[b].at(i)->m_lambda.get_value());
  736. }
  737. }
  738. spdlog::info("");
  739. }
  740. void print_sig_yields_tex(std::string texFiletag, unsigned int nBins, std::vector<UInt_t> pdf_idx,
  741. fcnc::options *theOptions,
  742. std::vector<UInt_t> *evts_cntr, std::vector<double> *f_sigs, std::vector<double> *f_sigserr){
  743. //Open texFile
  744. std::ofstream myFile;
  745. open_Latex_noteFile(texFiletag, myFile);
  746. double yield[nBins], yielderr[nBins];
  747. myFile << "\\begin{tabular}{|l|"; //TODO: have a function for this
  748. for(UInt_t i = 0; i < pdf_idx.size(); i++) myFile << "r";
  749. myFile << "|r|}\\hline" << std::endl;
  750. myFile << "\\qsq bin";
  751. for(UInt_t i = 0; i < pdf_idx.size(); i++){
  752. myFile << "\t& Run" << theOptions[i].run;
  753. }
  754. myFile << "\\\\" << std::endl;
  755. myFile << "\\hline\\hline" << std::endl;
  756. for(unsigned int b = 0; b < nBins; b++){
  757. myFile << b << "\t&";
  758. yield[b] = 0.0; yielderr[b] = 0.0;
  759. for(UInt_t i = 0; i < pdf_idx.size(); i++){
  760. 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&";
  761. yield[b] += evts_cntr[b].at(i)*f_sigs[b].at(i);
  762. yielderr[b] += evts_cntr[b].at(i)*f_sigserr[b].at(i)*evts_cntr[b].at(i)*f_sigserr[b].at(i);
  763. }
  764. myFile << "$" << yield[b] << "\\pm" << TMath::Sqrt(yielderr[b]) << "$\\\\" << std::endl;
  765. }
  766. myFile << "\\hline\\end{tabular}" << std::endl << std::endl << std::endl << std::endl;
  767. myFile << "\\begin{tabular}{|l|r|}\\hline" << std::endl;
  768. myFile << "\\qsq bin \t& signal yield\\\\" << std::endl;
  769. myFile << "\\hline\\hline" << std::endl;
  770. for(unsigned int b = 0; b < nBins; b++) myFile << b << "\t& $" << yield[b] << "\\pm" << TMath::Sqrt(yielderr[b]) << "$\\\\" << std::endl;
  771. myFile << "\\hline\\end{tabular}" << std::endl << std::endl;
  772. myFile.close();
  773. }
  774. 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){
  775. //Open the root file
  776. spdlog::info("[SAVE]\t\tSaving result values to file " + results_file);
  777. TFile* fout = new TFile(results_file.c_str(), "RECREATE");
  778. fout->cd();
  779. int param_index = 0;
  780. //loop over parameters:
  781. for(UInt_t p = 0; p < theParams[0].at(0)->nparameters(); p++){
  782. fcnc::parameter* param = theParams[0].at(0)->get_parameter(p);
  783. //if(param->get_step_size() == 0.0) continue; //skip fixed parameters
  784. std::string parname(param->get_name());
  785. std::string pardesc(param->get_description());
  786. spdlog::trace("Creating new TTree for parameter:" + parname);
  787. TTree* t = new TTree(parname.c_str(), pardesc.c_str());
  788. int pdf = DEFAULT_TREE_INT;
  789. int bin = DEFAULT_TREE_INT;
  790. int migrad = DEFAULT_TREE_INT;
  791. int status_cov = DEFAULT_TREE_INT;
  792. int totBins = DEFAULT_TREE_INT;
  793. double q2a = DEFAULT_TREE_VAL;
  794. double q2b = DEFAULT_TREE_VAL;
  795. double value = DEFAULT_TREE_VAL;
  796. double error = DEFAULT_TREE_ERR;
  797. double error_up = DEFAULT_TREE_ERR;
  798. double error_down = DEFAULT_TREE_ERR;
  799. double start_value = DEFAULT_TREE_VAL;
  800. double prev_value = DEFAULT_TREE_VAL;
  801. double prev_error = DEFAULT_TREE_ERR;
  802. const unsigned int corr_max = param->correlations.size();
  803. double tmp_corr[corr_max];
  804. t->Branch("pdf",&pdf,"pdf/I");
  805. t->Branch("bin",&bin,"bin/I");
  806. t->Branch("totBins",&totBins,"totBins/I");
  807. t->Branch("migrad",&migrad,"migrad/I");
  808. t->Branch("status_cov",&status_cov,"status_cov/I");
  809. t->Branch("value",&value,"value/D");
  810. t->Branch("q2min",&q2a,"q2min/D");
  811. t->Branch("q2max",&q2b,"q2max/D");
  812. t->Branch("error",&error,"error/D");
  813. t->Branch("error_up",&error_up,"error_up/D");
  814. t->Branch("error_down",&error_down,"error_down/D");
  815. t->Branch("start_value",&start_value,"start_value/D");
  816. t->Branch("prev_value",&prev_value,"prev_value/D");
  817. t->Branch("prev_error",&prev_error,"prev_error/D");
  818. t->Branch("index",&param_index, "index/I");
  819. t->Branch("correlations",&tmp_corr,("correlations["+std::to_string(corr_max)+"]/D").c_str());
  820. //loop over PDFs
  821. for_indexed(auto n_pdf: pdf_idx){
  822. for(unsigned int b = 0; b < nBins; b++){
  823. fcnc::parameter* par = par_with_correct_name(p, parname, theParams[b].at(i));
  824. if (par == NULL) break;
  825. totBins = nBins;
  826. bin = b;
  827. pdf = n_pdf;
  828. migrad = fit_results[b].at(simFit ? 0 : i) % 100;
  829. status_cov = fit_results[b].at(simFit ? 0 : i) / 100;
  830. q2a = opts->TheQ2binsmin[b];
  831. q2b = opts->TheQ2binsmax[b];
  832. value = par->get_value();
  833. error = par->get_error();
  834. error_up = par->get_error_up();
  835. error_down = par->get_error_down();
  836. if (opts->minos_errors){
  837. if (error_up==0.0 && value < par->get_max()) error_up = par->get_max() - value;
  838. if (error_down==0.0 && value > par->get_min()) error_down = par->get_min() - value;//needs to be negative
  839. }
  840. start_value = par->get_start_value();
  841. prev_value = par->get_previous_measurement();
  842. prev_error = par->get_previous_error();
  843. for (unsigned int l = 0; l < corr_max; l++) tmp_corr[l] = 0.0; //Fill with zeroes
  844. for (unsigned int l = 0; l < par->correlations.size(); l++){
  845. tmp_corr[l] = par->correlations.at(l);
  846. }
  847. t->Fill();
  848. }
  849. } //end loop over pdfs
  850. //Write the parameter tree
  851. t->Write();
  852. delete t;
  853. param_index++;
  854. }
  855. //Close the root file
  856. spdlog::info("Finished saving the parameters into the file {0:s}.",fout->GetName());
  857. fout->Close();
  858. delete fout;
  859. //Delete the tex file with parameters
  860. clear_Latex_noteFile(latex_params());
  861. //Copy the parameter in TeX format into the same place as the final results file
  862. tex_all_parameters(nBins,pdf_idx,theParams);
  863. replace(results_file,".root",".tex");
  864. copyFile(get_Latex_noteFile(latex_params()),results_file);
  865. return 0;
  866. }
  867. 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){
  868. //Open the root file
  869. spdlog::info("[SAVE]\t\tSaving result values to file " + results_file);
  870. TFile* fout = new TFile(results_file.c_str(), "RECREATE");
  871. fout->cd();
  872. int param_index = 0;
  873. //loop over parameters:
  874. for(UInt_t p = 0; p < theParams[0]->nparameters(); p++){
  875. fcnc::parameter* param = theParams[0]->get_parameter(p);
  876. //if(param->get_step_size() == 0.0) continue; //skip fixed parameters
  877. std::string parname(param->get_name());
  878. std::string pardesc(param->get_description());
  879. spdlog::trace("Creating new TTree for parameter:" + parname);
  880. TTree* t = new TTree(parname.c_str(), pardesc.c_str());
  881. int pdf = DEFAULT_TREE_INT;
  882. int bin = DEFAULT_TREE_INT;
  883. int migrad = DEFAULT_TREE_INT;
  884. int status_cov = DEFAULT_TREE_INT;
  885. int totBins = DEFAULT_TREE_INT;
  886. double q2a = DEFAULT_TREE_VAL;
  887. double q2b = DEFAULT_TREE_VAL;
  888. double value = DEFAULT_TREE_VAL;
  889. double error = DEFAULT_TREE_ERR;
  890. double error_up = DEFAULT_TREE_ERR;
  891. double error_down = DEFAULT_TREE_ERR;
  892. double start_value = DEFAULT_TREE_VAL;
  893. double prev_value = DEFAULT_TREE_VAL;
  894. double prev_error = DEFAULT_TREE_ERR;
  895. const unsigned int corr_max = param->correlations.size();
  896. double tmp_corr[corr_max];
  897. t->Branch("pdf",&pdf,"pdf/I");
  898. t->Branch("bin",&bin,"bin/I");
  899. t->Branch("totBins",&totBins,"totBins/I");
  900. t->Branch("migrad",&migrad,"migrad/I");
  901. t->Branch("status_cov",&status_cov,"status_cov/I");
  902. t->Branch("value",&value,"value/D");
  903. t->Branch("q2min",&q2a,"q2min/D");
  904. t->Branch("q2max",&q2b,"q2max/D");
  905. t->Branch("error",&error,"error/D");
  906. t->Branch("error_up",&error_up,"error_up/D");
  907. t->Branch("error_down",&error_down,"error_down/D");
  908. t->Branch("start_value",&start_value,"start_value/D");
  909. t->Branch("prev_value",&prev_value,"prev_value/D");
  910. t->Branch("prev_error",&prev_error,"prev_error/D");
  911. t->Branch("index",&param_index, "index/I");
  912. t->Branch("correlations",&tmp_corr,("correlations["+std::to_string(corr_max)+"]/D").c_str());
  913. //loop over nBins
  914. for(unsigned int b = 0; b < nBins; b++){
  915. fcnc::parameter* par = par_with_correct_name(p, parname, theParams[b]);
  916. if (par == NULL) break;
  917. totBins = nBins;
  918. bin = b;
  919. pdf = n_pdf;
  920. migrad = fit_results[b] % 100;
  921. status_cov = fit_results[b] / 100;
  922. q2a = opts->TheQ2binsmin[b];
  923. q2b = opts->TheQ2binsmax[b];
  924. value = par->get_value();
  925. error = par->get_error();
  926. error_up = par->get_error_up();
  927. error_down = par->get_error_down();
  928. if (opts->minos_errors){
  929. if (error_up==0.0 && value < par->get_max()) error_up = par->get_max() - value;
  930. if (error_down==0.0 && value > par->get_min()) error_down = par->get_min() - value;//needs to be negative
  931. }
  932. start_value = par->get_start_value();
  933. prev_value = par->get_previous_measurement();
  934. prev_error = par->get_previous_error();
  935. for (unsigned int l = 0; l < corr_max; l++) tmp_corr[l] = 0.0; //Fill with zeroes
  936. for (unsigned int l = 0; l < par->correlations.size(); l++){
  937. tmp_corr[l] = par->correlations.at(l);
  938. }
  939. t->Fill();
  940. }
  941. //Write the parameter tree
  942. t->Write();
  943. delete t;
  944. param_index++;
  945. } //End loop over names
  946. //Close the root file
  947. spdlog::info("Finished saving the parameters into the file {0:s}.",fout->GetName());
  948. fout->Close();
  949. //Delete the tex file with parameters
  950. clear_Latex_noteFile(latex_params());
  951. //Copy the parameter in TeX format into the same place as the final results file
  952. tex_all_parameters(nBins,n_pdf,theParams);
  953. replace(results_file,".root",".tex");
  954. copyFile(get_Latex_noteFile(latex_params()),results_file);
  955. delete fout;
  956. return 0;
  957. }
  958. //--------------------------------------//
  959. // Helpers for writting latex stuff //
  960. //--------------------------------------//
  961. int clear_Latex_noteFile(std::string tag){
  962. 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
  963. else spdlog::trace( "Latex noteFile successfully deleted" );
  964. return 0;
  965. }
  966. int open_Latex_noteFile(std::string tag, std::ofstream &myfile){
  967. //This is not working cause this thing is for whatever efin reason stuck with gcc 4.
  968. myfile.open (get_Latex_noteFile(tag), std::ios::out | std::ios::app);
  969. if (!myfile.is_open()){
  970. spdlog::error("Latex noteFile" + get_Latex_noteFile(tag) + " is not opened.");
  971. return 404;
  972. }
  973. else{
  974. spdlog::trace("Latex noteFile successfully deleted");
  975. return 0;
  976. }
  977. }
  978. //--------------------------------------//
  979. // Helpers for reading the parameters //
  980. //--------------------------------------//
  981. //Checks if the observable is in the TFile
  982. //If required Fl and there is S1s, it returns 11, ...
  983. //Modulo 10 then returns whether the observable actually exists
  984. //Example usage: if (try_getObservable(paramName, file)%10==0) assert(0)
  985. int try_getObservable(std::string observable, TFile* file){
  986. if (!file->GetListOfKeys()->Contains(observable.c_str())){
  987. //Also check if Fl<->S1s and A_FB<->S6s is available
  988. if (observable == "Fl") return 10+try_getObservable("S1s",file);
  989. if (observable == "S1s") return 20+try_getObservable("Fl",file);
  990. if (observable == "Afb") return 30+try_getObservable("S6s",file);
  991. if (observable == "S6s") return 40+try_getObservable("Afb",file);
  992. return 0;
  993. }
  994. else return 1;
  995. }
  996. std::vector<double> load_param_values_into_vector(std::string paramName, std::string fileName){
  997. //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
  998. //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
  999. //Create the vector that will be returned
  1000. std::vector<double> output;
  1001. //Open file
  1002. spdlog::info("Opening " + fileName);
  1003. TFile* file = new TFile(fileName.c_str(), "READ");
  1004. int isFoundFlag = try_getObservable(paramName, file);
  1005. if (!(isFoundFlag%10)){
  1006. spdlog::critical("Wrong tree name " + paramName + "! Returning an empty vector!");
  1007. //It should not crash here as it might be desired to init some observables but not use them
  1008. return {};
  1009. }
  1010. else{
  1011. switch(isFoundFlag){
  1012. case 11: //Need Fl, have S1s
  1013. paramName = "S1s";
  1014. break;
  1015. case 21: //Need S1s, have FL
  1016. paramName = "Fl";
  1017. break;
  1018. case 31: //Need Afb, have S6s
  1019. paramName = "S6s";
  1020. break;
  1021. case 41: //Need S6s, have Afb
  1022. paramName = "Afb";
  1023. break;
  1024. }
  1025. //case 1: all good, move one
  1026. }
  1027. //Get the tree
  1028. TTree* tree = (TTree*)file->Get(paramName.c_str());
  1029. //Activate only needed branches
  1030. tree->SetBranchStatus("*",0);
  1031. tree->SetBranchStatus("value",1);
  1032. double value = DEFAULT_TREE_VAL;
  1033. tree->SetBranchAddress("value", &value);
  1034. //Loop over nBins that are saved in the tree
  1035. for (int b = 0; b < tree->GetEntries(); b++){
  1036. tree->GetEntry(b);
  1037. //There are not many bins so just do a switch and fill accordingly
  1038. switch(isFoundFlag){
  1039. case 1:
  1040. output.push_back(value);
  1041. case 11: //Need Fl, have S1s
  1042. output.push_back(1-4.0/3.0*value);
  1043. break;
  1044. case 21: //Need S1s, have FL
  1045. output.push_back(3.0/4.0*(1-value));
  1046. break;
  1047. case 31: //Need Afb, have S6s
  1048. output.push_back(3.0/4.0*value);
  1049. break;
  1050. case 41: //Need S6s, have Afb
  1051. output.push_back(4.0/3.0*value);
  1052. break;
  1053. }
  1054. }
  1055. spdlog::debug(convert_vector_to_string(output));
  1056. return output;
  1057. }