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.

1260 lines
55 KiB

  1. //Renata Kopecna
  2. #include <fitter.hh>
  3. #include <paths.hh>
  4. #include <event.hh>
  5. #include <parameters.hh>
  6. #include <pdf.hh>
  7. #include <plotter.hh>
  8. #include <options.hh>
  9. #include <helpers.hh>
  10. #include <funcs.hh>
  11. #include <design.hh>
  12. #include <constants.hh>
  13. #include <TH1D.h>
  14. #include <TMatrixD.h>
  15. #include <TMatrixDSym.h>
  16. #include <TRandom3.h>
  17. #include <TVector.h>
  18. #include <TDecompChol.h>
  19. #include <spdlog.h>
  20. #include <fstream>
  21. #include <iostream>
  22. #include <complex>
  23. #include <assert.h>
  24. #include <thread>
  25. #include <mutex>
  26. //Log of the covariance matrix status
  27. void printCovMatrixStatus(int status, bool squared){
  28. std::string hesse = "Hesse";
  29. if (squared) hesse = "Squared Hesse";
  30. if (status==0) spdlog::warn(hesse + " returns 0: Hesse not calculated.");
  31. else if (status==1) spdlog::warn(hesse + " returns 1: Approximation only.");
  32. else if (status==2) spdlog::warn(hesse + " returns 2: Full, forced pos def");
  33. else if (status==3) spdlog::info(hesse + " returns 3: ALL GOOD");
  34. else spdlog::warn(hesse + " returns {0:d} -> SOMETHING VERY WRONG", status);
  35. return;
  36. }
  37. //Migrad status log so one doesn't have to look it up all the time
  38. void printMigradStatus(int status){
  39. if (status==0) spdlog::info("MIGRAD returns 0: ALL GOOD");
  40. else if (status==1) spdlog::warn("MIGRAD returns 1: Blank command, ignored.");
  41. else if (status==2) spdlog::warn("MIGRAD returns 2: Command line unreadable, ignored.");
  42. else if (status==3) spdlog::warn("MIGRAD returns 3: Unknown command, ignored");
  43. else if (status==4) spdlog::warn("MIGRAD returns 4: Abnormal termination, MIGRAD not converged or something.");
  44. else if (status==9) spdlog::warn("MIGRAD returns 9: Reserved.");
  45. else if (status==10) spdlog::warn("MIGRAD returns 10: End command.");
  46. else if (status==11) spdlog::warn("MIGRAD returns 11: Exit/Stop command.");
  47. else if (status==12) spdlog::warn("MIGRAD returns 12: Return command.");
  48. else spdlog::warn("MIGRAD returns {0:d} -> SOMETHING VERY WRONG", status);
  49. return;
  50. }
  51. //set plotter
  52. void fcnc::fitter::set_plotters(plotter* plot) {
  53. std::vector<plotter* > p;
  54. p.push_back(plot);
  55. plots = p;
  56. return;
  57. }
  58. ///set plotters
  59. void fcnc::fitter::set_plotters(std::vector<plotter*> plotters) {
  60. plots = plotters;
  61. return;
  62. }
  63. ///define common parameters for all pdfs
  64. void fcnc::fitter::set_common_parameters(std::vector<std::string> common_pars) {
  65. common_params = common_pars;
  66. return;
  67. }
  68. ///is the parameter with name one of the common parameters
  69. bool fcnc::fitter::is_common(std::string name) {
  70. for (unsigned int i=0; i<common_params.size(); i++){
  71. if (common_params.at(i) == name) return true;
  72. }
  73. return false;
  74. }
  75. ///is this the first occurence of the parameter?
  76. bool fcnc::fitter::is_first(std::string name, unsigned int idx_i, unsigned int idx_j) {
  77. for (unsigned int i = 0; i < params.size(); i++){
  78. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  79. if (name == params.at(i)->get_parameter(j)->get_name()){
  80. if (i==idx_i && j==idx_j) return true;
  81. else return false;
  82. }
  83. }
  84. }
  85. spdlog::critical("[FATAL]\t\tThe parameter '"+name+"' was not found!");
  86. assert(0);
  87. return true;
  88. }
  89. ///returns the nth minuit index for parameter with name
  90. int fcnc::fitter::nth_minuit_index(std::string name, unsigned int n) {
  91. assert(n);
  92. assert(n <= params.size());
  93. unsigned int start_param = 0;
  94. for (unsigned int i = 0; i < params.size(); i++){
  95. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  96. if (name == params.at(i)->get_parameter(j)->get_name()){
  97. if (n == 1) return start_param+j;
  98. else n--;
  99. }
  100. }
  101. start_param += minuit_one_fitter->params.at(i)->nparameters();
  102. }
  103. return -1;
  104. }
  105. ///returns the first minuit index for parameter with name
  106. int fcnc::fitter::first_minuit_index(std::string name) {
  107. return nth_minuit_index(name, 1);
  108. }
  109. ///returns wether this is an analysis with blinded parameters
  110. bool fcnc::fitter::is_blind() {
  111. for (unsigned int i = 0; i < params.size(); i++){
  112. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  113. if (params.at(i)->get_parameter(j)->is_blind()){
  114. return true;
  115. }
  116. }
  117. }
  118. return false;
  119. }
  120. //WHAT THE FUCK IS THIS DOING HERE?
  121. int fcnc::fitter::fit(pdf* probs, parameters* parms, std::vector<event>* ev, std::string index){
  122. std::vector<pdf *> the_probs;
  123. the_probs.push_back(probs);
  124. std::vector<parameters *> the_params;
  125. the_params.push_back(parms);
  126. std::vector<std::vector<event>* > the_events;
  127. the_events.push_back(ev);
  128. return fit(the_probs, the_params, the_events, index);
  129. }
  130. void fcnc::fitter::init(pdf* probs, parameters* parms, std::vector<event>* ev, std::string index){
  131. std::vector<pdf *> the_probs;
  132. the_probs.push_back(probs);
  133. std::vector<parameters *> the_params;
  134. the_params.push_back(parms);
  135. std::vector<std::vector<event>* > the_events;
  136. the_events.push_back(ev);
  137. return init(the_probs, the_params, the_events, index);
  138. }
  139. void fcnc::fitter::minuit_one_fcn(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *parameters, Int_t iflag){
  140. //set the parameter sets according to minuits current parameter values stored in the params pointer
  141. //do not forget to set common parameters correctly. these have no directly corresponding minuit index, use first_index instead
  142. unsigned int start_param = 0;
  143. for (unsigned int i = 0; i < minuit_one_fitter->params.size(); i++){
  144. for (unsigned int j = 0; j < minuit_one_fitter->params.at(i)->nparameters(); j++){
  145. unsigned int index = start_param + j;
  146. std::string par_name = minuit_one_fitter->params.at(i)->get_parameter(j)->get_name();
  147. if (minuit_one_fitter->is_common(par_name))
  148. minuit_one_fitter->params.at(i)->get_parameter(j)->set_value(parameters[minuit_one_fitter->first_minuit_index(par_name)]);
  149. else
  150. minuit_one_fitter->params.at(i)->get_parameter(j)->set_value(parameters[index]);
  151. }
  152. start_param += minuit_one_fitter->params.at(i)->nparameters();
  153. }
  154. lh = minuit_one_fitter->likelihood();
  155. return;
  156. }
  157. fcnc::fitter::fitter(options* o):
  158. opts(o)
  159. {
  160. minuit_one = new TMinuit(1000);//params->nparameters());
  161. minuit_one->SetFCN(&(minuit_one_fcn));
  162. //this makes minuit use highest precision
  163. int errorcode;
  164. double strategy_list[1];// = {2.0}
  165. strategy_list[0] = opts->minuit_strategy;
  166. minuit_one->mnexcm("SET STR", strategy_list, 1, errorcode);
  167. minuit_one->SetMaxIterations(40000);
  168. //need to set this value to 0.5 if you do not use -2*ln(LH)
  169. minuit_one->SetErrorDef(1.0);//default
  170. spdlog::info("Machine precision: {0:f}", minuit_one->fEpsmac); //8.88178e-16
  171. //verbose minuit
  172. //minuit_one->SetPrintLevel(o->print_level);
  173. //minuit_one->SetPrintLevel(-1);
  174. empirical_constant = 0.0;
  175. }
  176. fcnc::fitter::~fitter(){
  177. delete minuit_one;
  178. }
  179. void fcnc::fitter::init(std::vector<pdf*> probs, std::vector<parameters*> parms, std::vector< std::vector<event> * > ev, std::string index){
  180. square_weights = false;
  181. //set all important pointers and initialize
  182. minuit_one_fitter = this;
  183. //this could be different for every fit (feldman-cousins)
  184. int errorcode;
  185. double strategy_list[1];// = {2.0}
  186. strategy_list[0] = opts->minuit_strategy;
  187. minuit_one->mnexcm("SET STR", strategy_list, 1, errorcode);
  188. //prob = probability;
  189. pdfs = probs;
  190. params = parms;
  191. events = ev;
  192. reset_param_values();
  193. //this was originally before the reset... put here to catch reset of swave
  194. for (unsigned int i=0; i<pdfs.size(); i++)
  195. pdfs.at(i)->init(params.at(i));
  196. //update cached efficiencies in three situations
  197. //1. q2 fixed and regular acceptance
  198. //2. unfolded fit to determine the weight=1/eff
  199. //3. per event norm
  200. //cache fis
  201. if (opts->cache_fis){
  202. spdlog::info("Caching fis");
  203. for (unsigned int i = 0; i < pdfs.size(); i++)
  204. pdfs.at(i)->update_cached_integrated_fis(params.at(i));
  205. }
  206. for (unsigned int i = 0; i < pdfs.size(); i++){
  207. parameter* effq2 = params.at(i)->get_parameter("eff_q2");
  208. bool q2fixed = false;
  209. if (effq2) q2fixed = (effq2->get_step_size() == 0.0);
  210. if ((q2fixed && opts->use_angular_acc) || opts->weighted_fit || opts->use_event_norm){
  211. pdfs.at(i)->update_cached_efficiencies(params.at(i), events.at(i));
  212. }
  213. }
  214. //per event xis
  215. if (opts->use_event_norm){
  216. for (unsigned int i = 0; i < pdfs.size(); i++){
  217. pdfs.at(i)->update_cached_xis(params.at(i), events.at(i));
  218. }
  219. }
  220. }
  221. int fcnc::fitter::fit(std::vector<pdf*> probs, std::vector<parameters*> parms, std::vector< std::vector<event> * > ev, std::string index){
  222. //can only use either squared hesse or minos
  223. if(opts->minos_errors && opts->squared_hesse){
  224. spdlog::critical("Cannot use both MINOS and squared HESSE for uncertainty deterimination. Choose one!");
  225. assert(0);
  226. }
  227. square_weights = false;
  228. //set all important pointers and initialize
  229. minuit_one_fitter = this;
  230. //this could be different for every fit (feldman-cousins)
  231. int errorcode;
  232. double strategy_list[1];// = {2.0}
  233. strategy_list[0] = opts->minuit_strategy;
  234. minuit_one->mnexcm("SET STR", strategy_list, 1, errorcode);
  235. //prob = probability;
  236. pdfs = probs;
  237. params = parms;
  238. events = ev;
  239. //make sure to reduce output for blind analysis
  240. if (is_blind()) minuit_one->SetPrintLevel(-1);
  241. else if (spdlog_debug()) minuit_one->SetPrintLevel(0);
  242. else minuit_one->SetPrintLevel(-1);
  243. reset_param_values();
  244. //this was originally before the reset... put here to catch reset of swave
  245. for (unsigned int i=0; i<pdfs.size(); i++){
  246. pdfs.at(i)->init(params.at(i));
  247. }
  248. //update cached efficiencies in three situations
  249. //1. q2 fixed and regular acceptance
  250. //2. unfolded fit to determine the weight=1/eff
  251. //3. per event norm
  252. //cache fis
  253. if (opts->cache_fis){
  254. spdlog::info("Caching fis");
  255. for (unsigned int i = 0; i < pdfs.size(); i++){
  256. pdfs.at(i)->update_cached_integrated_fis(params.at(i));
  257. }
  258. }
  259. for (unsigned int i = 0; i < pdfs.size(); i++){
  260. parameter* effq2 = params.at(i)->get_parameter("eff_q2");
  261. bool q2fixed = false;
  262. if (effq2) q2fixed = (effq2->get_step_size() == 0.0);
  263. if ((q2fixed && opts->use_angular_acc) || opts->weighted_fit || opts->use_event_norm){
  264. pdfs.at(i)->update_cached_efficiencies(params.at(i), events.at(i));
  265. }
  266. }
  267. //per event xis
  268. if (opts->use_event_norm){
  269. for (unsigned int i = 0; i < pdfs.size(); i++){
  270. pdfs.at(i)->update_cached_xis(params.at(i), events.at(i));
  271. }
  272. }
  273. //get empirical factor
  274. empirical_constant = 0.0;
  275. if (opts->shift_lh){
  276. unsigned int the_size=0;
  277. for (unsigned int i=0; i<ev.size(); i++) the_size += ev.at(i)->size();
  278. empirical_constant = likelihood()/the_size;
  279. }
  280. spdlog::debug("Determined empirical constant of: {0:f}", empirical_constant);
  281. int result = 0;
  282. unsigned int varied_params = 0;
  283. //determine the number of varied parameters
  284. //count only parameters that are not common among the PDFs!
  285. for (unsigned int i = 0; i < params.size(); i++){
  286. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  287. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0 && !is_common(params.at(i)->get_parameter(j)->get_name())){
  288. varied_params++;
  289. spdlog::debug("[PDF{0:d}]\tPAR='"+params.at(i)->get_parameter(j)->get_name()+"'\trange=[{1:f} - {2:f}]", i+1, params.at(i)->get_parameter(j)->get_min(), params.at(i)->get_parameter(j)->get_max());
  290. }
  291. }
  292. }
  293. spdlog::debug("Count number of varied parameters: {0:d} PDF(s)", params.size());
  294. spdlog::debug("Number of varied, non-common parameters: {0:d}", varied_params);
  295. //assert(!(varied_params % params.size()));
  296. //add the parameters to the counter, that are common AND varied
  297. for (unsigned int i = 0; i < common_params.size(); i++){
  298. bool is_varied = false;
  299. for (unsigned int j = 0; j < params.size(); j++){
  300. for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){
  301. if (common_params.at(i) == params.at(j)->get_parameter(k)->get_name() && params.at(j)->get_parameter(k)->get_step_size() != 0.0){
  302. is_varied = true;
  303. spdlog::debug("[COMMON]\tPAR='"+params.at(j)->get_parameter(k)->get_name()+"'\trange=[{0:f} - {1:f}]", params.at(j)->get_parameter(k)->get_min(), params.at(j)->get_parameter(k)->get_max());
  304. break;
  305. }
  306. }
  307. if(is_varied)break;
  308. }
  309. if (is_varied){
  310. varied_params++;
  311. }
  312. }
  313. spdlog::info("Including common parameters, number of varied parameters is: {0:d}", varied_params);
  314. //open texFile
  315. std::ofstream myFile;
  316. if (index != ""){
  317. open_Latex_noteFile(latex_fitterFile(index), myFile);
  318. }
  319. //Use Markov Chain Monte Carlo //TODO when bored, move this to a separate function
  320. if (opts->use_mcmc){
  321. unsigned int nlength = 10000;
  322. //just run a single chain
  323. std::vector<TVectorD> chain;//(nlength);
  324. for (unsigned int i=0; i<nlength; i++){
  325. chain.push_back(TVectorD(varied_params));
  326. }
  327. TVectorD current(varied_params);
  328. //fill in starting values
  329. //TMatrixDSym S1(nparams);
  330. //S1.IdentityMatrix();
  331. //S1 *= 0.1;
  332. TMatrixDSym SNminusone(varied_params);
  333. SNminusone.UnitMatrix();
  334. //SNminusone *= 0.1; //might be more appropriate for the problem
  335. unsigned int idx = 0;
  336. for (unsigned int i = 0; i < params.size(); i++){
  337. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  338. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0 && !is_common(params.at(i)->get_parameter(j)->get_name())){
  339. current[idx] = params.at(i)->get_parameter(j)->get_value();
  340. SNminusone(idx, idx) = params.at(i)->get_parameter(j)->get_step_size();//this is actually quite clever
  341. idx++;
  342. }
  343. }
  344. }
  345. spdlog::debug("nrows {0:d}\tvaried_params {1:d}", current.GetNrows(), varied_params);
  346. for(int i=0; i<current.GetNrows(); i++) spdlog::debug("{0:d}", current[i]);
  347. TVectorD last(current);
  348. double alphastar = 0.234;
  349. double last_llh = likelihood();
  350. double minimum_llh = last_llh;
  351. TVectorD minimum(current);
  352. TMatrixDSym SN(SNminusone);
  353. TRandom3 * rnd = new TRandom3();
  354. spdlog::info("Starting Markov chain");
  355. //produce markov chain of the desired length
  356. for (unsigned int i=0; i<nlength; i++){
  357. if ((i*100)%nlength == 0) std::cout << i*100/double(nlength) << "%" << std::endl;
  358. //should optionally repeat this, until values are in parameter range
  359. TVectorD WN(varied_params);
  360. bool finished = false;
  361. while (!finished){//repeat until we are inside the boundaries
  362. //get random vector
  363. for (int j=0; j<WN.GetNrows(); j++){
  364. WN[j] = rnd->Gaus(0.0, 1.0);//could also use students t distribution
  365. }
  366. //shift depends on SNminusone
  367. TVectorD SW(SNminusone*WN);
  368. current = last + SW;
  369. finished = true;
  370. //this will disallow parameters outside the allowed range
  371. const bool constrain_parameters = true;
  372. if (constrain_parameters){
  373. idx = 0;
  374. for (unsigned int j = 0; j < params.size(); j++){
  375. for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){
  376. if (params.at(j)->get_parameter(k)->get_step_size() != 0.0 && !is_common(params.at(j)->get_parameter(k)->get_name())){
  377. if (current[idx] > params.at(j)->get_parameter(k)->get_max() || current[idx] < params.at(j)->get_parameter(k)->get_min()){
  378. finished = false;
  379. }
  380. idx++;
  381. }
  382. }
  383. }
  384. }
  385. }
  386. spdlog::debug("event {0:d}", i);
  387. //convert index back to parameter* and set to current point
  388. idx = 0;
  389. for (unsigned int j = 0; j < params.size(); j++){
  390. for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){
  391. if (params.at(j)->get_parameter(k)->get_step_size() != 0.0 && !is_common(params.at(j)->get_parameter(k)->get_name())){
  392. params.at(j)->get_parameter(k)->set_value(current[idx]);
  393. idx++;
  394. }
  395. }
  396. }
  397. for (unsigned int j=0; j<pdfs.size(); j++){//check if this is needed!
  398. pdfs.at(j)->init(params.at(j));
  399. }
  400. //compute likelihood of current point
  401. double current_llh = likelihood();
  402. double r = rnd->Rndm();
  403. double alpha = std::min(1.0, exp(0.5*(last_llh-current_llh)));//llhs are in fact Sum_i -2*log(P_i)
  404. //debug output
  405. if (spdlog_debug()){
  406. for (int i=0; i<current.GetNrows(); i++) std::cout << current[i] << " ";
  407. std::cout << std::endl;
  408. }
  409. //check if current point is accepted
  410. spdlog::debug("accept event?");
  411. if (r < alpha){
  412. chain.at(i) = current;
  413. last = current;
  414. last_llh = current_llh;
  415. }
  416. else{
  417. chain.at(i) = last;
  418. //last stays last
  419. }
  420. //debugging output
  421. spdlog::debug("current_llh {0:f}\t last_llh {1:f}" + std::string((r<alpha) ? " accepted " : " rejected "), current_llh, last_llh);
  422. //check wether a new likelihood minimum is found and set if this is the case
  423. if (current_llh < minimum_llh){
  424. minimum = current;
  425. minimum_llh = current_llh;
  426. }
  427. //update SN
  428. TMatrixDSym SNminusoneT(SNminusone);
  429. SNminusoneT.T();
  430. double etan = std::min(1.0, varied_params*pow(double(i), -2.0/3.0));
  431. TMatrixDSym WNWNT(varied_params);
  432. WNWNT.Zero();
  433. for (int row = 0; row < WNWNT.GetNrows(); row++){
  434. for (int col = 0; col < WNWNT.GetNcols(); col++){
  435. WNWNT[row][col] = WN[row]*WN[col]/WN.Norm2Sqr();
  436. }
  437. }
  438. //TMatrixDSym SNSNT(identity + WNWNT*etan*(alpha-alphastar));
  439. TMatrixDSym SNSNT(varied_params);
  440. SNSNT.UnitMatrix();
  441. SNSNT += WNWNT*etan*(alpha-alphastar);
  442. SNSNT = SNSNT.Similarity(SNminusone);
  443. TDecompChol chol(SNSNT);
  444. bool success = chol.Decompose();
  445. assert(success);
  446. TMatrixD SNT = chol.GetU();
  447. TMatrixD SN(SNT);
  448. SN.T();
  449. for (int row = 0; row < SN.GetNrows(); row++){
  450. for (int col = 0; col < SN.GetNcols(); col++){
  451. SNminusone(row,col) = SN(row,col);
  452. }
  453. }
  454. }
  455. //best spot found
  456. spdlog::info("lowest point found at llh of {0:f}\n", minimum_llh);
  457. if (spdlog_info()){
  458. for (int i=0; i<minimum.GetNrows(); i++) std::cout << minimum[i] << " ";
  459. std::cout << std::endl;
  460. }
  461. //mean
  462. spdlog::info("mean point at");
  463. TVectorD mean(varied_params);
  464. mean.Zero();
  465. for (unsigned int i=0; i<nlength; i++){
  466. TVectorD v(chain.at(i));
  467. v *= 1.0/double(nlength);
  468. mean += v;
  469. }
  470. if (spdlog_info()){
  471. for (int i=0; i<mean.GetNrows(); i++) std::cout << mean[i] << std::endl;
  472. std::cout << std::endl;
  473. }
  474. //rms
  475. spdlog::info("rms is ");
  476. TVectorD rms(varied_params);
  477. rms.Zero();
  478. for (unsigned int i=0; i<nlength; i++){
  479. TVectorD v(chain.at(i)-mean);
  480. v.Sqr();
  481. v *= 1.0/double(nlength);
  482. rms += v;
  483. }
  484. rms.Sqrt();
  485. if (spdlog_info()){
  486. for (int i=0; i<rms.GetNrows(); i++) std::cout << rms[i] << " ";
  487. std::cout << std::endl;
  488. }
  489. //get covariance matrix estimate from matrix SN
  490. spdlog::debug("matrix SNminousone");
  491. if (spdlog_debug()){
  492. for (int row = 0; row < SNminusone.GetNrows(); row++){
  493. for (int col = 0; col < SNminusone.GetNcols(); col++) std::cout << std::setw(8) << SNminusone(row,col) << " ";
  494. std::cout << std::endl;
  495. }
  496. }
  497. TMatrixD SNminusoneT(SNminusone);
  498. SNminusoneT.T();
  499. TMatrixD cov = SNminusone*SNminusoneT;
  500. spdlog::debug("matrix cov");
  501. if (spdlog_debug()){
  502. for (int row = 0; row < cov.GetNrows(); row++){
  503. for (int col = 0; col < cov.GetNcols(); col++) std::cout << std::setw(8) << cov(row,col) << " ";
  504. std::cout << std::endl;
  505. }
  506. }
  507. spdlog::debug("errors from matrix cov");
  508. if (spdlog_debug()){
  509. for (int row = 0; row < cov.GetNrows(); row++)std::cout << sqrt(cov(row,row)) << " ";
  510. std::cout << std::endl;
  511. }
  512. //proper estimate of best point and uncertainties from projections
  513. unsigned int nbins = 1000;
  514. TH1D* histos[varied_params];
  515. idx = 0;
  516. for (unsigned int j = 0; j < params.size(); j++){
  517. for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){
  518. if (params.at(j)->get_parameter(k)->get_step_size() != 0.0 && !is_common(params.at(j)->get_parameter(k)->get_name())){
  519. std::ostringstream hname;
  520. hname << "hist" << idx;
  521. histos[idx] = new TH1D(hname.str().c_str(), ";;", nbins,
  522. params.at(j)->get_parameter(k)->get_min(),
  523. params.at(j)->get_parameter(k)->get_max());
  524. idx++;
  525. }
  526. }
  527. }
  528. //loop over chain and fill histos
  529. for (unsigned int i=0; i<nlength; i++){
  530. TVectorD v(chain.at(i));
  531. for (int row = 0; row < v.GetNrows(); row++) histos[row]->Fill(v[row]);
  532. }
  533. if (true){//smooth all histos
  534. const unsigned int ntimes = 1;
  535. for (unsigned int i=0; i<varied_params; i++) histos[i]->Smooth(ntimes);
  536. }
  537. if (spdlog_debug()){ //If in debug mode, just save the histos for now
  538. for (unsigned int i=0; i<varied_params; i++){
  539. plotAndSave(histos[i],"c"+std::to_string(i),std::string(histos[i]->GetName()),"eps");
  540. }
  541. }
  542. //get maximum from histos (for now no smoothing) and add up highes bins until 1 sigma
  543. //probably want to add from highest bin, no?
  544. TVectorD max(varied_params);
  545. TVectorD eup(varied_params);
  546. TVectorD edown(varied_params);
  547. for (unsigned int i=0; i<varied_params; i++){
  548. int maxbin = histos[i]->GetMaximumBin();
  549. double x = histos[i]->GetBinCenter(maxbin);
  550. double left = histos[i]->GetBinLowEdge(maxbin);
  551. double right = histos[i]->GetBinLowEdge(maxbin+1);
  552. double sum = histos[i]->GetBinContent(maxbin);
  553. histos[i]->SetBinContent(maxbin, 0.0);
  554. bool finished = sum/nlength > ONE_SIGMA;
  555. while (!finished){
  556. maxbin = histos[i]->GetMaximumBin();
  557. double nx = histos[i]->GetBinCenter(maxbin);
  558. sum += histos[i]->GetBinContent(maxbin);
  559. histos[i]->SetBinContent(maxbin, 0.0);
  560. if (nx > right) right = histos[i]->GetBinLowEdge(maxbin+1);
  561. if (nx < left) left = histos[i]->GetBinLowEdge(maxbin);
  562. finished = sum/nlength > ONE_SIGMA;
  563. }
  564. max[i] = x;
  565. eup[i] = right-x;
  566. edown[i] = left-x;
  567. delete histos[i];
  568. }
  569. //output of the newly determined mean and errors
  570. if (spdlog_info()){
  571. spdlog::info("max");
  572. for (int i=0; i<max.GetNrows(); i++) std::cout << max[i] << " ";
  573. std::cout << std::endl;
  574. spdlog::info("eup");
  575. for (int i=0; i<eup.GetNrows(); i++) std::cout << eup[i] << " ";
  576. std::cout << std::endl;
  577. spdlog::info("edown");
  578. for (int i=0; i<edown.GetNrows(); i++) std::cout << edown[i] << " ";
  579. std::cout << std::endl;
  580. }
  581. idx = 0;
  582. for (unsigned int j = 0; j < params.size(); j++){
  583. for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){
  584. if (params.at(j)->get_parameter(k)->get_step_size() != 0.0 && !is_common(params.at(j)->get_parameter(k)->get_name())){
  585. params.at(j)->get_parameter(k)->set_value(max[idx]);
  586. params.at(j)->get_parameter(k)->set_error(0.5*(fabs(eup[idx])+fabs(edown[idx])));
  587. params.at(j)->get_parameter(k)->set_error_up(eup[idx]);
  588. params.at(j)->get_parameter(k)->set_error_down(edown[idx]);
  589. //params.at(j)->get_parameter(k)->set_value(mean[idx]);
  590. //params.at(j)->get_parameter(k)->set_error(sqrt(cov(idx,idx)));
  591. idx++;
  592. }
  593. }
  594. }
  595. //MCMC always returns status OK
  596. return 300;//this means all ok
  597. }
  598. //When using no Markov Chain MC: Nominal fit procedure
  599. else{ //TODO when bored, move this to a separate function
  600. spdlog::debug("Starting Fit Procedure");
  601. int errorcode;
  602. //double eps[1] = {1.0e-10};
  603. //minuit_one->mnexcm("SET EPS", eps, 1, errorcode);
  604. //double strategy_list[2] = {0,0.1};
  605. double migrad_options[2] = {MIG_MAX_CALLS, MIG_TOLERANCE}; //Maxcalls and tolerance
  606. // The default tolerance is 0.1, and the minimization will stop when the estimated vertical distance to the minimum (EDM) is less than 0.001*[tolerance]*UP(see SET ERR)
  607. if (opts->simplex_prerun){
  608. spdlog::info("Running Simplex");
  609. minuit_one->mnexcm("SIM", migrad_options, 2, errorcode);
  610. }
  611. minuit_one->mnexcm("MIG", migrad_options, 2, errorcode);
  612. result = errorcode;
  613. printMigradStatus(result);
  614. spdlog::warn("EDM: {0:f}", minuit_one->fEDM);
  615. if (opts->hesse_postrun){
  616. spdlog::info("Starting hesse");
  617. minuit_one->mnhess();
  618. if (spdlog_debug()) minuit_one->mnmatu(1); //Print the correlation matrix, they are annoying so turned off for now
  619. }
  620. int nfree, ntot, status_cov;
  621. double m_fcn, m_edm, up;
  622. minuit_one->mnstat(m_fcn, m_edm, up, nfree, ntot, status_cov);
  623. //status_cov 0=not calculated, 1=approximation, 2=full but forced pos. def., 3=full accurate
  624. result += 100*status_cov;
  625. if (opts->hesse_postrun){ //Hesse calculates the 2nd derivative of the likelihood profile to assign the correct systematics
  626. printCovMatrixStatus(status_cov,false);
  627. }
  628. double tmp_cov[varied_params * varied_params];
  629. //spdlog::info("nvaried params = " << varied_params);;
  630. minuit_one->mnemat(tmp_cov, varied_params);
  631. if (opts->weighted_fit && opts->asymptotic){//perform correction according to 1911.01303 Eq. 18
  632. spdlog::debug("Starting an assymptotic treatment.");
  633. assert(!(opts->squared_hesse));//TODOCL i think hesse_postrun is fine (and will lead to better estimate for the weighted Hessian)
  634. //weighted hesse matrix is available as tmp_cov
  635. //need to iterate over all events
  636. //need to evaluate first derivatives at central values
  637. //events in different pdfs are independently distributed
  638. //just should count every event separately
  639. TMatrixDSym V(varied_params, tmp_cov);//weighted covariance matrix
  640. TMatrixDSym C(varied_params);//, 0.0);//tmp_cov_sq);
  641. for (unsigned int k=0; k<varied_params; k++){
  642. for (unsigned int l=0; l<varied_params; l++){
  643. C(k,l) = 0.0;
  644. }
  645. }
  646. //save best fit values
  647. spdlog::debug("Saving best fit values.");
  648. std::vector<std::string> param_names;
  649. std::vector<double> param_values;
  650. std::vector<double> eps(varied_params, 1.0e-5);
  651. for (unsigned int i = 0; i < params.size(); i++){
  652. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  653. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){
  654. //if the parameter is common, only add name once
  655. if (!is_common(params.at(i)->get_parameter(j)->get_name()) || is_first(params.at(i)->get_parameter(j)->get_name(), i, j)){
  656. double v,e;
  657. std::string par_name = params.at(i)->get_parameter(j)->get_name();
  658. unsigned int idx = first_minuit_index(par_name);
  659. minuit_one->GetParameter(idx, v, e);
  660. param_names.push_back(par_name);
  661. param_values.push_back(v);
  662. spdlog::debug(par_name+": {0:f}", v);
  663. }
  664. }
  665. }
  666. }
  667. //the optimized version varies the parameter in the outer loop and performs the update_cached_normalisation only once for + and -
  668. //loop over data samples
  669. spdlog::debug("Looping over data samples.");
  670. std::vector<double> lh_extended_nsig(events.size(),0.0);
  671. std::vector<double> lh_extended_nbkg(events.size(),0.0);
  672. std::vector<double> lh_extended_nsigbar(events.size(),0.0);
  673. std::vector<double> lh_extended_nbkgbar(events.size(),0.0);
  674. for (unsigned int i = 0; i<events.size(); i++){
  675. //save derivative for every event, every param
  676. if (i%10==0) spdlog::trace("Event {0:d}",i);
  677. std::vector<std::vector<double> > derivs; //first idx varied param, second index event
  678. for (unsigned int k=0; k<varied_params; k++){
  679. //only want to do this for params.at(i), other data samples use the other param set
  680. fcnc::parameter* varied = params.at(i)->get_parameter(param_names.at(k));
  681. if (!varied){
  682. std::vector<double> derivs_k(events.at(i)->size(),0.0);
  683. derivs.push_back(derivs_k);
  684. continue;
  685. }
  686. //set varied parameter + everywhere
  687. varied->set_value(param_values.at(k)+eps.at(k));
  688. //cache integrals
  689. pdfs.at(i)->update_cached_normalization(params.at(i));
  690. if (opts->use_event_norm) pdfs.at(i)->update_cached_normalization(params.at(i), events.at(i));
  691. //TODOCL
  692. spdlog::debug("Getting likelihood.");
  693. likelihood();//this is supposed to only get the extended term, for the + varied parameters, should be fast enough //This doesn't do anything!
  694. //loop over lh_plus events
  695. std::vector<double> loglh_plus_k(events.at(i)->size(),0.0);
  696. for (unsigned int j = 0; j < events.at(i)->size(); j++){
  697. //for every event do finite differences
  698. const fcnc::event meas = events.at(i)->at(j);
  699. double probability = 0.0;
  700. probability = pdfs.at(i)->prob(params.at(i), meas);
  701. if (probability > 0.0) loglh_plus_k.at(j) = -TMath::Log(probability);
  702. //TODOCL
  703. if (meas.cp_conjugate){ //TODOCL CHECK!! //LEONS COMMENT meas.cp_conjugate corresponds to n_sig !!!!!!!
  704. loglh_plus_k.at(j) += -TMath::Log(lh_extended_nsig.at(i)+lh_extended_nbkg.at(i));
  705. }
  706. else{
  707. loglh_plus_k.at(j) += -TMath::Log(lh_extended_nsigbar.at(i)+lh_extended_nbkgbar.at(i));
  708. }
  709. }
  710. //set varied parameter - everywhere
  711. varied->set_value(param_values.at(k)-eps.at(k));
  712. //cache integrals
  713. pdfs.at(i)->update_cached_normalization(params.at(i));
  714. if (opts->use_event_norm) pdfs.at(i)->update_cached_normalization(params.at(i), events.at(i));
  715. //TODOCL
  716. likelihood();//this is supposed to only get the extended term, for the - varied parameters, should be fast enough
  717. //loop over lh_minus events
  718. std::vector<double> loglh_minus_k(events.at(i)->size(),0.0);
  719. // for (unsigned int j = 0; j < events.at(i)->size(); j++){
  720. // //for every event do finite differences
  721. // const fcnc::event meas = events.at(i)->at(j);
  722. // double probability = 0.0;
  723. // probability = pdfs.at(i)->prob(params.at(i), meas);
  724. // if (probability > 0.0) loglh_minus_k.at(j) = -TMath::Log(probability);
  725. // //TODOCL
  726. // if (meas.cp_conjugate){ //TODOCL CHECK!! //LEONS COMMENT meas.cp_conjugate corresponds to n_sig !!!!!!!
  727. // loglh_minus_k.at(j) += -TMath::Log(lh_extended_nsig.at(i)+lh_extended_nbkg.at(i));
  728. // }
  729. // else{
  730. // loglh_minus_k.at(j) += -TMath::Log(lh_extended_nsigbar.at(i)+lh_extended_nbkgbar.at(i));
  731. // }
  732. // }
  733. //calculate derivatives for all events
  734. spdlog::debug("Calculating derivatives for all events");
  735. std::vector<double> derivs_k(events.at(i)->size(),0.0);
  736. for (unsigned int j = 0; j < events.at(i)->size(); j++){
  737. derivs_k.at(j) = (loglh_plus_k.at(j)-loglh_minus_k.at(j))/(2.0*eps.at(k));
  738. }
  739. spdlog::trace("Derivatives:+ "+convert_vector_to_string(derivs_k));
  740. derivs.push_back(derivs_k);
  741. //reset varied parameter everywhere
  742. varied->set_value(param_values.at(k));
  743. //cache integrals
  744. pdfs.at(i)->update_cached_normalization(params.at(i));
  745. if (opts->use_event_norm){
  746. pdfs.at(i)->update_cached_normalization(params.at(i), events.at(i));
  747. }
  748. }
  749. //afterwards determine derivative via finite differences
  750. spdlog::debug("Calculating derivatives for finite differences");
  751. //and save matrix of squared first derivatives
  752. for (unsigned int j = 0; j < events.at(i)->size(); j++){
  753. //for every event do finite differences
  754. const fcnc::event meas = events.at(i)->at(j);
  755. for (unsigned int k=0; k<varied_params; k++){
  756. for (unsigned int l=0; l<varied_params; l++){
  757. C(k,l) += meas.weight*meas.weight*derivs.at(k).at(j)*derivs.at(l).at(j);
  758. }
  759. }
  760. }
  761. }
  762. TMatrixD VCV(V,TMatrixD::kMult,TMatrixD(C,TMatrixD::kMult,V));
  763. TMatrixDSym VCVsym(varied_params);
  764. spdlog::debug("printing corrected covariance matrix");
  765. for (unsigned int i=0; i<varied_params; i++){
  766. for (unsigned int j=0; j<varied_params; j++) {
  767. if (spdlog_debug()) std::cout << std::scientific << std::setw(9) << std::setprecision(2) << VCV(i,j) << " ";
  768. VCVsym(i,j) = 0.5*(VCV(i,j)+VCV(j,i));//no check for now
  769. tmp_cov[varied_params*j + i] = VCVsym(i,j);//save corrected covariance matrix
  770. }
  771. if (spdlog_debug()) std::cout << std::endl;
  772. }
  773. }
  774. if (opts->weighted_fit && opts->squared_hesse){
  775. square_weights = true;
  776. spdlog::info("Starting hesse with squared weights");
  777. minuit_one->mnhess();
  778. //check that this went fine
  779. double m_sq_fcn, m_sq_edm, sq_up;
  780. int status_sq_cov;
  781. minuit_one->mnstat(m_sq_fcn, m_sq_edm, sq_up, nfree, ntot, status_sq_cov);
  782. printCovMatrixStatus(status_sq_cov,true);
  783. //change status to invalied if squared weighted fit failed
  784. if (status_cov != status_sq_cov){
  785. result -= 100*status_cov;
  786. result += 100*((status_cov < status_sq_cov) ? status_cov : status_sq_cov);
  787. }
  788. // minuit_one->mnmatu(1);//this also sets something internal in minuit! getparameter seems to get its error from here!
  789. double tmp_cov_sq[varied_params * varied_params];
  790. minuit_one->mnemat(tmp_cov_sq, varied_params);
  791. //lets use root classes for the matrix inversion
  792. TMatrixDSym V(varied_params, tmp_cov);//tmp_cov
  793. TMatrixDSym C(varied_params, tmp_cov_sq);
  794. double det=0.0;
  795. C.Invert(&det);
  796. TMatrixD VCV(V,TMatrixD::kMult,TMatrixD(C,TMatrixD::kMult,V));
  797. TMatrixDSym VCVsym(varied_params);
  798. spdlog::info("printing corrected covariance matrix");
  799. for (unsigned int i=0; i<varied_params; i++){
  800. for (unsigned int j=0; j<varied_params; j++){
  801. if (spdlog_debug()){
  802. std::cout << std::scientific << std::setw(9) << std::setprecision(2) << VCV(i,j) << " ";
  803. }
  804. VCVsym(i,j) = 0.5*(VCV(i,j)+VCV(j,i));//no check for now
  805. tmp_cov[varied_params*j + i] = VCVsym(i,j);//save corrected covariance matrix
  806. }
  807. if (spdlog_debug()) std::cout << std::endl;
  808. }
  809. square_weights = false;
  810. }
  811. //to get the correct latex names
  812. std::vector<std::string> varied_names;
  813. for (unsigned int i = 0; i < params.size(); i++){
  814. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  815. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){//if the parameter is common, only add name once
  816. if (!is_common(params.at(i)->get_parameter(j)->get_name()) || is_first(params.at(i)->get_parameter(j)->get_name(), i, j)){
  817. varied_names.push_back(params.at(i)->get_parameter(j)->get_description());
  818. }
  819. }
  820. }
  821. }
  822. //printing error matrix
  823. if (spdlog_debug()){
  824. spdlog::debug("printing error matrix");
  825. for (unsigned int x = 0; x < varied_params; x++) std::cout << "\tvar" << x << " ";
  826. std::cout << std::endl;
  827. for (unsigned int y = 0; y < varied_params; y++){
  828. std::cout << "var" << y;
  829. for (unsigned int x = 0; x < varied_params; x++){
  830. std::cout << " " << std::scientific << std::setw(9) << std::setprecision(2) << tmp_cov[varied_params*y + x];
  831. }
  832. std::cout << std::endl;
  833. }
  834. }
  835. //calculating correlation matrix from error matrix
  836. double cor[varied_params*varied_params];
  837. for (unsigned int x = 0; x < varied_params; x++){
  838. for (unsigned int y = 0; y < varied_params; y++){
  839. cor[varied_params*y + x] = tmp_cov[varied_params*y + x]
  840. /(sqrt(fabs(tmp_cov[varied_params*x + x]))*sqrt(fabs(tmp_cov[varied_params*y + y])));
  841. }
  842. }
  843. //printing correlation matrix
  844. if (index != ""){
  845. spdlog::info("printing correlation matrix");
  846. myFile << "Run: " << opts->run << std::endl;
  847. myFile << "\\begin{tabular}{c";
  848. for (unsigned int x = 0; x < varied_params; x++){
  849. myFile << "c";
  850. }
  851. myFile << "} \\hline" << std::endl;
  852. myFile << " ";
  853. for (unsigned int x = 0; x < varied_params; x++){
  854. myFile << " & $" << varied_names.at(x) << "$";
  855. }
  856. myFile << "\\\\ \\hline" << std::endl;
  857. bool upper_half = true;
  858. for (unsigned int y = 0; y < varied_params; y++){
  859. myFile << std::setw(20) << "$" << varied_names.at(y) << "$";
  860. for (unsigned int x = 0; x < varied_params; x++){
  861. if (x >= y || !upper_half){
  862. if (fabs(cor[varied_params*y + x]) >= 0.005){
  863. myFile << " & " << std::fixed << std::setw(5) << std::setprecision(2) << cor[varied_params*y + x];
  864. }
  865. else myFile << " & " << std::setw(5) << "-";
  866. }
  867. else myFile << " & " << std::setw(5) << " ";
  868. }
  869. myFile << " \\\\ " << std::endl;
  870. }
  871. myFile <<"\\hline \\end{tabular}" << std::endl;
  872. }
  873. //saves correlations for all parameters
  874. for (unsigned int i = 0; i < params.size(); i++){
  875. for (unsigned int j=0; j < params.at(i)->nparameters(); j++){
  876. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){
  877. params.at(i)->get_parameter(j)->correlations.clear();
  878. unsigned int apary = 0;
  879. for (unsigned int y=0; y < varied_params; y++){
  880. if (varied_names.at(y) == params.at(i)->get_parameter(j)->get_description()){
  881. apary = y;
  882. break;
  883. }
  884. }
  885. for (unsigned int x=0; x < varied_params; x++)
  886. params.at(i)->get_parameter(j)->correlations.push_back(cor[varied_params*apary + x]);
  887. }
  888. }
  889. }
  890. //minos error analysis
  891. if (opts->minos_errors && (result%100) == 0){//migrad is successfull
  892. spdlog::info("Starting Minos error analysis");
  893. std::vector<int> indices;
  894. for (unsigned int i = 0; i < params.size(); i++){
  895. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  896. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0 && params.at(i)->get_parameter(j)->get_minos()){
  897. std::string par_name = params.at(i)->get_parameter(j)->get_name();
  898. unsigned int idx = 0;
  899. if(is_common(par_name) || opts->use_individual_param_names) idx = first_minuit_index(par_name);
  900. else idx = nth_minuit_index(par_name, i+1);
  901. indices.push_back(idx);
  902. }
  903. }
  904. }
  905. if (indices.size() > 0){//run minos just for subset of parameters
  906. spdlog::info("MINOS SUBSET");
  907. int errorcode;
  908. /*
  909. double migrad_options[indices.size()+1];
  910. migrad_options[0] = 100000000.0;
  911. for (unsigned int i = 0; i < indices.size(); i++)
  912. //migrad_options[i+1] = indices.at(i);
  913. migrad_options[i+1] = indices.at(i)+1;
  914. minuit_one->mnexcm("MINO", migrad_options, indices.size()+1, errorcode);
  915. */
  916. for (unsigned int i = 0; i < indices.size(); i++){
  917. double migrad_options[2];
  918. migrad_options[0] = 100000000.0;
  919. migrad_options[1] = indices.at(i)+1;
  920. minuit_one->mnexcm("MINO", migrad_options, 2, errorcode);
  921. }
  922. }
  923. else minuit_one->mnmnos();//do minos error analysis on all parameters
  924. //write MINOS errors to parameters
  925. for (unsigned int i = 0; i < params.size(); i++){
  926. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  927. double e_up, e_down, parab, gcc;
  928. if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){
  929. std::string par_name = params.at(i)->get_parameter(j)->get_name();
  930. unsigned int idx = 0;
  931. if(is_common(par_name) || opts->use_individual_param_names) idx = first_minuit_index(par_name);
  932. else idx = nth_minuit_index(par_name, i+1);
  933. minuit_one->mnerrs(idx, e_up, e_down, parab, gcc);
  934. params.at(i)->get_parameter(j)->set_error_up(e_up);
  935. params.at(i)->get_parameter(j)->set_error_down(e_down);
  936. }
  937. }
  938. }
  939. }
  940. //finally extract fitted parameters from minuit
  941. for (unsigned int i = 0; i < params.size(); i++){
  942. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  943. double v,e;
  944. std::string par_name = params.at(i)->get_parameter(j)->get_name();
  945. unsigned int idx;
  946. if(is_common(par_name) || opts->use_individual_param_names) idx = first_minuit_index(par_name);
  947. else idx = nth_minuit_index(par_name, i + 1);
  948. spdlog::trace("[PDF{0:d}]\tPAR{1:d}:\t{2:s}\tTMinuit_idx: {3:d}", i, j, par_name, idx);
  949. minuit_one->GetParameter(idx, v, e);
  950. params.at(i)->get_parameter(j)->set_value(v);
  951. params.at(i)->get_parameter(j)->set_error(e);
  952. if (opts->weighted_fit){
  953. //this method is approximate for parameters with limited range!
  954. int iidx = minuit_one->fNiofex[idx] - 1;
  955. if (iidx>=0){
  956. e = sqrt(fabs(tmp_cov[iidx*varied_params+iidx]));
  957. params.at(i)->get_parameter(j)->set_error(e);
  958. }
  959. }
  960. }
  961. }
  962. if (spdlog_trace()){
  963. for (unsigned int i = 0; i < params.size(); i++){
  964. params.at(i)->print_parameters();
  965. }
  966. }
  967. if (opts->project){
  968. for (unsigned int i = 0; i<plots.size(); i++)
  969. plots.at(i)->plot_data(pdfs.at(i), params.at(i), events.at(i), index);
  970. }
  971. spdlog::info("Fit procedure finished");
  972. }
  973. //Close Latex file
  974. if (index != "") myFile.close();
  975. return result;
  976. }
  977. void fcnc::fitter::define_parameter(int i, const parameter & p){
  978. if (p.get_unlimited()){
  979. minuit_one->DefineParameter(i, p.get_mn_name(), p(), p.get_step_size(), 0.0, 0.0);
  980. }
  981. else{
  982. minuit_one->DefineParameter(i, p.get_mn_name(), p(), p.get_step_size(), p.get_min(), p.get_max());
  983. }
  984. }
  985. void fcnc::fitter::reset_param_values(){
  986. spdlog::debug("Resetting parameter values");
  987. minuit_one->mncler();
  988. unsigned int start_param = 0;
  989. for (unsigned int i = 0; i < params.size(); i++){
  990. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  991. if (opts->reset_start){
  992. params.at(i)->get_parameter(j)->reset_start();
  993. }
  994. std::string par_name = params.at(i)->get_parameter(j)->get_name();
  995. if (!is_common(par_name) || is_first(par_name, i, j)){
  996. define_parameter(start_param+j, *(params.at(i)->get_parameter(j)));
  997. }
  998. }
  999. start_param += params.at(i)->nparameters();
  1000. }
  1001. }
  1002. double fcnc::fitter::likelihood(){
  1003. lh_tot = 0.0;
  1004. //this is called on every parameter change
  1005. //this can never hurt, also needed in case of weighted/unfolded fit
  1006. for (unsigned int i = 0; i < pdfs.size(); i++){
  1007. pdfs.at(i)->update_cached_normalization(params.at(i));//should do this, but should buffer f1, update f1 on fit command
  1008. if(opts->use_event_norm){
  1009. pdfs.at(i)->update_cached_normalization(params.at(i), events.at(i));
  1010. }
  1011. }
  1012. //threading the likelihood determination on multiple CPU cores
  1013. if(opts->ncores > 1){
  1014. std::vector<std::thread*> threads;
  1015. for(unsigned int i = 0; i < opts->ncores; i++){
  1016. std::thread* t = new std::thread(std::bind( &fitter::likelihood_thread, this, i));
  1017. threads.push_back(t);
  1018. }
  1019. for(unsigned int i = 0; i < opts->ncores; i++) threads[i]->join();
  1020. for(unsigned int i = 0; i < opts->ncores; i++) delete threads[i];
  1021. }
  1022. else{
  1023. likelihood_thread(0);
  1024. }
  1025. if (spdlog_trace()){
  1026. unsigned int start_param = 0;
  1027. for(unsigned int i = 0; i < params.size(); i++){
  1028. for(unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  1029. if(params.at(i)->get_parameter(j)->get_step_size() != 0.0){
  1030. std::string par_name = params.at(i)->get_parameter(j)->get_name();
  1031. if(!is_common(par_name) || is_first(par_name, i, j)){
  1032. if(!params.at(i)->get_parameter(j)->is_blind()) std::cout << par_name << ":" << params.at(i)->get_parameter(j)->get_value() << " ";
  1033. else std::cout << par_name << ":" << "XXX" << " ";
  1034. }
  1035. }
  1036. }
  1037. start_param += params.at(i)->nparameters();
  1038. }
  1039. std::cout << std::endl;
  1040. }
  1041. //there is an additional term for parameters which have been measured previously
  1042. for (unsigned int i = 0; i < params.size(); i++){
  1043. for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){
  1044. const parameter* param = params.at(i)->get_parameter(j);
  1045. if (param->get_gaussian_constraint()){
  1046. if (!is_common(param->get_name()) || is_first(param->get_name(), i, j)){
  1047. double mean = param->get_previous_measurement();
  1048. double x = param->get_value();
  1049. double dup = fabs(param->get_previous_error_high());
  1050. double ddown = fabs(param->get_previous_error_low());
  1051. double sigma = (x>mean ? dup : ddown);
  1052. //spdlog::trace("mean {0:f}\tx {1:f}\tdup {2:f}\tddown {3:f}\tsigma {4:f}",mean,x,dup,ddown,sigma);
  1053. if (x>mean+dup) sigma = dup;
  1054. else if (x<mean-ddown) sigma = ddown;
  1055. else sigma = ddown + (dup-ddown)*(x-(mean-ddown))/(dup+ddown);
  1056. lh_tot += (-2.0*(-(x-mean)*(x-mean)/(2.0*sigma*sigma)));
  1057. }
  1058. }
  1059. }
  1060. }
  1061. if (opts->chisquaredstudy){
  1062. double chi2 = 0.0;
  1063. for (unsigned int i = 0; i < pdfs.size(); i++) chi2 += pdfs.at(i)->chi2(params.at(i));
  1064. lh_tot += chi2;
  1065. }
  1066. if (opts->extended_ml){
  1067. double lh_ext = 0.0;
  1068. for(unsigned int i = 0; i < params.size(); i++){
  1069. double nobs = 0.0;
  1070. parameter* pnsig = params.at(i)->get_parameter("n_sig");
  1071. parameter* pnbkg = params.at(i)->get_parameter("n_bkg");
  1072. assert(pnsig && pnbkg);
  1073. double nsig = pnsig->get_value();
  1074. double nbkg = pnbkg->get_value();
  1075. if(opts->weighted_fit){
  1076. for(unsigned int j = 0; j<events.at(i)->size(); j++){
  1077. nobs += events.at(i)->at(j).weight;
  1078. }
  1079. }
  1080. else{
  1081. nobs = events.at(i)->size();
  1082. }
  1083. double prob = TMath::Poisson(nsig+nbkg, nobs);
  1084. if(prob == 0.0) prob = 1e-100;
  1085. lh_ext += -2.0*TMath::Log( prob );
  1086. if (std::isinf(lh_ext) || std::isnan(lh_ext)){
  1087. std::cout << "[PDF" << i << "]\t\tlh_ext = " << lh_ext << "\t prob = " << prob << "\t -2log(prob) = " << -2.0*TMath::Log( prob ) << std::endl;
  1088. std::cout << "[PDF" << i << "]\t\tnsig = " << nsig << "\t n_bkg = " << nbkg << "\t nobs = " << nobs << std::endl;
  1089. assert(0);
  1090. }
  1091. }
  1092. if (std::isinf(lh_ext)){
  1093. spdlog::error("{0:0.16f}", lh_ext);
  1094. spdlog::error("lh (w/o lh_ext) = {0:0.16f}", lh_tot);
  1095. assert(0);
  1096. }
  1097. lh_tot += lh_ext;
  1098. }
  1099. if (std::isinf(lh_tot || std::isnan(lh_tot))){
  1100. spdlog::error("lh = {0:0.16f}", lh_tot);
  1101. assert(0);
  1102. }
  1103. if (spdlog_trace()) std::cout << "[debug]\t" << std::setprecision(16) << "lh = " << lh_tot << "\r" << std::flush;
  1104. return lh_tot;
  1105. }
  1106. void fcnc::fitter::likelihood_thread(int thread_id){
  1107. double probability = 0.0;
  1108. event meas;
  1109. long double result = 0.0;
  1110. for (unsigned int i = 0; i<events.size(); i++){
  1111. unsigned int min, max;
  1112. unsigned int evts_per_thread = events.at(i)->size()/opts->ncores;
  1113. //is too small for last vector!
  1114. min = evts_per_thread * thread_id;
  1115. max = evts_per_thread * (thread_id+1);
  1116. int last_thread = opts->ncores - 1;
  1117. if (thread_id == last_thread){//last thread needs to take all posibly remaining events
  1118. max = events.at(i)->size();
  1119. }
  1120. std::vector<long double> vec;
  1121. vec.reserve(max - min);
  1122. for (unsigned int j = min; j < max; j++){
  1123. meas = events.at(i)->at(j);
  1124. probability = pdfs.at(i)->prob(params.at(i), meas);
  1125. if (probability < 0.0 || std::isnan(probability) || std::isinf(probability)){
  1126. std::lock_guard<std::mutex> lock(fitter_mutex);
  1127. spdlog::info("Event probability is {0:d}", probability);
  1128. print_event(meas);
  1129. params.at(i)->print_parameters();
  1130. assert(0);
  1131. }
  1132. if (probability == 0.0){
  1133. probability = 1.0;//ignore event
  1134. }
  1135. if (probability != 0.0){
  1136. if (opts->weighted_fit){
  1137. if (square_weights) vec.push_back(-2.0 * meas.weight * meas.weight * TMath::Log(probability) - empirical_constant);//todo: does the empirical constant pose a problem here?
  1138. else vec.push_back(-2.0 * meas.weight * TMath::Log(probability) - empirical_constant);
  1139. }
  1140. else vec.push_back(-2.0 * TMath::Log(probability) - empirical_constant);
  1141. }
  1142. else if (!std::isnan(probability)){
  1143. spdlog::error("Event probability is {0:d}", probability);
  1144. print_event(meas);
  1145. assert(0);
  1146. }
  1147. else{//is inf?
  1148. vec.push_back(8.0);//is inf?//use something like prob max? log(p_min)
  1149. }
  1150. }
  1151. result += add_results<std::vector<long double>::iterator>(vec.begin(), vec.end());
  1152. }
  1153. if (opts->ncores > 1){
  1154. std::lock_guard<std::mutex> lock(fitter_mutex);
  1155. lh_tot += result;
  1156. }
  1157. else{
  1158. lh_tot += result;
  1159. }
  1160. }
  1161. //boost::mutex fitter::fitter_mutex;
  1162. std::mutex fcnc::fitter::fitter_mutex;
  1163. fcnc::fitter* fcnc::fitter::minuit_one_fitter;