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.

458 lines
21 KiB

  1. #include <parameterscan.hh>
  2. #include <iostream>
  3. #include <fstream>
  4. #include <paths.hh>
  5. #include <options.hh>
  6. #include <funcs.hh>
  7. #include <generator.hh>
  8. #include <parameters.hh>
  9. #include <event.hh>
  10. #include <funcs.hh>
  11. #include <pdf.hh>
  12. #include <fitter.hh>
  13. #include <helpers.hh>
  14. #include <TFile.h>
  15. #include <TTree.h>
  16. #include <TCanvas.h>
  17. #include <spdlog.h>
  18. /**
  19. * @file parameterscan.cc
  20. * @author Renata Kopecna
  21. * @date 2021-03-02
  22. *
  23. */
  24. fcnc::parameterscan::parameterscan(options* o):
  25. multifit(o)
  26. {
  27. };
  28. void fcnc::parameterscan::scan(std::string param_name, double min, double max, unsigned int nsteps, unsigned int nevents, unsigned int reruns, pdf* prob, parameters* params, generator* gen, bool only_float_in_generation){
  29. std::vector<unsigned int > events;
  30. events.push_back(nevents);
  31. std::vector<pdf* > probs;
  32. probs.push_back(prob);
  33. std::vector<parameters* > the_params;
  34. the_params.push_back(params);
  35. std::vector<generator* > gens;
  36. gens.push_back(gen);
  37. scan(param_name, min, max, nsteps, events, reruns, probs, the_params, gens, only_float_in_generation);
  38. }
  39. //void parameterscan::scan(std::string param_name, double min, double max, unsigned int nsteps, unsigned int nevents, unsigned int reruns, pdf_type* prob, params_type* params, generator_type* gen, bool only_float_in_generation) //fixed in fit on fixed value
  40. void fcnc::parameterscan::scan(std::string param_name, double min, double max, unsigned int nsteps, std::vector<unsigned int> nevents, unsigned int reruns, std::vector<pdf*> pdfs, std::vector<parameters*> params, std::vector<generator*> gens, bool only_float_in_generation){
  41. parameter* param_varied = 0;
  42. for (unsigned int i=0; i<params.size(); i++){
  43. if (params.at(i)->get_parameter(param_name)) {
  44. param_varied = params.at(i)->get_parameter(param_name);
  45. break;
  46. }
  47. }
  48. //open TeX file
  49. std::ofstream myFile;
  50. open_Latex_noteFile(latex_paramScan(), myFile);
  51. //parameter* param_varied = params->get_parameter(param_name);
  52. double fit_start_value = param_varied->get_start_value();
  53. if (only_float_in_generation) spdlog::info( "The fit start value will be fixed at: {0:f}",fit_start_value);
  54. int param_index = param_varied->get_index();
  55. if (param_varied != 0){
  56. std::string param_description = param_varied->get_description();
  57. std::string param_root = param_varied->get_root_name();
  58. spdlog::info( "Doing parameter scan of parameter {0:d}: {1:s}", param_index, param_name);
  59. spdlog::info( "Varying parameter from {0:f} to {1:f}", min, max);
  60. unsigned int nparams = 0;
  61. for (unsigned int i=0; i<params.size(); i++){
  62. nparams += params.at(i)->nparameters();
  63. }
  64. //params->nparameters();
  65. TH1D* error_hists[nparams];
  66. TH1D* value_hists[nparams];
  67. double mean_values[nparams][nsteps+1];
  68. double sigma_mean_values[nparams][nsteps+1];
  69. double mean_errors[nparams][nsteps+1];
  70. double sigma_mean_errors[nparams][nsteps+1];
  71. double min_hist = min - 0.5*(max-min)/nsteps;
  72. double max_hist = max + 0.5*(max-min)/nsteps;
  73. //create histograms
  74. unsigned int start_param = 0;
  75. for (unsigned int i=0; i<params.size(); i++){
  76. for (unsigned int j = 0; j < nparams; j++){
  77. unsigned int idx = start_param+j;
  78. parameter* param = params.at(i)->get_parameter(j);
  79. error_hists[idx] = new TH1D(("error_" + param->get_name()).c_str(),
  80. ("#sigma" + param->get_root_name() + ";" + param_root).c_str(),
  81. nsteps+1, min_hist, max_hist);
  82. error_hists[idx]->SetMarkerStyle(8);
  83. error_hists[idx]->SetMarkerColor(4);
  84. value_hists[idx] = new TH1D(("value_" + param->get_name()).c_str(),
  85. (param->get_root_name() + ";" + param_root).c_str(),
  86. nsteps+1, min_hist, max_hist);
  87. value_hists[idx]->SetMarkerStyle(8);
  88. value_hists[idx]->SetMarkerColor(4);
  89. }
  90. start_param += params.at(i)->nparameters();
  91. }
  92. //do precalculations
  93. for (unsigned int i=0; i<params.size(); i++){
  94. pdfs.at(i)->init(params.at(i));
  95. }
  96. //create output trees
  97. //current values to fill into the tree
  98. double value, error, error_up, error_down, start_value, param_value, nominal_error, nominal_value;
  99. int step, run, migrad, status_cov;
  100. std::vector<TTree*> trees;//one tree for every varied parameter
  101. //start_param = 0;
  102. for (unsigned int i=0; i<params.size(); i++){
  103. for (unsigned int j = 0; j < nparams; j++){
  104. //unsigned int idx = start_param+j;
  105. parameter* param = params.at(i)->get_parameter(j);
  106. if (param->get_step_size() != 0.0){
  107. std::string parname(param->get_name());
  108. std::string pardesc(param->get_description());// + " results");
  109. TTree* t = new TTree(parname.c_str(), pardesc.c_str());
  110. t->Branch("step",&step,"step/I");
  111. t->Branch("run",&run,"run/I");
  112. t->Branch("param_value",&param_value,"param_value/D");
  113. t->Branch("value",&value,"value/D");
  114. t->Branch("error",&error,"error/D");
  115. t->Branch("nominal_value",&nominal_value,"nominal_value/D");
  116. t->Branch("nominal_error",&nominal_error,"nominal_error/D");
  117. t->Branch("error_up",&error_up,"error_up/D");
  118. t->Branch("error_down",&error_down,"error_down/D");
  119. t->Branch("start_value",&start_value,"start_value/D");
  120. t->Branch("migrad",&migrad,"migrad/I");
  121. t->Branch("status_cov",&status_cov,"status_cov/I");
  122. trees.push_back(t);
  123. }
  124. }
  125. //start_param += params.at(i)->nparameters();
  126. }
  127. //enter main loop
  128. for (unsigned int i = 0; i <= nsteps; i++){
  129. //reset all results
  130. std::vector<std::vector<double> > values(nparams, std::vector<double>(reruns, 0.0));
  131. std::vector<std::vector<double> > errors(nparams, std::vector<double>(reruns, 0.0));
  132. std::vector<std::vector<double> > errors_up(nparams, std::vector<double>(reruns, 0.0));
  133. std::vector<std::vector<double> > errors_down(nparams, std::vector<double>(reruns, 0.0));
  134. std::vector<std::vector<double> > nominal_values(nparams, std::vector<double>(reruns, 0.0));
  135. std::vector<std::vector<double> > nominal_errors(nparams, std::vector<double>(reruns, 0.0));
  136. std::vector<int> return_values(reruns);
  137. //only_float_in_generation means that you use a varied parameter
  138. //for generation but in the fit use the start_value
  139. //this can be used for systematic studies
  140. //we would also need to do a nominal fit
  141. //then we can see the actual difference
  142. //choose new value for the scan parameter
  143. param_value = double(i)*(max - min)/(nsteps) + min;
  144. if (!only_float_in_generation){ //float in generation and fit
  145. param_varied->set_value(param_value);
  146. param_varied->set_start_value(param_value);
  147. }
  148. // param_varied->init(param_name, param_description,
  149. // param_value,
  150. // param_varied->get_min(), param_varied->get_max(),
  151. // param_varied->get_step_size());
  152. //this is the scanned parameter so usually we change it before generation and fit
  153. //this is the point: we need to do a couple reruns
  154. fitter fit(opts);
  155. fit.set_common_parameters(common_params);
  156. for (unsigned int k = 0; k < reruns; k++){
  157. spdlog::info( "Parameter "+param_name+" {0:f}", param_value);
  158. spdlog::info( "Run no. {0:d}", k);
  159. std::string num;
  160. std::stringstream out;
  161. out << opts->name << "_" << (i+1) << "_" << (k+1); //TOOD: move to paths
  162. num = out.str();
  163. if (only_float_in_generation){//this generates with updated parameter values
  164. param_varied->set_value(param_value);
  165. param_varied->set_start_value(param_value);
  166. }
  167. // param_varied->init(param_name, param_description,
  168. // param_value,
  169. // param_varied->get_min(), param_varied->get_max(),
  170. // param_varied->get_step_size());
  171. for (unsigned int j=0; j<params.size(); j++){
  172. params.at(j)->reset_parameters();//this line was missing before? did we generate with fitted params?
  173. }
  174. std::vector< std::vector <event> > temp_events;
  175. for (unsigned int j=0; j<gens.size(); j++){
  176. std::vector<event> ev = gens.at(j)->generate(nevents.at(j), params.at(j), pdfs.at(j));
  177. temp_events.push_back(ev);
  178. }
  179. std::vector< std::vector <event> * > events;
  180. for (unsigned int j=0; j<gens.size(); j++){
  181. events.push_back(&temp_events.at(j));
  182. }
  183. if (only_float_in_generation){//this tries to fit with original parameter values
  184. param_varied->set_value(fit_start_value);
  185. param_varied->set_start_value(fit_start_value);
  186. }
  187. // param_varied->init(param_name, param_description,
  188. // fit_start_value, //use start value here!
  189. // param_varied->get_min(), param_varied->get_max(),
  190. // param_varied->get_step_size());
  191. for (unsigned int j=0; j<params.size(); j++){
  192. params.at(j)->reset_parameters();
  193. }
  194. int result = 0;
  195. result = fit.fit(pdfs, params, events, num);
  196. return_values.at(k) = result;
  197. if (result != 0 && opts->repeat_on_fail){
  198. spdlog::warn( "Fit failed, repeating run");
  199. k--;
  200. continue;
  201. }
  202. unsigned int start_param = 0;
  203. for (unsigned int j = 0; j < params.size(); j++){
  204. for (unsigned int l = 0; l < params.at(j)->nparameters(); l++){
  205. unsigned int idx = start_param+l;
  206. parameter* param = params.at(j)->get_parameter(l);
  207. values.at(idx).at(k) = param->get_value();
  208. errors.at(idx).at(k) = param->get_error();
  209. errors_up.at(idx).at(k) = param->get_error_up();
  210. errors_down.at(idx).at(k) = param->get_error_down();
  211. }
  212. start_param += params.at(j)->nparameters();
  213. }
  214. //now we want to do a nominal fit (if the respective options are set)
  215. if (opts->refitting_nominal && only_float_in_generation){//now we do a nominal fit
  216. spdlog::info( "Nominal fit");
  217. param_varied->set_value(param_value);
  218. param_varied->set_start_value(param_value);
  219. // param_varied->init(param_name, param_description,
  220. // param_value,
  221. // param_varied->get_min(), param_varied->get_max(),
  222. // param_varied->get_step_size());
  223. for (unsigned int j = 0; j < params.size(); j++){
  224. params.at(j)->reset_parameters();
  225. }
  226. //and lets fit
  227. fit.fit(pdfs, params, events, num);
  228. //extract the parameters from the fit
  229. start_param = 0;
  230. for (unsigned int j = 0; j < params.size(); j++){
  231. for (unsigned int l = 0; l < params.at(j)->nparameters(); l++){
  232. unsigned int idx = start_param+l;
  233. parameter* param = params.at(j)->get_parameter(l);
  234. nominal_values.at(idx).at(k) = (param->get_value());
  235. nominal_errors.at(idx).at(k) = (param->get_error());
  236. }
  237. start_param += params.at(j)->nparameters();
  238. }
  239. }
  240. else{
  241. for (unsigned int j = 0; j < nparams; j++){
  242. nominal_values.at(j).at(k) = (0.0);
  243. nominal_errors.at(j).at(k) = (0.0);
  244. }
  245. }
  246. }//end reruns
  247. //determine means/widths of the distributions via gauss-fits
  248. unsigned int start_param = 0;
  249. for (unsigned int j = 0; j < params.size(); j++){
  250. for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){
  251. unsigned int idx = start_param + k;
  252. parameter* param = params.at(j)->get_parameter(k);
  253. if (param->get_step_size() != 0.0){
  254. std::string step;
  255. std::stringstream out;
  256. out << (i+1);
  257. step = out.str();
  258. double dummy1, dummy2, dummy3, dummy4, dummy5;
  259. double mean_value, mean_error, sigma_mean_value, sigma_mean_error;
  260. update_pull(param, values.at(idx), errors.at(idx),
  261. dummy1, dummy2, dummy3, dummy4, dummy5, step);
  262. update_value(param, values.at(idx), errors.at(idx),
  263. mean_value, sigma_mean_value, dummy3, dummy4, dummy5, step);
  264. update_error(param, values.at(idx), errors.at(idx),
  265. mean_error, sigma_mean_error, dummy3, dummy4, dummy5, step);
  266. value_hists[idx]->SetBinContent(i+1,mean_value);
  267. value_hists[idx]->SetBinError(i+1,sigma_mean_value);
  268. error_hists[idx]->SetBinContent(i+1,mean_error);
  269. error_hists[idx]->SetBinError(i+1,sigma_mean_error);
  270. mean_values[idx][i] = mean_value;//for the output tables
  271. sigma_mean_values[idx][i] = sigma_mean_value;//for the output tables
  272. mean_errors[idx][i] = mean_error;
  273. sigma_mean_errors[idx][i] = sigma_mean_error;
  274. }
  275. }
  276. start_param += params.at(j)->nparameters();
  277. }
  278. //save tree results
  279. int param_idx = 0;
  280. output->cd();
  281. start_param = 0;
  282. for (unsigned int j = 0; j < params.size(); j++){//this gives nice output
  283. for (unsigned int l = 0; l < params.at(j)->nparameters(); l++){
  284. unsigned int idx = start_param+l;
  285. parameter* param = params.at(j)->get_parameter(l);
  286. if (param->get_step_size() != 0.0){
  287. TTree* t = trees.at(param_idx);
  288. for (unsigned int k=0; k<reruns; k++){
  289. step = i;
  290. run = k;
  291. //param_value is already set;
  292. value = values.at(idx).at(k);
  293. error = errors.at(idx).at(k);
  294. nominal_value = nominal_values.at(idx).at(k);
  295. nominal_error = nominal_errors.at(idx).at(k);
  296. error_up = errors_up.at(idx).at(k);
  297. error_down = errors_down.at(idx).at(k);
  298. start_value = param->get_start_value();
  299. migrad = return_values.at(k) % 100;
  300. status_cov = return_values.at(k) / 100;
  301. t->Fill();
  302. }
  303. param_idx++;
  304. }
  305. }
  306. start_param += params.at(j)->nparameters();
  307. }
  308. }
  309. //save output trees
  310. for (unsigned int j = 0; j < trees.size(); j++){
  311. trees.at(j)->Write();
  312. }
  313. //summary output
  314. myFile << "Parameter scan results: values\\\\" << std::endl;
  315. myFile << "\\begin{tabular}{|c|";
  316. for (unsigned int i=0; i<=nsteps; i++){
  317. myFile << "c";
  318. }
  319. myFile << "|}\\hline" << std::endl;
  320. myFile << "$" << param_varied->get_description() << "$";
  321. for (unsigned int i=0; i<=nsteps; i++){
  322. double param_value = double(i)*(max - min)/(nsteps) + min;
  323. myFile << " & " << std::setprecision(2) << param_value;
  324. }
  325. myFile << "\\\\ \\hline" << std::endl;
  326. start_param = 0;
  327. for (unsigned int i=0; i < params.size(); i++){
  328. for (unsigned int j=0; j < params.at(i)->nparameters(); j++){
  329. unsigned int idx = start_param+j;
  330. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){
  331. myFile << "$" << params.at(i)->get_parameter(j)->get_description() << "$";
  332. for (unsigned int k=0; k <= nsteps; k++){
  333. myFile << " & $" << std::setprecision(2)
  334. << mean_values[idx][k] << " \\pm "
  335. //<< mean_errors[i][j]
  336. << sigma_mean_values[idx][k]
  337. << "$";
  338. }
  339. myFile << "\\\\" << std::endl;
  340. }
  341. }
  342. start_param += params.at(i)->nparameters();
  343. }
  344. myFile << "\\hline \\end{tabular}" << std::endl;
  345. myFile << "Parameter scan results: errors\\\\" << std::endl;
  346. myFile << "\\begin{tabular}{|c|";
  347. for (unsigned int i=0; i<=nsteps; i++){
  348. myFile << "c";
  349. }
  350. myFile << "|}\\hline" << std::endl;
  351. myFile << "$" << param_varied->get_description() << "$";
  352. for (unsigned int i=0; i<=nsteps; i++){
  353. double param_value = double(i)*(max - min)/(nsteps) + min;
  354. myFile << " & " << std::setprecision(2) << param_value;
  355. }
  356. myFile << "\\\\ \\hline" << std::endl;
  357. start_param = 0;
  358. for (unsigned int i=0; i < params.size(); i++){
  359. for (unsigned int j=0; j < params.at(i)->nparameters(); j++){
  360. unsigned int idx = start_param+j;
  361. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){
  362. myFile << "$" << params.at(i)->get_parameter(j)->get_description() << "$";
  363. for (unsigned int k=0; k <= nsteps; k++){
  364. myFile << " & $" << std::setprecision(2)
  365. << mean_errors[idx][k] << " \\pm "
  366. << sigma_mean_errors[idx][k] << "$";
  367. }
  368. myFile << "\\\\" << std::endl;
  369. }
  370. }
  371. start_param += params.at(i)->nparameters();
  372. }
  373. myFile << "\\hline \\end{tabular}" << std::endl;
  374. start_param = 0;
  375. for (unsigned int i=0; i < params.size(); i++){
  376. for (unsigned int j=0; j < params.at(i)->nparameters(); j++){
  377. unsigned int idx = start_param+j;
  378. //print result histos
  379. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){
  380. output->cd();
  381. parameter* param = params.at(i)->get_parameter(j);
  382. std::string error_name = "parameter scan sigma(" + param->get_name() + ")";
  383. TCanvas *c1 = new TCanvas(error_name.c_str(), error_name.c_str(), 1600, 1200);
  384. c1->cd();
  385. error_hists[idx]->Draw("e");
  386. if (opts->write_eps) c1->Print(get_param_scan_path(param->get_name(),true).c_str(), "eps");
  387. c1->Write();
  388. delete error_hists[idx];
  389. delete c1;
  390. std::string value_name = "Parameter scan "+param->get_name();
  391. TCanvas *c2 = new TCanvas(value_name.c_str(), value_name.c_str(), 1600, 1200);
  392. c2->cd();
  393. value_hists[idx]->Draw("e");
  394. if (opts->write_eps) c2->Print(get_param_scan_path(param->get_name(),false).c_str(), "eps");
  395. c2->Write();
  396. delete value_hists[idx];
  397. delete c2;
  398. //TODO add pulls
  399. }
  400. }
  401. start_param += params.at(i)->nparameters();
  402. }
  403. }
  404. else{
  405. spdlog::error("Parameter "+param_name+" not found.");
  406. assert(0);
  407. }
  408. }