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.

414 lines
18 KiB

  1. //Renata Kopecna
  2. #include <massfit.hh>
  3. #include <event.hh>
  4. #include <fitter.hh>
  5. #include <bu2kstarmumu_plotter.hh>
  6. #include <paths.hh>
  7. #include <design.hh>
  8. #include <helpers.hh>
  9. #include <fstream>
  10. #include <spdlog.h>
  11. #include <TROOT.h>
  12. #include <TStyle.h>
  13. //Fitter part that fits only the mass of DATA
  14. bool checkForCommonValues(std::vector<std::string> vec_one,std::vector<std::string> vec_two){
  15. for (auto key: vec_one){
  16. if (std::find(vec_two.begin(), vec_two.end(), key)!= vec_two.end()){
  17. spdlog::warn("Parameter " + key + " is shared between two vectors!");
  18. return true;
  19. }
  20. }
  21. return false;
  22. }
  23. int massfit(fcnc::options opts, bool fitReference, bool splitRuns, basic_params pars){
  24. //splitRuns = true means one gets a simFit of Run 1 and Run 2
  25. //splitRuns = false means Run 1 and Run 2 are fit together
  26. const bool fitKstarMass = true;
  27. bool Blind = false;//!fitReference; //If signal channel, blind to be sure
  28. const unsigned int nBins = opts.get_nQ2bins(); //unsigned because vector.size is unsigned
  29. bool constrainMassFromMC = false; //Use mass fit of MC to constrain mass parameters?
  30. bool constrainMassFromRefMC = true;//Use mass fit of *RefMC* to constrain mass parameters?
  31. bool constrainMassFromData = !fitReference; //Use the mass fit of data Reference to constrain the parameters?
  32. bool fixBMass = !fitReference; //Fix the B mass to PDG?
  33. //Set the parameters that should be constrained
  34. std::vector<std::string> toBeConstrainedMC = {};
  35. std::vector<std::string> toBeFixedMC = {};
  36. std::vector<std::string> toBeConstrainedRefMC = {};
  37. std::vector<std::string> toBeFixedRefMC = {"alpha_1","alpha_2","n_1","n_2"};
  38. std::vector<std::string> toBeConstrainedRefData = {};
  39. std::vector<std::string> toBeFixedRefData = {"m_b","m_sigma_1"};
  40. //Sanity check one doesn't constrain one thing to two different values
  41. if (constrainMassFromMC && constrainMassFromRefMC){
  42. if (checkForCommonValues(toBeConstrainedMC, toBeConstrainedRefMC)){
  43. spdlog::warn("Fix your options, aborting now!");
  44. return 2;
  45. }
  46. if (checkForCommonValues(toBeFixedMC, toBeFixedRefMC)){
  47. spdlog::warn("Fix your options, aborting now!");
  48. return 2;
  49. }
  50. }
  51. if (constrainMassFromMC && constrainMassFromData){
  52. if (checkForCommonValues(toBeConstrainedMC, toBeConstrainedRefData)){
  53. spdlog::warn("Fix your options, aborting now!");
  54. return 2;
  55. }
  56. if (checkForCommonValues(toBeFixedMC, toBeFixedRefData)){
  57. spdlog::warn("Fix your options, aborting now!");
  58. return 2;
  59. }
  60. }
  61. if (constrainMassFromRefMC && constrainMassFromData){
  62. if (checkForCommonValues(toBeConstrainedRefMC, toBeConstrainedRefData) ){
  63. spdlog::warn("Fix your options, aborting now!");
  64. return 2;
  65. }
  66. if (checkForCommonValues(toBeFixedRefMC, toBeFixedRefData)){
  67. spdlog::warn("Fix your options, aborting now!");
  68. return 2;
  69. }
  70. }
  71. if (constrainMassFromMC && checkForCommonValues(toBeConstrainedMC, toBeFixedMC)){
  72. spdlog::warn("The parameter will be fixed!");
  73. }
  74. if (constrainMassFromRefMC && checkForCommonValues(toBeConstrainedRefMC, toBeFixedRefMC)){
  75. spdlog::warn("The parameter will be fixed!");
  76. }
  77. if (constrainMassFromData && checkForCommonValues(toBeConstrainedRefData, toBeFixedRefData)){
  78. spdlog::warn("The parameter will be fixed!");
  79. }
  80. gROOT->SetBatch(kTRUE);
  81. gROOT->SetStyle("Plain");
  82. set_gStyle();
  83. //Open texFile
  84. std::ofstream myFile;
  85. open_Latex_noteFile(latex_massFit(), myFile);
  86. spdlog::info("[FIT]\t\tFitting only mass...");
  87. // --- Set the options --- //
  88. opts.only_Bmass = !fitKstarMass;
  89. opts.only_mass2DFit = fitKstarMass;
  90. opts.swave = fitKstarMass;
  91. opts.shift_lh = false; //keep it, it was there before
  92. opts.weighted_fit = fitKstarMass; // weights for the MASS DATA fit
  93. opts.plot_chi2 = true;
  94. opts.fit_mkpi = fitKstarMass;
  95. opts.use_mkpi = false;
  96. opts.plot_folder = get_MassFitPlot_path(); //Set the plot path
  97. opts.minos_errors = true; //TODO!
  98. opts.squared_hesse = false;
  99. opts.asymptotic = false;
  100. if (!fitReference) opts.plots_m_bins = 30; //Plot less bins for signal channel as the stats are sad there
  101. if (!fitReference) opts.plots_mkpi_bins = 20; //Plot less bins for signal channel as the stats are sad there
  102. // --- Load events from data tuple --- //
  103. std::vector<std::vector<fcnc::event>>events;
  104. std::vector<UInt_t> pdf_idx;
  105. if (opts.run == 1 || opts.run == 12){
  106. std::vector<fcnc::event> tmp = fcnc::load_events(get_theFCNCpath(0,1), "Events", -1);
  107. if (!fitReference) events.push_back(fcnc::filterResonances(tmp));
  108. else events.push_back(tmp);
  109. pdf_idx.push_back(1);
  110. }
  111. if (opts.run == 2 || opts.run == 12){
  112. std::vector<fcnc::event> tmp = fcnc::load_events(get_theFCNCpath(0,2), "Events", -1);
  113. if (!fitReference) events.push_back(fcnc::filterResonances(tmp));
  114. else events.push_back(tmp);
  115. pdf_idx.push_back(2);
  116. }
  117. //No need to keep the datasets separated, as there is no need for the weights
  118. if (!splitRuns && opts.run == 12){
  119. pdf_idx.clear();
  120. pdf_idx.push_back(12);
  121. //Add the vector from Run 2 into Run 1 vector
  122. events[0].insert(events[0].end(), events[1].begin(), events[1].end());
  123. //Delete the Run 2 vector
  124. events.pop_back();
  125. }
  126. //check that the number of pdfs is the same as number of event vectors
  127. if (pdf_idx.size() != events.size()){
  128. spdlog::error("Something went very wrong when loading the events and setting the pdfs.");
  129. spdlog::error("The number of PDFs!= number of event vectors: {0:d} vs {1:d}",pdf_idx.size(), events.size());
  130. return 5;
  131. }
  132. //we are good to go, now; how many individual pdfs are used?
  133. const UInt_t nPDFs = pdf_idx.size();
  134. //Check the number of events
  135. UInt_t N_tot = 0;
  136. for (UInt_t n = 0; n < nPDFs; n++){
  137. spdlog::debug("Event vector {0:d}:\t"+(Blind ? "Larger 1 ":std::to_string(events.at(n).size())), n);
  138. if (events.at(n).size()==0){
  139. spdlog::error("Empty event vector!");
  140. return 404;
  141. }
  142. N_tot += events.at(n).size();
  143. }
  144. spdlog::info("Total number of used events:\t{0:d}", N_tot);
  145. //Get the path to the file where to get the values/constraints from
  146. //Always use simFit from MCand mass only, it is easier
  147. std::string ParamInitFileMC = final_result_name_MC(pars, nBins, fitReference, false, true, false, false);
  148. std::string ParamInitFileRefMC = final_result_name_MC(pars, 1, true, false, true, false, true);
  149. std::string ParamInitFileRefData = final_result_name_mass(true, 1, splitRuns, pars, pars.Run);
  150. //current fitter, plotter, parameter and pdf:
  151. fcnc::fitter f(&opts);
  152. fcnc::options theOptions[nPDFs];
  153. fcnc::bu2kstarmumu_plotter * thePlotter[nPDFs];
  154. std::vector<fcnc::parameters*> theParams [nBins];
  155. std::vector<fcnc::pdf*> theProbs [nBins];
  156. std::vector< std::vector<fcnc::event>*> selection[nBins];
  157. //Set FS as a common parameter if fitting the sWeight
  158. if(fitKstarMass) f.set_common_parameters({"FS"});
  159. //Loop over PDFs and initialize parameters
  160. for(unsigned n = 0; n < nPDFs; n++){
  161. opts.run = pdf_idx.at(n); //Set proper run to options
  162. opts.name = get_MassFit_label(fitReference, -1, nBins, splitRuns, pars, pdf_idx.at(n));
  163. spdlog::debug("Initializing run {0:d}", opts.run);
  164. opts.update_efficiencies = true; //This ensures the acceptance weights to be taken into account.
  165. //loop over number of bins
  166. for(UInt_t b = 0; b < nBins; b++){
  167. //Create parameter set
  168. fcnc::bu2kstarmumu_parameters * leParameters = new fcnc::bu2kstarmumu_parameters(&opts);
  169. //create PDF
  170. fcnc::bu2kstarmumu_pdf * lePDF = new fcnc::bu2kstarmumu_pdf(&opts, leParameters);
  171. //Init the sig/bkg fraction
  172. leParameters->f_sig.init(fitReference ? 0.8 : 0.3, 0.1, 1.0, 0.1);
  173. //Init PDG mass, keep the range this large!
  174. leParameters->m_b.init(PDGMASS_B, B_MASS_LOW, B_MASS_HIGH, fixBMass ? 0.0 : 0.1);
  175. //Init mass parameters to defaults
  176. leParameters->init_mass_parameters(n,nBins,b,0.01);
  177. //Overwrite the defaults with constraints/fixes from MC/Ref, if needed
  178. if (constrainMassFromMC){
  179. leParameters->constrain_param_from_rootfile(ParamInitFileMC, toBeConstrainedMC, splitRuns ? pdf_idx.at(n) : 2, b);
  180. leParameters->fix_param_from_rootfile(ParamInitFileMC, toBeFixedMC, splitRuns ? pdf_idx.at(n) : 2, b);
  181. }
  182. if (constrainMassFromRefMC){ //Fix to refrence channel, so always read 0th bin
  183. leParameters->constrain_param_from_rootfile(ParamInitFileRefMC, toBeConstrainedRefMC, splitRuns ? pdf_idx.at(n) : 2, 0);
  184. leParameters->fix_param_from_rootfile(ParamInitFileRefMC, toBeFixedRefMC, splitRuns ? pdf_idx.at(n) : 2, 0);
  185. }
  186. if (constrainMassFromData){ //Fix to refrence channel, so always read 0th bin
  187. leParameters->constrain_param_from_rootfile(ParamInitFileRefData, toBeConstrainedRefData, splitRuns ? pdf_idx.at(n) : 2, 0);
  188. leParameters->fix_param_from_rootfile(ParamInitFileRefData, toBeFixedRefData, splitRuns ? pdf_idx.at(n) : 2, 0);
  189. }
  190. //Make sure the B mass range is correct
  191. leParameters->m_b.set_min(B_MASS_LOW);
  192. leParameters->m_b.set_max(B_MASS_HIGH);
  193. //Init the ratio of sigmas in signal MC/reference MC
  194. if (!fitReference) leParameters->m_sigma_1.init_fixed(leParameters->m_sigma_1.get_value()*get_sigmaRatio_fromMC(pars,nBins,b,pdf_idx.at(n)));
  195. //I don't trust the m_scale
  196. //Init background
  197. leParameters->init_mass_background_parameters(nBins, b, opts.fit_lambda);
  198. //define center of q2bin as effective q2:
  199. leParameters->eff_q2.init_fixed(bin_center_q2(opts,b));
  200. //Init the Kstar mass fit
  201. if(opts.fit_mkpi || opts.use_mkpi){
  202. //p-wave;
  203. leParameters->init_mkpi_pWave_parameters(fitReference,0.001);
  204. leParameters->init_kpi_background_parameters(fitReference,0.05);
  205. //s-wave
  206. leParameters->FS.init(0.055, 0.00, 0.5, 0.001); //David got 0.055
  207. leParameters->init_mkpi_sWave_parameters(fitReference, 0.0); //Fix it, otherwise it doesn't converge
  208. }
  209. //Control print of the parameters
  210. //leParameters->print_parameters(false);
  211. //Save the parameters and PDF per bin
  212. leParameters->take_current_as_start();
  213. theParams[b].push_back(leParameters);
  214. theProbs [b].push_back(lePDF);
  215. spdlog::info("[PDF{0:d}]\tSaved PDF and parameters!", pdf_idx.at(n));
  216. //create vector with events according to the requested fits/pulls
  217. std::vector<fcnc::event> *leEvents= new std::vector<fcnc::event>;
  218. //Loop over events
  219. spdlog::debug("Loop over events");
  220. for (auto meas: events.at(n)){
  221. if(meas.m < opts.m_low || meas.m > opts.m_high) continue;
  222. if(pars.polarity==1 && meas.magnet > 0) continue;
  223. if(pars.polarity==-1 && meas.magnet < 0) continue;
  224. if(meas.q2 < opts.TheQ2binsmin.at(b) || meas.q2 > opts.TheQ2binsmax.at(b)) continue;
  225. leEvents->push_back(meas);
  226. }
  227. //Update efficiencies (aka take into account angular parametrization weights) ONCE
  228. lePDF->load_coeffs_eff_phsp_4d();
  229. lePDF->update_cached_normalization(leParameters);
  230. lePDF->update_cached_efficiencies(leParameters, leEvents);
  231. spdlog::info("[PDF{0:d}]\tFinished selecting the events: {1:d}",n, leEvents->size());
  232. //save event vector in vector
  233. selection[b].push_back(leEvents);
  234. if(selection[b].back()->size() > 0){
  235. spdlog::info("[PDF{0:d}]\t[BIN{1:d}]\tDone!", n, b);
  236. }
  237. else{
  238. spdlog::critical("No events found for PDF={0:d} and q2 bin={1:d}. Exit!",n,b);
  239. assert(0);
  240. }
  241. } //End loop over bins
  242. opts.update_efficiencies = false; //Prevent the weights to be applied several more times in fitter::fit
  243. theOptions[n] = opts;
  244. //Allocate the plotter... sigh #ItIsn'tThe90sAnymore
  245. thePlotter[n] = new fcnc::bu2kstarmumu_plotter(&theOptions[n]);
  246. }//end loop over PDFs
  247. //--------------------------------
  248. // FIT
  249. //--------------------------------
  250. spdlog::info("[MASSFIT]\tMass fit started.");
  251. //Measure the time for the fit:
  252. runTime timer = runTime();
  253. //Save the fit results
  254. std::vector<int>fit_results[nBins];
  255. std::vector<double>f_sigs[nBins];
  256. std::vector<double>f_sigserr[nBins];
  257. std::vector<double> bkg_int_full_range[nBins]; //Not really used
  258. std::vector<UInt_t>evts_cntr[nBins];
  259. //fit per bins:
  260. for(unsigned int b = 0; b < nBins; b++){
  261. //Start the clock
  262. timer.start();
  263. time_t startTime = time(0);
  264. spdlog::info("[START]\tStart the fit for bin #{0:d}", b);
  265. std::string tag = get_MassFit_label(fitReference, b,nBins, splitRuns, pars, 0);
  266. clear_Latex_noteFile(latex_fitterFile(tag));
  267. spdlog::info("[FIT]\tRunning the fitter...");
  268. fit_results[b].push_back(f.fit(theProbs[b], theParams[b], selection[b], tag));
  269. spdlog::info("Q2BIN={0:d}\tLLH={1:f}", b, f.likelihood());
  270. //Stop the clock
  271. timer.stop(startTime);
  272. //save signal fraction and event number for each bin and each pdf:
  273. for(UInt_t n = 0; n < nPDFs; n++){
  274. f_sigs[b] .push_back(((fcnc::bu2kstarmumu_parameters *) theParams[b].at(n))->f_sig.get_value());
  275. f_sigserr[b].push_back(((fcnc::bu2kstarmumu_parameters *) theParams[b].at(n))->f_sig.get_error());
  276. evts_cntr[b].push_back(selection[b].at(n)->size());
  277. //integrate the background pdf over the range [opts.m_min; opts.m_max] to estimate the background contribution in each q2bin:
  278. bkg_int_full_range[b].push_back(((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n))->integral_m_bkg_prob((fcnc::bu2kstarmumu_parameters*)theParams[b].at(n),B_MASS_LOW, B_MASS_HIGH));
  279. }
  280. //Plot everything
  281. bool sigRegion = true; //Plot only in the signal region
  282. for(UInt_t n = 0; n < nPDFs; n++){
  283. tag = get_MassFit_label(fitReference, b,nBins, splitRuns, pars, pdf_idx.at(n));
  284. theOptions[n].plot_label = "LHCb data";
  285. theOptions[n].q2_label =q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b));
  286. if (nPDFs>1){ //If only one PDF, just plot the "added pdfs"
  287. spdlog::info("[PLOT]\t"+theOptions[n].plot_label);
  288. thePlotter[n]->plot_data((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n),
  289. (fcnc::bu2kstarmumu_parameters*)theParams[b].at(n),
  290. selection[b].at(n), get_MassFitPlot_path(),tag, sigRegion);
  291. }
  292. }
  293. //Plot joint result
  294. std::vector<fcnc::bu2kstarmumu_pdf*> * prober = (std::vector<fcnc::bu2kstarmumu_pdf*> *) & theProbs[b];
  295. std::vector<fcnc::bu2kstarmumu_parameters*> * paramser = (std::vector<fcnc::bu2kstarmumu_parameters*> *) & theParams[b];
  296. tag = get_MassFit_label(fitReference, b,nBins, splitRuns, pars, pars.Run);
  297. thePlotter[0]->plot_added_pdfs(prober, paramser, &selection[b],
  298. get_MassFitPlot_path(), tag, sigRegion);
  299. }//end bin loop
  300. //Plot the significances and yields in the fancy plot
  301. //TODO: unhardcode the runs
  302. if (!fitReference && nBins>1){
  303. std::string tag = get_MassFit_label(fitReference, -1,nBins, splitRuns, pars, 12);
  304. spdlog::info("Saving yield plots into " + tag);
  305. thePlotter[0]->plotYieldInQ2(true, theParams, theProbs, nPDFs, evts_cntr, get_MassFitPlot_path(), tag);
  306. thePlotter[1]->plotYieldInQ2(false, theParams, theProbs, nPDFs, evts_cntr, get_MassFitPlot_path(), tag);
  307. }
  308. //--------------------------------
  309. // Print & Save
  310. //--------------------------------
  311. //Print running time
  312. timer.print(nBins);
  313. //Print all fit results
  314. print_all_parameters(nBins, pdf_idx, theParams, spdlog::level::debug);
  315. //Save the fit results
  316. for(unsigned int b = 0; b < nBins; b++){
  317. for(UInt_t i = 0; i < pdf_idx.size(); i++){
  318. std::vector<fcnc::bu2kstarmumu_parameters*> * paramser = (std::vector<fcnc::bu2kstarmumu_parameters*> *) & theParams[b];
  319. std::string results_file = get_MassFitResult_path()+ "fitresult_"
  320. +get_MassFit_label(fitReference, b, nBins, splitRuns, pars, pars.Run)+ ".txt";
  321. paramser->at(i)->save_param_values(results_file);
  322. }
  323. }
  324. //Print signal yield in the terminal and to a tex file
  325. if (!Blind){
  326. print_sig_yields(nBins, pdf_idx, evts_cntr, f_sigs, f_sigserr);
  327. print_bkg_yields(nBins, pdf_idx, evts_cntr, f_sigs, f_sigserr);
  328. }
  329. print_sig_yields_tex(get_MassFit_label(fitReference, -1,nBins,
  330. splitRuns, pars, pars.Run),
  331. nBins, pdf_idx, &opts, evts_cntr, f_sigs, f_sigserr);
  332. //Save results to root file
  333. std::string results_file = final_result_name_mass(fitReference, nBins, splitRuns, pars, pars.Run);
  334. save_results(results_file, nBins, pdf_idx, fit_results, theParams, true, &opts);
  335. //Close Latex file
  336. myFile.close();
  337. spdlog::info("[MASSFIT]\tMass fit finished.");
  338. return 0;
  339. }