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.

412 lines
15 KiB

  1. /**
  2. * @file bu2kstarmumu.cc
  3. * @author Christoph Langenbruch, David Gerick, Renata Kopecna
  4. * @date 2020-30-11
  5. *
  6. * Main control file for the Bu -> K*+mumu analysis
  7. */
  8. #include <sys/stat.h>
  9. #include <iostream>
  10. #include <fstream>
  11. #include <sstream>
  12. #include <cstdio>
  13. //Yes, I know that <> is not ideal for compilation time,
  14. //but I was lazy to always put the correct path there at the begining
  15. //when files were moved around rather often
  16. #include <parameters.hh>
  17. #include <parse.hh>
  18. #include <toystudy.hh>
  19. #include <angularcorr.hh>
  20. #include <massfit.hh>
  21. #include <mainfit.hh>
  22. #include <backgroundfit.hh>
  23. #include <mcfit.hh>
  24. #include <momfit.hh>
  25. #include <genlvlfit.hh>
  26. #include <toysfit.hh>
  27. #include <help.hh>
  28. #include <constants.hh>
  29. #include <generatetoys.hh>
  30. #include <helpers.hh>
  31. #include <event.hh>
  32. #include <design.hh>
  33. #include <paths.hh>
  34. #include "sources/Scripts/RunningScripts.hh"
  35. #include <TROOT.h>
  36. #include <colors.hh>
  37. int main ( int argc, char *argv[] )
  38. {
  39. //Set gROOT and gStyle
  40. gROOT->SetStyle("Plain");
  41. set_gStyle();
  42. //Initiliaze pretty colors
  43. myColorScheme::init();
  44. //gStyle->SetPaintTextFormat("4.1f m");
  45. //gStyle->SetCanvasPreferGL(true);
  46. ///set the fitting options
  47. fcnc::options opts;
  48. opts = fcnc::options("-1");
  49. //how many events should be taken per Test/ToyFit?
  50. UInt_t nMCEvents = 350;
  51. //Retun errors:
  52. //1: wrong options
  53. //5: Inexplicable stuff
  54. //404: not found
  55. basic_params pars = basic_params();
  56. basic_actions acts = basic_actions();
  57. //The pars and acts are a bit wonky at the moment, hopefully as I progress this will get better
  58. if (parseOpts(argc, argv, pars, acts, nMCEvents) == 1) return 1;
  59. if (checkOpts(pars,acts) == 1) return 1;
  60. //Set opts.folding according to the parsed options
  61. //default should be -1
  62. opts.folding = pars.folding;
  63. ////////////////////////////////////////////
  64. // [START] GLOBAL OPTIONS
  65. ////////////////////////////////////////////
  66. //Use only DTF, could be removed
  67. opts.DTF = true;
  68. //SET OUTPUT DESIGN
  69. reset_spdlog();
  70. set_spdlog_level(pars.verbosity);
  71. //Make ROOT shut up
  72. gStyle -> SetOptStat(0);
  73. gROOT->SetBatch(kTRUE);
  74. gErrorIgnoreLevel = kWarning;
  75. //gErrorIgnoreLevel = kError;
  76. opts.ncores = NCORES;
  77. if(opts.ncores > 1) spdlog::info("[CPU]\tUse parallelisation on {0:d} CPU cores", opts.ncores);
  78. //FIXED to true, since we have flatQ2 phase-space MC
  79. opts.IsFlatQ2 = true;
  80. //get individual angular acceptance corrections for every year
  81. opts.angacccorrperyear = false;
  82. //Decide in what format everything should be saved in
  83. opts.write_eps = true;
  84. opts.write_C = false;
  85. opts.write_jpg = false;
  86. opts.write_pdf = true;
  87. //Set the default path for plots_folder, somehow it doesn't want to accept PLOTS_PATH in the options constructor, possibly fix TODO
  88. opts.plot_folder = PLOTS_PATH;
  89. //fit pdfs over complete phi range [-pi, +pi]
  90. opts.full_angular = opts.folding == -1;
  91. //use a two tailed CrystalBall function instead of a Gaussian
  92. opts.twotailedcrystalball = DOUBLE_CB;
  93. opts.crystalball = !DOUBLE_CB;
  94. //No exponential, but flat background model
  95. opts.flat_bkg = false;
  96. //////////////////////////
  97. // HARDCODED FUNCTIONS: //
  98. //////////////////////////
  99. //default is NOT Kshort channel:
  100. opts.KS = false;
  101. //Set 'globally' fl and afb to (not) be used
  102. opts.fit_fl = true;
  103. opts.fit_afb = true;
  104. //Set 'globaly' to use lambda in the background fit
  105. //fit exponential with exp(-lambda*x) instead of exp(-x/tau), it has better precision
  106. opts.fit_lambda = true;
  107. //Assymetries to be included in the fit itself
  108. opts.fit_asymmetries = false; //you don't have enough stats for this to be true
  109. /////////////////////////////////////
  110. // Set the order of the polynomial //
  111. /////////////////////////////////////
  112. opts.bkg_order_costhetal = 2; //TODO: put as a const into constants.cc and modify it accordingly in options.cc
  113. opts.bkg_order_costhetak = 5;
  114. ////////////////////////
  115. // ANGULAR RESOLUTION //
  116. ////////////////////////
  117. //Set the order of legendre polynomial
  118. opts.eff_order_costhetal = ORDER_COSTHETAL;
  119. opts.eff_order_costhetak = ORDER_COSTHETAK;
  120. opts.eff_order_phi = ORDER_PHI;
  121. opts.eff_order_q2 = ORDER_Q2;
  122. std::vector<std::vector<double>> resolution = get_resolution();
  123. //Have angular correction per each Run (false)
  124. opts.angacccorrbothruns = false;
  125. //Don't use angular acceptance convoluted in the likelihood (false)
  126. opts.use_angular_acc = false;
  127. ////////////////////////////////////////////
  128. // GLOBAL OPTIONS //
  129. ////////////////////////////////////////////
  130. //TODO fix this (actually nice, but can be done elsewhere)
  131. //maximum range of considered B mass:
  132. opts.m_low = B_MASS_LOW;
  133. opts.m_high = B_MASS_HIGH;
  134. //signal window of B mass:
  135. opts.m_min = PDGMASS_B-B_MASS_TIGHT_WINDOW;
  136. opts.m_max = PDGMASS_B+B_MASS_TIGHT_WINDOW;
  137. //If MC, use MC weights//TODO: check for data
  138. opts.multiply_eff = pars.dataset >0;
  139. //TODO move to paths
  140. std::string angularsuffix = opts.full_angular ? "full_angular" : "folding"+std::to_string(opts.folding);
  141. //generate vector with years for every run option, including just one year
  142. std::vector<Int_t>years = (pars.Run == 0 ? std::vector<Int_t>{pars.year} : get_years(pars.Run, pars.dataset==1, pars.dataset==2));
  143. spdlog::debug("Using years: " + convert_vector_to_string(years));
  144. //---------------------------------------------
  145. // Put stuff from pars and acts into opts
  146. //---------------------------------------------
  147. //yes it is dumb but I cannot be bothered to change the whole options
  148. opts.verbose = pars.verbosity;
  149. opts.run = pars.Run; //This is not ideal when fitting per year,
  150. //From now on passing the pars as well
  151. opts.useMC = pars.dataset > 0;
  152. opts.fit_pprimes = pars.usePprime;
  153. //-------------------------------
  154. // Get corresponding Q2 bins
  155. //-------------------------------
  156. if (pars.reference) pars.nBins = 1; //For reference, always use 1 bin
  157. opts.TheQ2binsmin = get_TheQ2binsmin(pars.nBins, pars.reference);
  158. opts.TheQ2binsmax = get_TheQ2binsmax(pars.nBins, pars.reference);
  159. spdlog::debug("Using {0:d} q2 bins.", opts.TheQ2binsmax.size());
  160. if (spdlog::default_logger_raw()->level()==spdlog::level::info){
  161. spdlog::info("Using the following binning scheme:");
  162. for(UInt_t b = 0; b < opts.TheQ2binsmin.size(); b++){
  163. assert(opts.TheQ2binsmin.at(b) != 0.0);
  164. assert(opts.TheQ2binsmax.at(b) != 0.0);
  165. assert(opts.TheQ2binsmin.at(b) < opts.TheQ2binsmax.at(b));
  166. std::cout << std::fixed << std::setprecision(2) << "\tbin" << b+1 << ": [" << opts.TheQ2binsmin.at(b) << "-" << opts.TheQ2binsmax.at(b) << "] GeV^2/c^4" << std::endl;
  167. }
  168. }
  169. //-------------------------------
  170. // Set ranges of the angles
  171. //-------------------------------
  172. //Not ideal to have it as an opts and as a constant, but this is how it is going to be now
  173. opts.reset_angle_ranges();
  174. //The ranges might change in the folding, hence I will keep the opts.angle_min/max for this case
  175. //Check if something is wrong; if any task is assigned, raise this flag
  176. bool isItDoingAnything_flag = false;
  177. int returnCode = 0;
  178. //-------------------------------
  179. // create branches for FCNCfitter
  180. //-------------------------------
  181. if(acts.convert){ //these booleans are only for running, used only here
  182. //maybe put it into a new class //TODO
  183. isItDoingAnything_flag = true;
  184. return convert_tuples(pars.dataset, get_theFCNCpath(pars.dataset, opts.run), opts,years);
  185. }
  186. //-------------------------------
  187. // scan angular acceptance max. order of legendre
  188. //-------------------------------
  189. if(acts.angCorrScan){
  190. isItDoingAnything_flag = true;
  191. bool quickTest = false;
  192. bool test_4times1D = false;
  193. bool checkSignificance = false;
  194. bool runMinuit = false;
  195. bool checkFactorization = false;
  196. bool do3Dmoments = false;
  197. const bool assumePhiEven = IS_PHI_EVEN;
  198. spdlog::debug("Scanning angular acceptance corrections...");
  199. returnCode = scan_max_order_angular_ccorrection(opts, assumePhiEven, quickTest, test_4times1D,
  200. checkSignificance, runMinuit, checkFactorization, do3Dmoments);
  201. if (returnCode!=0) return returnCode;
  202. }
  203. //-------------------------------
  204. // fit angular acceptance
  205. //-------------------------------
  206. if (acts.angCorr){
  207. if (pars.testInt > -1) sanityCheck_MC(opts);
  208. else{
  209. isItDoingAnything_flag = true;
  210. bool testSaving = false;
  211. spdlog::debug("Calculating angular acceptance correction parameters...");
  212. returnCode = get_angular_acceptance(opts, testSaving);
  213. if (returnCode!=0) return returnCode;
  214. }
  215. }
  216. //--------------------------------
  217. // FIT MASS
  218. //--------------------------------
  219. if(acts.fitType == 2){
  220. isItDoingAnything_flag = true;
  221. bool splitRuns = true;
  222. massfit(opts, pars.reference, splitRuns, pars);
  223. }
  224. //--------------------------------
  225. // MC FIT
  226. //--------------------------------
  227. if(acts.fitType == 4){
  228. isItDoingAnything_flag = true;
  229. opts.only_angles = false;//(nBins == 8); //Do not fit the mass, just angles //Apply only when fitting B0 binning
  230. //Reference MC is broken (K* is PHSP), so when fitting the reference, fit only mass
  231. opts.only_Bmass = pars.reference; //Do not fit the angles, just mass
  232. opts.initSM = !pars.reference; //Set to true only for reference
  233. returnCode = mcfit_4D(opts, pars.reference, pars.dataset==3, pars);
  234. //yes, fitRef could be included in params, but I like to keep my options open :)
  235. if (returnCode!=0) return returnCode;
  236. }
  237. //--------------------------------
  238. // COMPLETE FIT
  239. //--------------------------------
  240. if(acts.fitType == 1){
  241. isItDoingAnything_flag = true;
  242. bool fitToy = pars.testInt > -1; //If test, then do fit toys
  243. if (pars.folding == 5){ //We do not need this here, we can run the code 5 times, no?
  244. for (int f = 0; f < 5; f++){
  245. pars.folding = f;
  246. opts.folding = f;
  247. spdlog::debug("Fitting with folding={0:d}", pars.folding);
  248. mainfit(opts, pars, pars.reference, fitToy, pars.likelyhood, pars.FeldCous);
  249. }
  250. }
  251. else {
  252. mainfit(opts, pars, pars.reference, fitToy, pars.likelyhood, pars.FeldCous);
  253. }
  254. }
  255. //--------------------------------
  256. // BACKGROUND ONLY FIT
  257. //--------------------------------
  258. if(acts.fitType == 0){
  259. isItDoingAnything_flag = true;
  260. //Clear the bkgFit file
  261. clear_Latex_noteFile("_bkgFit");
  262. //Set options
  263. //One can also fit only upper/lower mass sideband, to set this use -index
  264. bool LowMassFit = (pars.index == 1);
  265. bool HighMassFit = (pars.index == 2);
  266. bool Use2DAngularBins = false;
  267. bool fitKpiMass = true;
  268. //Run the background only fit
  269. int bkgfit = 0;
  270. if (pars.folding == 5){ //We do not need this here, we can run the code 5 times, no?
  271. for (int f = 0; f < 5; f++){
  272. pars.folding = f;
  273. opts.folding = f;
  274. bkgfit =+ backgroundfit(opts, pars.reference,
  275. LowMassFit, HighMassFit, fitKpiMass,
  276. Use2DAngularBins, pars);
  277. }
  278. }
  279. else bkgfit = backgroundfit(opts, pars.reference,
  280. LowMassFit, HighMassFit, fitKpiMass,
  281. Use2DAngularBins, pars);
  282. if (bkgfit != 0) return bkgfit;
  283. }
  284. //--------------------------------
  285. // start GENERATOR LEVEL MC FIT
  286. //--------------------------------
  287. if(acts.fitType == 5){
  288. isItDoingAnything_flag = true;
  289. opts.initSM = pars.nBins != 8; //SM for 8 bins not implemented
  290. genlvlfit(opts, pars.dataset==4, pars);
  291. }
  292. //--------------------------------
  293. // method of moment fit
  294. //--------------------------------
  295. //TODO
  296. if(acts.fitType == 3){
  297. isItDoingAnything_flag = true;
  298. bool blind = true;
  299. bool Fit2bins = false, Fit1bin = false, FitAllbins = false; //TODO: remove
  300. momfit(opts, pars.nBins==0, pars.dataset==1, pars.dataset==0, blind,
  301. Fit1bin, Fit2bins, FitAllbins);
  302. }
  303. //--------------------------------
  304. // BEGIN angular resolution
  305. //--------------------------------
  306. if(acts.angRes){
  307. isItDoingAnything_flag = true;
  308. get_angular_resolution(opts, get_years(opts.run, true, false));
  309. }
  310. //-------------------------------
  311. // generate Toy events
  312. //-------------------------------
  313. if (acts.genToys){
  314. isItDoingAnything_flag = true;
  315. spdlog::debug("Generating and fitting toys");
  316. bool onlySig = true;
  317. bool onlyBkg = false;
  318. if (pars.folding == 5){ //We do not need this here, we can run the code 5 times, no?
  319. for (int f = 0; f < 5; f++){
  320. pars.folding = f;
  321. opts.folding = f;
  322. spdlog::debug("Generating and fitting a toy sample with folding={0:d}", pars.folding);
  323. toysfit(opts, pars.nBins, pars.reference, pars, onlySig, onlyBkg);
  324. }
  325. }
  326. else {
  327. if (pars.testInt > -1)saveToys(pars, opts, pars.dataset>0, false); //if MC generate without bkg
  328. else{
  329. if(pars.folding != -1)spdlog::debug("Generating and fitting a toy sample with folding={0:d}", pars.folding);
  330. toysfit(opts, pars.nBins, pars.reference, pars, onlySig, onlyBkg);
  331. }
  332. }
  333. }
  334. //-------------------------------------------
  335. // Run whatever script you decide to run
  336. //-------------------------------------------
  337. //Yes, this is tedious, but I don't want to hardcode everything just so root is happy
  338. //nor I wanna compile everything, so here we are
  339. if(acts.script){
  340. isItDoingAnything_flag = true;
  341. int status = runWhatever(pars, acts); //FILL IN RunningScripts.cc BY HAND
  342. if(status)return status;
  343. }
  344. if (!isItDoingAnything_flag) spdlog::warn("Nothing to do! Exitting.");
  345. else spdlog::info("Done with everything. Exit.");
  346. return 0;
  347. }