musrfit  1.9.2
PFitter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 
3  PFitter.cpp
4 
5  Author: Andreas Suter
6  e-mail: andreas.suter@psi.ch
7 
8 ***************************************************************************/
9 
10 /***************************************************************************
11  * Copyright (C) 2007-2023 by Andreas Suter *
12  * andreas.suter@psi.ch *
13  * *
14  * This program is free software; you can redistribute it and/or modify *
15  * it under the terms of the GNU General Public License as published by *
16  * the Free Software Foundation; either version 2 of the License, or *
17  * (at your option) any later version. *
18  * *
19  * This program is distributed in the hope that it will be useful, *
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22  * GNU General Public License for more details. *
23  * *
24  * You should have received a copy of the GNU General Public License *
25  * along with this program; if not, write to the *
26  * Free Software Foundation, Inc., *
27  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28  ***************************************************************************/
29 
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #ifdef HAVE_GOMP
35 #include <omp.h>
36 #endif
37 
38 #include <iostream>
39 #include <iomanip>
40 #include <fstream>
41 #include <limits>
42 
43 #include <cmath>
44 
45 #include <sys/time.h>
46 
47 #include "Minuit2/FunctionMinimum.h"
48 #include "Minuit2/MnContours.h"
49 #include "Minuit2/MnHesse.h"
50 #include "Minuit2/MnMinimize.h"
51 #include "Minuit2/MnMigrad.h"
52 #include "Minuit2/MnMinos.h"
53 #include "Minuit2/MnPlot.h"
54 #include "Minuit2/MnPrint.h"
55 #include "Minuit2/MnScan.h"
56 #include "Minuit2/MnSimplex.h"
57 #include "Minuit2/MnUserParameterState.h"
58 #include "Minuit2/MinosError.h"
59 
60 #include <TCanvas.h>
61 #include <TH2.h>
62 #include <TFile.h>
63 #include <TDatime.h>
64 #include <TString.h>
65 #include <TObjArray.h>
66 #include <TObjString.h>
67 
68 #include "PFitter.h"
69 
70 
71 //+++ PSectorChisq class +++++++++++++++++++++++++++++++++++++++++++++++++++
72 
73 //--------------------------------------------------------------------------
74 // Constructor
75 //--------------------------------------------------------------------------
79 PSectorChisq::PSectorChisq(UInt_t noOfRuns) : fNoOfRuns(noOfRuns)
80 {
81  // init
82  fLast = 0.0;
83  fChisq = 0.0;
84  fExpectedChisq = 0.0;
85  fNDF = 0;
86  fFirst.resize(fNoOfRuns);
87  fChisqRun.resize(fNoOfRuns);
89  fNDFRun.resize(fNoOfRuns);
90  for (UInt_t i=0; i<fNoOfRuns; i++) {
91  fFirst[i] = 0.0;
92  fChisqRun[i] = 0.0;
93  fExpectedChisqRun[i] = 0.0;
94  fNDFRun[i] = 0;
95  }
96 }
97 
98 //--------------------------------------------------------------------------
99 // SetRunFirstTime
100 //--------------------------------------------------------------------------
107 void PSectorChisq::SetRunFirstTime(Double_t first, UInt_t idx)
108 {
109  if (idx > fNoOfRuns) {
110  std::cerr << "**WARNING** from PSectorChisq::SetRunFirstTime. It tries to set" << std::endl;
111  std::cerr << " a fgb time stamp with idx=" << idx << " which is larger than #RUNS=" << fNoOfRuns << "." << std::endl;
112  std::cerr << " Will ignore it, but you better check what is going on!" << std::endl;
113  return;
114  }
115 
116  fFirst[idx] = first;
117 }
118 
119 //--------------------------------------------------------------------------
120 // SetChisq
121 //--------------------------------------------------------------------------
128 void PSectorChisq::SetChisq(Double_t chisq, UInt_t idx)
129 {
130  if (idx > fNoOfRuns) {
131  std::cerr << "**WARNING** from PSectorChisq::SetChisq. It tries to set" << std::endl;
132  std::cerr << " a chisq with idx=" << idx << " which is larger than #RUNS=" << fNoOfRuns << "." << std::endl;
133  std::cerr << " Will ignore it, but you better check what is going on!" << std::endl;
134  return;
135  }
136 
137  fChisqRun[idx] = chisq;
138 }
139 
140 //--------------------------------------------------------------------------
141 // SetExpectedChisq
142 //--------------------------------------------------------------------------
149 void PSectorChisq::SetExpectedChisq(Double_t chisq, UInt_t idx)
150 {
151  if (idx > fNoOfRuns) {
152  std::cerr << "**WARNING** from PSectorChisq::SetExpectedChisq. It tries to set" << std::endl;
153  std::cerr << " a chisq with idx=" << idx << " which is larger than #RUNS=" << fNoOfRuns << "." << std::endl;
154  std::cerr << " Will ignore it, but you better check what is going on!" << std::endl;
155  return;
156  }
157 
158  fExpectedChisqRun[idx] = chisq;
159 }
160 
161 //--------------------------------------------------------------------------
162 // SetNDF
163 //--------------------------------------------------------------------------
170 void PSectorChisq::SetNDF(UInt_t ndf, UInt_t idx)
171 {
172  if (idx > fNoOfRuns) {
173  std::cerr << "**WARNING** from PSectorChisq::SetNDF. It tries to set" << std::endl;
174  std::cerr << " a NDF with idx=" << idx << " which is larger than #RUNS=" << fNoOfRuns << "." << std::endl;
175  std::cerr << " Will ignore it, but you better check what is going on!" << std::endl;
176  return;
177  }
178 
179  fNDFRun[idx] = ndf;
180 }
181 
182 //--------------------------------------------------------------------------
183 // GetTimeRangeFirst
184 //--------------------------------------------------------------------------
194 {
195  if (idx > fNoOfRuns)
196  return PMUSR_UNDEFINED;
197 
198  return fFirst[idx];
199 }
200 
201 //--------------------------------------------------------------------------
202 // GetChisq
203 //--------------------------------------------------------------------------
211 Double_t PSectorChisq::GetChisq(UInt_t idx)
212 {
213  if (idx >= fNoOfRuns)
214  return -1.0;
215 
216  return fChisqRun[idx];
217 }
218 
219 //--------------------------------------------------------------------------
220 // GetExpectedChisq
221 //--------------------------------------------------------------------------
229 Double_t PSectorChisq::GetExpectedChisq(UInt_t idx)
230 {
231  if (idx >= fNoOfRuns)
232  return -1.0;
233 
234  return fExpectedChisqRun[idx];
235 }
236 
237 //--------------------------------------------------------------------------
238 // GetNDF
239 //--------------------------------------------------------------------------
247 UInt_t PSectorChisq::GetNDF(UInt_t idx)
248 {
249  if (idx >= fNoOfRuns)
250  return 0;
251 
252  return fNDFRun[idx];
253 }
254 
255 //+++ PFitter class ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
256 
257 //--------------------------------------------------------------------------
258 // Constructor
259 //--------------------------------------------------------------------------
267 PFitter::PFitter(PMsrHandler *runInfo, PRunListCollection *runListCollection, Bool_t chisq_only) :
268  fChisqOnly(chisq_only), fRunInfo(runInfo), fRunListCollection(runListCollection)
269 {
270  // initialize variables
271  fIsScanOnly = true;
272  fConverged = false;
273  fUseChi2 = true; // chi^2 is the default
274 
275  fStrategy = 1; // 0=low, 1=default, 2=high
276 
277  fSectorFlag = false;
278 
279  fParams = *(runInfo->GetMsrParamList());
280  fCmdLines = *runInfo->GetMsrCommands();
281 
282  // init class variables
283  fScanAll = true;
284  fScanParameter[0] = 0;
285  fScanParameter[1] = 0;
286  fScanNoPoints = 41; // minuit2 default
287  fScanLow = 0.0; // minuit2 default, i.e. 2 std deviations
288  fScanHigh = 0.0; // minuit2 default, i.e. 2 std deviations
289  fPrintLevel = 1.0;
290 
291  // keep all the fit ranges in case RANGE command is present
292  PDoublePair rangeGlob;
294  rangeGlob.first = global->GetFitRange(0);
295  rangeGlob.second = global->GetFitRange(1);
296 
298  PDoublePair range;
299  for (UInt_t i=0; i<runs->size(); i++) {
300  range.first = (*runs)[i].GetFitRange(0);
301  range.second = (*runs)[i].GetFitRange(1);
302  if (range.first == PMUSR_UNDEFINED)
303  fOriginalFitRange.push_back(rangeGlob);
304  else
305  fOriginalFitRange.push_back(range);
306  }
307 
308  // check msr minuit commands
309  if (!CheckCommands()) {
310  return;
311  }
312 
313  // create phase bool array
314  GetPhaseParams();
315 
316  // create fit function object
317  fFitterFcn = std::make_unique<PFitterFcn>(runListCollection, fUseChi2);
318 }
319 
320 //--------------------------------------------------------------------------
321 // Destructor
322 //--------------------------------------------------------------------------
327 {
328  fCmdList.clear();
329 
330  fScanData.clear();
331 
332  fElapsedTime.clear();
333 }
334 
335 //--------------------------------------------------------------------------
336 // GetPhaseParams (private)
337 //--------------------------------------------------------------------------
343 {
344  fPhase.resize(fRunInfo->GetNoOfParams());
345  for (unsigned int i=0; i<fPhase.size(); i++)
346  fPhase[i] = false;
347 
348  // analyze theory block for parameters. Phases are present in the following
349  // default functions:
350  // user functions cannot be checked!
351  PMsrLines *theo = fRunInfo->GetMsrTheory();
352  TObjArray *tok = nullptr;
353  TObjString *ostr = nullptr;
354  TString str;
355  int pos = -1;
356  for (unsigned int i=0; i<theo->size(); i++) {
357  pos = -1;
358  TString line = theo->at(i).fLine;
359  if (line.Contains("TFieldCos") || line.Contains("tf ") ||
360  line.Contains("bessel") || line.Contains("b ") ||
361  line.Contains("skewedGss") || line.Contains("skg ") ||
362  line.Contains("staticNKTF") || line.Contains("snktf ") ||
363  line.Contains("dynamicNKTF") || line.Contains("dnktf ")) { // phase is 1st param
364  pos = 1;
365  }
366  if (line.Contains("internFld") || line.Contains("if ") ||
367  line.Contains("internBsl") || line.Contains("ib ")) { // phase is 2nd param
368  pos = 2;
369  }
370  if (line.Contains("muMinusExpTF") || line.Contains("mmsetf ")) { // phase is 5th param
371  pos = 5;
372  }
373 
374  if (pos == -1)
375  continue;
376 
377  // extract phase token
378  tok = line.Tokenize(" \t");
379  if (tok == nullptr) {
380  std::cerr << "PFitter::GetPhaseParams(): **ERROR** couldn't tokenize theory line string." << std::endl;
381  return;
382  }
383  if (tok->GetEntries() > pos) {
384  ostr = dynamic_cast<TObjString*>(tok->At(pos));
385  str = ostr->GetString();
386  }
387  // clean up
388  delete tok;
389  tok = nullptr;
390 
391  // decode phase token. It can be funX, mapX, or a number
392  if (str.Contains("fun")) { // function
393  PIntVector parVec = GetParFromFun(str);
394  for (int i=0; i<parVec.size(); i++) {
395  if (parVec[i] <= fRunInfo->GetNoOfParams())
396  fPhase[parVec[i]-1] = true;
397  }
398  } else if (str.Contains("map")) { // map
399  PIntVector parVec = GetParFromMap(str);
400  for (int i=0; i<parVec.size(); i++) {
401  if (parVec[i] <= fRunInfo->GetNoOfParams())
402  fPhase[parVec[i]-1] = true;
403  }
404  } else { // must be a number
405  int idx = str.Atoi();
406  if (idx == 0) { // something went wrong, str is not an integer
407  std::cerr << "PFitter::GetPhaseParams(): **ERROR** str=" << str.View() << " is not an integer!" << std::endl;
408  return;
409  }
410  idx -= 1; // param start at 1, vector at 0
411  if (idx >= fRunInfo->GetNoOfParams()) { // idx is out-of-range
412  std::cerr << "PFitter::GetPhaseParams(): **ERROR** idx=" << idx << " is > #param = " << fRunInfo->GetNoOfParams() << "!" << std::endl;
413  return;
414  }
415  fPhase[idx] = true;
416  }
417  }
418 }
419 
420 //--------------------------------------------------------------------------
421 // GetParFromFun (private)
422 //--------------------------------------------------------------------------
430 PIntVector PFitter::GetParFromFun(const TString funStr)
431 {
432  PIntVector parVec;
433 
434  PMsrLines *funList = fRunInfo->GetMsrFunctions();
435  TObjArray *tok = nullptr;
436  TObjString *ostr = nullptr;
437  TString str;
438 
439  for (int i=0; i<funList->size(); i++) {
440  if (funList->at(i).fLine.Contains(funStr)) {
441  // tokenize function string
442  tok = funList->at(i).fLine.Tokenize(" =+-*/");
443  if (tok == nullptr) {
444  std::cerr << "PFitter::GetParFromFun(): **ERROR** couldn't tokenize function string." << std::endl;
445  return parVec;
446  }
447 
448  for (int j=1; j<tok->GetEntries(); j++) {
449  ostr = dynamic_cast<TObjString*>(tok->At(j));
450  str = ostr->GetString();
451  // parse tok for parX
452  if (str.Contains("par")) {
453  // find start idx of par in token
454  Ssiz_t idx = str.Index("par");
455  idx += 3;
456  TString parStr("");
457  do {
458  parStr += str[idx];
459  } while (isdigit(str[idx++]));
460  parVec.push_back(parStr.Atoi());
461  }
462  // parse tok for mapX
463  if (str.Contains("map")) {
464  // find start idx of par in token
465  Ssiz_t idx = str.Index("map");
466  idx += 3;
467  TString mapStr("map");
468  do {
469  mapStr += str[idx];
470  } while (isdigit(str[idx++]));
471  PIntVector mapParVec = GetParFromMap(mapStr);
472  for (int k=0; k<mapParVec.size(); k++) {
473  parVec.push_back(mapParVec[k]);
474  }
475  }
476  }
477 
478  // clean up
479  delete tok;
480  tok = nullptr;
481  }
482  }
483 
484  return parVec;
485 }
486 
487 //--------------------------------------------------------------------------
488 // GetParFromMap (private)
489 //--------------------------------------------------------------------------
497 PIntVector PFitter::GetParFromMap(const TString mapStr)
498 {
499  PIntVector parVec;
500 
501  TString str = mapStr;
502  str.Remove(0,3); // remove map from string
503 
504  int idx=str.Atoi();
505  if (idx == 0) {
506  std::cerr << "PFitter::GetParFromMap(): **ERROR** couldn't get propper index from mapX!" << std::endl;
507  return parVec;
508  }
509 
510  idx -= 1; // map starts at 1, map vector at 0
511 
512  // go through all the runs and collect the parameters from the map vectors
513  PMsrRunList *runList = fRunInfo->GetMsrRunList();
514  if (runList == nullptr) {
515  std::cerr << "PFitter::GetParFromMap(): **ERROR** couldn't get required run list information!" << std::endl;
516  return parVec;
517  }
518 
519  PIntVector *map = nullptr;
520  for (int i=0; i<runList->size(); i++) {
521  map = runList->at(i).GetMap();
522  if (map == nullptr) {
523  std::cerr << "PFitter::GetParFromMap(): **ERROR** couldn't get required map information (idx=" << i << ")!" << std::endl;
524  parVec.clear();
525  return parVec;
526  }
527  if (idx >= map->size()) {
528  std::cerr << "PFitter::GetParFromMap(): **ERROR** requested map index (idx=" << idx << ") out-of-range (" << map->size() << ")!" << std::endl;
529  parVec.clear();
530  return parVec;
531  }
532  parVec.push_back(map->at(idx));
533  }
534 
535  return parVec;
536 }
537 
538 //--------------------------------------------------------------------------
539 // DoFit
540 //--------------------------------------------------------------------------
547 {
548  // feed minuit parameters
549  SetParameters();
550 
551  // check if only chisq/maxLH shall be calculated once
552  if (fChisqOnly) {
553  std::vector<Double_t> param = fMnUserParams.Params();
554  std::vector<Double_t> error = fMnUserParams.Errors();
555  Int_t usedParams = 0;
556  for (UInt_t i=0; i<error.size(); i++) {
557  if (error[i] != 0.0)
558  usedParams++;
559  }
560  UInt_t ndf = static_cast<int>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
561  Double_t val = (*fFitterFcn)(param);
562  if (fUseChi2) {
563  // calculate expected chisq
564  Double_t totalExpectedChisq = 0.0;
565  PDoubleVector expectedChisqPerRun;
566  fFitterFcn->CalcExpectedChiSquare(param, totalExpectedChisq, expectedChisqPerRun);
567  // calculate chisq per run
568  std::vector<Double_t> chisqPerRun;
569  for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
570  chisqPerRun.push_back(fRunListCollection->GetSingleRunChisq(param, i));
571  }
572 
573  std::cout << std::endl << std::endl << ">> chisq = " << val << ", NDF = " << ndf << ", chisq/NDF = " << val/ndf;
574 
575  if (totalExpectedChisq != 0.0) {
576  std::cout << std::endl << ">> expected chisq = " << totalExpectedChisq << ", NDF = " << ndf << ", expected chisq/NDF = " << totalExpectedChisq/ndf;
577  UInt_t ndf_run = 0;
578  for (UInt_t i=0; i<expectedChisqPerRun.size(); i++) {
579  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
580  if (ndf_run > 0)
581  std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.chisq/red.chisq_e) = (" << ndf_run << "/" << chisqPerRun[i]/ndf_run << "/" << expectedChisqPerRun[i]/ndf_run << ")";
582  }
583  } else if (chisqPerRun.size() > 0) { // in case expected chisq is not applicable like for asymmetry fits
584  UInt_t ndf_run = 0;
585  for (UInt_t i=0; i<chisqPerRun.size(); i++) {
586  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
587  if (ndf_run > 0)
588  std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.chisq) = (" << ndf_run << "/" << chisqPerRun[i]/ndf_run << ")";
589  }
590  }
591 
592  // clean up
593  chisqPerRun.clear();
594  expectedChisqPerRun.clear();
595 
596  if (fSectorFlag) {
597  PDoublePairVector secFitRange;
598  secFitRange.resize(1);
599  for (UInt_t k=0; k<fSector.size(); k++) {
600  // set sector fit range
601  secFitRange[0].first = fSector[k].GetTimeRangeFirst(0);
602  secFitRange[0].second = fSector[k].GetTimeRangeLast();
603  fRunListCollection->SetFitRange(secFitRange);
604  // calculate chisq
605  val = (*fFitterFcn)(param);
606  // calculate NDF
607  ndf = static_cast<UInt_t>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
608  // calculate expected chisq
609  totalExpectedChisq = 0.0;
610  fFitterFcn->CalcExpectedChiSquare(param, totalExpectedChisq, expectedChisqPerRun);
611  // calculate chisq per run
612  for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
613  chisqPerRun.push_back(fRunListCollection->GetSingleRunChisq(param, i));
614  }
615 
616  std::cout << std::endl;
617  std::cout << "++++" << std::endl;
618  std::cout << ">> Sector " << k+1 << ": FitRange: " << secFitRange[0].first << ", " << secFitRange[0].second << std::endl;
619  std::cout << ">> chisq = " << val << ", NDF = " << ndf << ", chisq/NDF = " << val/ndf;
620 
621  if (totalExpectedChisq != 0.0) {
622  std::cout << std::endl << ">> expected chisq = " << totalExpectedChisq << ", NDF = " << ndf << ", expected chisq/NDF = " << totalExpectedChisq/ndf;
623  UInt_t ndf_run = 0;
624  for (UInt_t i=0; i<expectedChisqPerRun.size(); i++) {
625  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
626  if (ndf_run > 0)
627  std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.chisq/red.chisq_e) = (" << ndf_run << "/" << chisqPerRun[i]/ndf_run << "/" << expectedChisqPerRun[i]/ndf_run << ")";
628  }
629  } else if (chisqPerRun.size() > 0) { // in case expected chisq is not applicable like for asymmetry fits
630  UInt_t ndf_run = 0;
631  for (UInt_t i=0; i<chisqPerRun.size(); i++) {
632  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
633  if (ndf_run > 0)
634  std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.chisq) = (" << ndf_run << "/" << chisqPerRun[i]/ndf_run << ")";
635  }
636  }
637  // clean up
638  chisqPerRun.clear();
639  expectedChisqPerRun.clear();
640  }
641  }
642  } else { // max. log likelihood
643  // calculate expected maxLH
644  Double_t totalExpectedMaxLH = 0.0;
645  std::vector<Double_t> expectedMaxLHPerRun;
646  fFitterFcn->CalcExpectedChiSquare(param, totalExpectedMaxLH, expectedMaxLHPerRun);
647  // calculate maxLH per run
648  std::vector<Double_t> maxLHPerRun;
649  for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
650  maxLHPerRun.push_back(fRunListCollection->GetSingleRunMaximumLikelihood(param, i));
651  }
652 
653  std::cout << std::endl << std::endl << ">> maxLH = " << val << ", NDF = " << ndf << ", maxLH/NDF = " << val/ndf;
654 
655  if (totalExpectedMaxLH != 0.0) {
656  std::cout << std::endl << ">> expected maxLH = " << totalExpectedMaxLH << ", NDF = " << ndf << ", expected maxLH/NDF = " << totalExpectedMaxLH/ndf;
657  UInt_t ndf_run = 0;
658  for (UInt_t i=0; i<expectedMaxLHPerRun.size(); i++) {
659  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
660  if (ndf_run > 0)
661  std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.maxLH/red.maxLH_e) = (" << ndf_run << "/" << maxLHPerRun[i]/ndf_run << "/" << expectedMaxLHPerRun[i]/ndf_run << ")";
662  }
663  }
664 
665  // clean up
666  maxLHPerRun.clear();
667  expectedMaxLHPerRun.clear();
668 
669  if (fSectorFlag) {
670  PDoublePairVector secFitRange;
671  secFitRange.resize(1);
672  for (UInt_t k=0; k<fSector.size(); k++) {
673  // set sector fit range
674  secFitRange[0].first = fSector[k].GetTimeRangeFirst(0);
675  secFitRange[0].second = fSector[k].GetTimeRangeLast();
676  fRunListCollection->SetFitRange(secFitRange);
677  // calculate maxLH
678  val = (*fFitterFcn)(param);
679  // calculate NDF
680  ndf = static_cast<int>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
681  // calculate expected maxLH
682  totalExpectedMaxLH = 0.0;
683  fFitterFcn->CalcExpectedChiSquare(param, totalExpectedMaxLH, expectedMaxLHPerRun);
684  // calculate maxLH per run
685  for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
686  maxLHPerRun.push_back(fRunListCollection->GetSingleRunMaximumLikelihood(param, i));
687  }
688 
689  std::cout << std::endl;
690  std::cout << "++++" << std::endl;
691  std::cout << ">> Sector " << k+1 << ": FitRange: " << secFitRange[0].first << ", " << secFitRange[0].second << std::endl;
692  std::cout << ">> maxLH = " << val << ", NDF = " << ndf << ", maxLH/NDF = " << val/ndf;
693 
694  if (totalExpectedMaxLH != 0.0) {
695  std::cout << std::endl << ">> expected maxLH = " << totalExpectedMaxLH << ", NDF = " << ndf << ", expected maxLH/NDF = " << totalExpectedMaxLH/ndf;
696  UInt_t ndf_run = 0;
697  for (UInt_t i=0; i<expectedMaxLHPerRun.size(); i++) {
698  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
699  if (ndf_run > 0)
700  std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.maxLH/red.maxLH_e) = (" << ndf_run << "/" << maxLHPerRun[i]/ndf_run << "/" << expectedMaxLHPerRun[i]/ndf_run << ")";
701  }
702  }
703 
704  // clean up
705  maxLHPerRun.clear();
706  expectedMaxLHPerRun.clear();
707  }
708  }
709  }
710  std::cout << std::endl << std::endl;
711  return true;
712  }
713 
714  // debugging information
715  #ifdef HAVE_GOMP
716  std::cout << std::endl << ">> Number of available threads for the function optimization: " << omp_get_max_threads() << std::endl;
717  #endif
718 
719  // real fit wanted
720  if (fUseChi2)
721  std::cout << std::endl << ">> Chi Square fit will be executed" << std::endl;
722  else
723  std::cout << std::endl << ">> Maximum Likelihood fit will be executed" << std::endl;
724 
725  Bool_t status = true;
726  // init positive errors to default false, if minos is called, it will be set true there
727  for (UInt_t i=0; i<fParams.size(); i++) {
729  }
730 
731  // walk through the command list and execute them
732  Bool_t firstSave = true;
733  for (UInt_t i=0; i<fCmdList.size(); i++) {
734  switch (fCmdList[i].first) {
735  case PMN_INTERACTIVE:
736  std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command INTERACTIVE is not yet implemented.";
737  std::cerr << std::endl;
738  break;
739  case PMN_CONTOURS:
741  break;
742  case PMN_FIT_RANGE:
743  status = ExecuteFitRange(fCmdList[i].second);
744  break;
745  case PMN_FIX:
746  status = ExecuteFix(fCmdList[i].second);
747  break;
748  case PMN_EIGEN:
749  std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command EIGEN is not yet implemented.";
750  std::cerr << std::endl;
751  break;
752  case PMN_HESSE:
753  status = ExecuteHesse();
754  break;
756  std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command MACHINE_PRECISION is not yet implemented.";
757  std::cerr << std::endl;
758  break;
759  case PMN_MIGRAD:
760  status = ExecuteMigrad();
761  break;
762  case PMN_MINIMIZE:
764  break;
765  case PMN_MINOS:
766  status = ExecuteMinos();
767  break;
768  case PMN_PLOT:
769  status = ExecutePlot();
770  break;
771  case PMN_RELEASE:
772  status = ExecuteRelease(fCmdList[i].second);
773  break;
774  case PMN_RESTORE:
776  break;
777  case PMN_SAVE:
778  status = ExecuteSave(firstSave);
779  if (firstSave)
780  firstSave = false;
781  break;
782  case PMN_SCAN:
783  status = ExecuteScan();
784  break;
785  case PMN_SECTOR:
786  // nothing to be done here
787  break;
788  case PMN_SIMPLEX:
790  break;
791  case PMN_USER_COVARIANCE:
792  std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command USER_COVARIANCE is not yet implemented.";
793  std::cerr << std::endl;
794  break;
796  std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command USER_PARAM_STATE is not yet implemented.";
797  std::cerr << std::endl;
798  break;
799  case PMN_PRINT:
800  status = ExecutePrintLevel(fCmdList[i].second);
801  break;
802  default:
803  std::cerr << std::endl << "**PANIC ERROR**: PFitter::DoFit(): You should never have reached this point";
804  std::cerr << std::endl;
805  exit(0);
806  }
807 
808  // check if command has been successful
809  if (!status)
810  break;
811  }
812 
813  if (IsValid()) {
814  fRunInfo->GetMsrStatistic()->fValid = true;
815  } else {
816  fRunInfo->GetMsrStatistic()->fValid = false;
817  }
818 
819  return true;
820 }
821 
822 //--------------------------------------------------------------------------
823 // CheckCommands
824 //--------------------------------------------------------------------------
832 {
833  fIsValid = true;
834 
835  // check if chisq or log max likelihood fit
837 
838  // walk through the msr-file COMMAND block
839  PIntPair cmd;
840  PMsrLines::iterator it;
841  UInt_t cmdLineNo = 0;
842  TString line;
843  Ssiz_t pos;
844  for (it = fCmdLines.begin(); it != fCmdLines.end(); ++it) {
845  if (it == fCmdLines.begin())
846  cmdLineNo = 0;
847  else
848  cmdLineNo++;
849 
850  // strip potential comments
851  line = it->fLine;
852  pos = line.First('#');
853  if (pos > 0) // comment present
854  line.Remove(pos,line.Length()-pos);
855 
856  if (line.Contains("COMMANDS", TString::kIgnoreCase)) {
857  continue;
858  } else if (line.Contains("SET BATCH", TString::kIgnoreCase)) { // needed for backward compatibility
859  continue;
860  } else if (line.Contains("END RETURN", TString::kIgnoreCase)) { // needed for backward compatibility
861  continue;
862  } else if (line.Contains("CHI_SQUARE", TString::kIgnoreCase)) {
863  continue;
864  } else if (line.Contains("MAX_LIKELIHOOD", TString::kIgnoreCase)) {
865  continue;
866  } else if (line.Contains("SCALE_N0_BKG", TString::kIgnoreCase)) {
867  continue;
868  } else if (line.Contains("INTERACTIVE", TString::kIgnoreCase)) {
869  cmd.first = PMN_INTERACTIVE;
870  cmd.second = cmdLineNo;
871  fCmdList.push_back(cmd);
872  } else if (line.Contains("CONTOURS", TString::kIgnoreCase)) {
873  cmd.first = PMN_CONTOURS;
874  cmd.second = cmdLineNo;
875  fCmdList.push_back(cmd);
876  // filter out possible parameters for scan
877  TObjArray *tokens = nullptr;
878  TObjString *ostr;
879  TString str;
880  UInt_t ival;
881 
882  tokens = line.Tokenize(", \t");
883 
884  for (Int_t i=0; i<tokens->GetEntries(); i++) {
885  ostr = dynamic_cast<TObjString*>(tokens->At(i));
886  str = ostr->GetString();
887 
888  if ((i==1) || (i==2)) { // parX / parY
889  // check that token is a UInt_t
890  if (!str.IsDigit()) {
891  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
892  std::cerr << std::endl << ">> " << line.Data();
893  std::cerr << std::endl << ">> parameter number is not number!";
894  std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
895  std::cerr << std::endl;
896  fIsValid = false;
897  if (tokens) {
898  delete tokens;
899  tokens = nullptr;
900  }
901  break;
902  }
903  ival = str.Atoi();
904  // check that parameter is within range
905  if ((ival < 1) || (ival > fParams.size())) {
906  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
907  std::cerr << std::endl << ">> " << line.Data();
908  std::cerr << std::endl << ">> parameter number is out of range [1," << fParams.size() << "]!";
909  std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
910  std::cerr << std::endl;
911  fIsValid = false;
912  if (tokens) {
913  delete tokens;
914  tokens = nullptr;
915  }
916  break;
917  }
918  // keep parameter
919  fScanParameter[i-1] = ival-1; // internally parameter number starts at 0
920  fScanAll = false;
921  }
922 
923  if (i==3) {
924  // check that token is a UInt_t
925  if (!str.IsDigit()) {
926  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
927  std::cerr << std::endl << ">> " << line.Data();
928  std::cerr << std::endl << ">> number of points is not number!";
929  std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
930  std::cerr << std::endl;
931  fIsValid = false;
932  if (tokens) {
933  delete tokens;
934  tokens = nullptr;
935  }
936  break;
937  }
938  ival = str.Atoi();
939  if ((ival < 1) || (ival > 100)) {
940  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
941  std::cerr << std::endl << ">> " << line.Data();
942  std::cerr << std::endl << ">> number of scan points is out of range [1,100]!";
943  std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
944  std::cerr << std::endl;
945  fIsValid = false;
946  if (tokens) {
947  delete tokens;
948  tokens = nullptr;
949  }
950  break;
951  }
952  fScanNoPoints = ival;
953  }
954  }
955 
956  if (tokens) {
957  delete tokens;
958  tokens = nullptr;
959  }
960  } else if (line.Contains("EIGEN", TString::kIgnoreCase)) {
961  cmd.first = PMN_EIGEN;
962  cmd.second = cmdLineNo;
963  fCmdList.push_back(cmd);
964  } else if (line.Contains("FIT_RANGE", TString::kIgnoreCase)) {
965  // check the 5 options:
966  // (i) FIT_RANGE RESET,
967  // (ii) FIT_RANGE start end,
968  // (iii) FIT_RANGE start1 end1 start2 end2 ... startN endN
969  // (iv) FIT_RANGE fgb+n0 lgb-n1
970  // (v) FIT_RANGE fgb+n00 lgb-n01 fgb+n10 lgb-n11 ... fgb+nN0 lgb-nN1
971  TObjArray *tokens = nullptr;
972  TObjString *ostr;
973  TString str;
974 
975  tokens = line.Tokenize(", \t");
976 
977  if (tokens->GetEntries() == 2) { // should only be RESET
978  ostr = dynamic_cast<TObjString*>(tokens->At(1));
979  str = ostr->GetString();
980  if (str.Contains("RESET", TString::kIgnoreCase)) {
981  cmd.first = PMN_FIT_RANGE;
982  cmd.second = cmdLineNo;
983  fCmdList.push_back(cmd);
984  } else {
985  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
986  std::cerr << std::endl << ">> " << line.Data();
987  std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE start end | FIT_RANGE s1 e1 s2 e2 .. sN eN,";
988  std::cerr << std::endl << ">> with N the number of runs in the msr-file." << std::endl;
989  std::cerr << std::endl << ">> Found " << str.Data() << ", instead of RESET" << std::endl;
990  fIsValid = false;
991  if (tokens) {
992  delete tokens;
993  tokens = nullptr;
994  }
995  break;
996  }
997  } else if ((tokens->GetEntries() > 1) && (static_cast<UInt_t>(tokens->GetEntries()) % 2) == 1) {
998  if ((tokens->GetEntries() > 3) && ((static_cast<UInt_t>(tokens->GetEntries())-1)) != 2*fRunInfo->GetMsrRunList()->size()) {
999  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1000  std::cerr << std::endl << ">> " << line.Data();
1001  std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE <start> <end> | FIT_RANGE <s1> <e1> <s2> <e2> .. <sN> <eN> |";
1002  std::cerr << std::endl << ">> FIT_RANGE fgb+<n0> lgb-<n1> | FIT_RANGE fgb+<n00> lgb-<n01> fgb+<n10> lgb-<n11> ... fgb+<nN0> lgb-<nN1>,";
1003  std::cerr << std::endl << ">> with N the number of runs in the msr-file.";
1004  std::cerr << std::endl << ">> Found N=" << (tokens->GetEntries()-1)/2 << ", # runs in msr-file=" << fRunInfo->GetMsrRunList()->size() << std::endl;
1005  fIsValid = false;
1006  if (tokens) {
1007  delete tokens;
1008  tokens = nullptr;
1009  }
1010  break;
1011  } else {
1012  // check that all range entries are numbers or fgb+n0 / lgb-n1
1013  Bool_t ok = true;
1014  for (Int_t n=1; n<tokens->GetEntries(); n++) {
1015  ostr = dynamic_cast<TObjString*>(tokens->At(n));
1016  str = ostr->GetString();
1017  if (!str.IsFloat()) {
1018  if ((n%2 == 1) && (!str.Contains("fgb", TString::kIgnoreCase)))
1019  ok = false;
1020  if ((n%2 == 0) && (!str.Contains("lgb", TString::kIgnoreCase)))
1021  ok = false;
1022  }
1023  if (!ok)
1024  break;
1025  }
1026 
1027  if (ok) { // everything is fine
1028  cmd.first = PMN_FIT_RANGE;
1029  cmd.second = cmdLineNo;
1030  fCmdList.push_back(cmd);
1031  } else {
1032  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1033  std::cerr << std::endl << ">> " << line.Data();
1034  std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE <start> <end> | FIT_RANGE <s1> <e1> <s2> <e2> .. <sN> <eN> |";
1035  std::cerr << std::endl << ">> FIT_RANGE fgb+<n0> lgb-<n1> | FIT_RANGE fgb+<n00> lgb-<n01> fgb+<n10> lgb-<n11> ... fgb+<nN0> lgb-<nN1>,";
1036  std::cerr << std::endl << ">> with N the number of runs in the msr-file.";
1037  std::cerr << std::endl << ">> Found token '" << str.Data() << "', which is not a floating point number." << std::endl;
1038  fIsValid = false;
1039  if (tokens) {
1040  delete tokens;
1041  tokens = nullptr;
1042  }
1043  break;
1044  }
1045  }
1046  } else {
1047  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1048  std::cerr << std::endl << ">> " << line.Data();
1049  std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE <start> <end> | FIT_RANGE <s1> <e1> <s2> <e2> .. <sN> <eN> |";
1050  std::cerr << std::endl << ">> FIT_RANGE fgb+<n0> lgb-<n1> | FIT_RANGE fgb+<n00> lgb-<n01> fgb+<n10> lgb-<n11> ... fgb+<nN0> lgb-<nN1>,";
1051  std::cerr << std::endl << ">> with N the number of runs in the msr-file.";
1052  fIsValid = false;
1053  if (tokens) {
1054  delete tokens;
1055  tokens = nullptr;
1056  }
1057  break;
1058  }
1059 
1060  if (tokens) {
1061  delete tokens;
1062  tokens = nullptr;
1063  }
1064  } else if (line.Contains("FIX", TString::kIgnoreCase)) {
1065  // check if the given set of parameters (number or names) is present
1066  TObjArray *tokens = nullptr;
1067  TObjString *ostr;
1068  TString str;
1069  UInt_t ival;
1070 
1071  tokens = line.Tokenize(", \t");
1072 
1073  for (Int_t i=1; i<tokens->GetEntries(); i++) {
1074  ostr = dynamic_cast<TObjString*>(tokens->At(i));
1075  str = ostr->GetString();
1076 
1077  if (str.IsDigit()) { // token might be a parameter number
1078  ival = str.Atoi();
1079  // check that ival is in the parameter list
1080  if (ival > fParams.size()) {
1081  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1082  std::cerr << std::endl << ">> " << line.Data();
1083  std::cerr << std::endl << ">> Parameter " << ival << " is out of the Parameter Range [1," << fParams.size() << "]";
1084  std::cerr << std::endl;
1085  fIsValid = false;
1086  if (tokens) {
1087  delete tokens;
1088  tokens = nullptr;
1089  }
1090  break;
1091  }
1092  } else { // token might be a parameter name
1093  // check if token is present as parameter name
1094  Bool_t found = false;
1095  for (UInt_t j=0; j<fParams.size(); j++) {
1096  if (fParams[j].fName.CompareTo(str, TString::kIgnoreCase) == 0) { // found
1097  found = true;
1098  break;
1099  }
1100  }
1101  if (!found) {
1102  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1103  std::cerr << std::endl << ">> " << line.Data();
1104  std::cerr << std::endl << ">> Parameter '" << str.Data() << "' is NOT present as a parameter name";
1105  std::cerr << std::endl;
1106  fIsValid = false;
1107  if (tokens) {
1108  delete tokens;
1109  tokens = nullptr;
1110  }
1111  break;
1112  }
1113  }
1114  }
1115 
1116  if (tokens) {
1117  delete tokens;
1118  tokens = nullptr;
1119  }
1120 
1121  // everything looks fine, feed the command list
1122  cmd.first = PMN_FIX;
1123  cmd.second = cmdLineNo;
1124  fCmdList.push_back(cmd);
1125  } else if (line.Contains("HESSE", TString::kIgnoreCase)) {
1126  fIsScanOnly = false;
1127  cmd.first = PMN_HESSE;
1128  cmd.second = cmdLineNo;
1129  fCmdList.push_back(cmd);
1130  } else if (line.Contains("MACHINE_PRECISION", TString::kIgnoreCase)) {
1131  cmd.first = PMN_MACHINE_PRECISION;
1132  cmd.second = cmdLineNo;
1133  fCmdList.push_back(cmd);
1134  } else if (line.Contains("MIGRAD", TString::kIgnoreCase)) {
1135  fIsScanOnly = false;
1136  cmd.first = PMN_MIGRAD;
1137  cmd.second = cmdLineNo;
1138  fCmdList.push_back(cmd);
1139  } else if (line.Contains("MINIMIZE", TString::kIgnoreCase)) {
1140  fIsScanOnly = false;
1141  cmd.first = PMN_MINIMIZE;
1142  cmd.second = cmdLineNo;
1143  fCmdList.push_back(cmd);
1144  } else if (line.Contains("MINOS", TString::kIgnoreCase)) {
1145  fIsScanOnly = false;
1146  cmd.first = PMN_MINOS;
1147  cmd.second = cmdLineNo;
1148  fCmdList.push_back(cmd);
1149  } else if (line.Contains("MNPLOT", TString::kIgnoreCase)) {
1150  cmd.first = PMN_PLOT;
1151  cmd.second = cmdLineNo;
1152  fCmdList.push_back(cmd);
1153  } else if (line.Contains("PRINT_LEVEL", TString::kIgnoreCase)) {
1154  cmd.first = PMN_PRINT;
1155  cmd.second = cmdLineNo;
1156  fCmdList.push_back(cmd);
1157  } else if (line.Contains("RELEASE", TString::kIgnoreCase)) {
1158  // check if the given set of parameters (number or names) is present
1159  TObjArray *tokens = nullptr;
1160  TObjString *ostr;
1161  TString str;
1162  UInt_t ival;
1163 
1164  tokens = line.Tokenize(", \t");
1165 
1166  for (Int_t i=1; i<tokens->GetEntries(); i++) {
1167  ostr = dynamic_cast<TObjString*>(tokens->At(i));
1168  str = ostr->GetString();
1169 
1170  if (str.IsDigit()) { // token might be a parameter number
1171  ival = str.Atoi();
1172  // check that ival is in the parameter list
1173  if (ival > fParams.size()) {
1174  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1175  std::cerr << std::endl << ">> " << line.Data();
1176  std::cerr << std::endl << ">> Parameter " << ival << " is out of the Parameter Range [1," << fParams.size() << "]";
1177  std::cerr << std::endl;
1178  fIsValid = false;
1179  if (tokens) {
1180  delete tokens;
1181  tokens = nullptr;
1182  }
1183  break;
1184  }
1185  } else { // token might be a parameter name
1186  // check if token is present as parameter name
1187  Bool_t found = false;
1188  for (UInt_t j=0; j<fParams.size(); j++) {
1189  if (fParams[j].fName.CompareTo(str, TString::kIgnoreCase) == 0) { // found
1190  found = true;
1191  break;
1192  }
1193  }
1194  if (!found) {
1195  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1196  std::cerr << std::endl << ">> " << line.Data();
1197  std::cerr << std::endl << ">> Parameter '" << str.Data() << "' is NOT present as a parameter name";
1198  std::cerr << std::endl;
1199  fIsValid = false;
1200  if (tokens) {
1201  delete tokens;
1202  tokens = nullptr;
1203  }
1204  break;
1205  }
1206  }
1207  }
1208 
1209  if (tokens) {
1210  delete tokens;
1211  tokens = nullptr;
1212  }
1213  cmd.first = PMN_RELEASE;
1214  cmd.second = cmdLineNo;
1215  fCmdList.push_back(cmd);
1216  } else if (line.Contains("RESTORE", TString::kIgnoreCase)) {
1217  cmd.first = PMN_RESTORE;
1218  cmd.second = cmdLineNo;
1219  fCmdList.push_back(cmd);
1220  } else if (line.Contains("SAVE", TString::kIgnoreCase)) {
1221  cmd.first = PMN_SAVE;
1222  cmd.second = cmdLineNo;
1223  fCmdList.push_back(cmd);
1224  } else if (line.Contains("SCAN", TString::kIgnoreCase)) {
1225  cmd.first = PMN_SCAN;
1226  cmd.second = cmdLineNo;
1227  fCmdList.push_back(cmd);
1228  // filter out possible parameters for scan
1229  TObjArray *tokens = nullptr;
1230  TObjString *ostr;
1231  TString str;
1232  UInt_t ival;
1233 
1234  tokens = line.Tokenize(", \t");
1235 
1236  for (Int_t i=0; i<tokens->GetEntries(); i++) {
1237  ostr = dynamic_cast<TObjString*>(tokens->At(i));
1238  str = ostr->GetString();
1239  if (i==1) { // get parameter number
1240  // check that token is a UInt_t
1241  if (!str.IsDigit()) {
1242  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1243  std::cerr << std::endl << ">> " << line.Data();
1244  std::cerr << std::endl << ">> parameter number is not number!";
1245  std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1246  std::cerr << std::endl;
1247  fIsValid = false;
1248  if (tokens) {
1249  delete tokens;
1250  tokens = nullptr;
1251  }
1252  break;
1253  }
1254  ival = str.Atoi();
1255  // check that parameter is within range
1256  if ((ival < 1) || (ival > fParams.size())) {
1257  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1258  std::cerr << std::endl << ">> " << line.Data();
1259  std::cerr << std::endl << ">> parameter number is out of range [1," << fParams.size() << "]!";
1260  std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1261  std::cerr << std::endl;
1262  fIsValid = false;
1263  if (tokens) {
1264  delete tokens;
1265  tokens = nullptr;
1266  }
1267  break;
1268  }
1269  // keep parameter
1270  fScanParameter[0] = ival-1; // internally parameter number starts at 0
1271  fScanAll = false;
1272  }
1273 
1274  if (i==2) { // get number of points
1275  // check that token is a UInt_t
1276  if (!str.IsDigit()) {
1277  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1278  std::cerr << std::endl << ">> " << line.Data();
1279  std::cerr << std::endl << ">> number of points is not number!";
1280  std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1281  std::cerr << std::endl;
1282  fIsValid = false;
1283  if (tokens) {
1284  delete tokens;
1285  tokens = nullptr;
1286  }
1287  break;
1288  }
1289  ival = str.Atoi();
1290  if ((ival < 1) || (ival > 100)) {
1291  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1292  std::cerr << std::endl << ">> " << line.Data();
1293  std::cerr << std::endl << ">> number of scan points is out of range [1,100]!";
1294  std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1295  std::cerr << std::endl;
1296  fIsValid = false;
1297  if (tokens) {
1298  delete tokens;
1299  tokens = nullptr;
1300  }
1301  break;
1302  }
1303  fScanNoPoints = ival;
1304  }
1305 
1306  if (i==3) { // get low
1307  // check that token is a Double_t
1308  if (!str.IsFloat()) {
1309  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1310  std::cerr << std::endl << ">> " << line.Data();
1311  std::cerr << std::endl << ">> low is not a floating point number!";
1312  std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1313  std::cerr << std::endl;
1314  fIsValid = false;
1315  if (tokens) {
1316  delete tokens;
1317  tokens = nullptr;
1318  }
1319  break;
1320  }
1321  fScanLow = str.Atof();
1322  }
1323 
1324  if (i==4) { // get high
1325  // check that token is a Double_t
1326  if (!str.IsFloat()) {
1327  std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1328  std::cerr << std::endl << ">> " << line.Data();
1329  std::cerr << std::endl << ">> high is not a floating point number!";
1330  std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1331  std::cerr << std::endl;
1332  fIsValid = false;
1333  if (tokens) {
1334  delete tokens;
1335  tokens = nullptr;
1336  }
1337  break;
1338  }
1339  fScanHigh = str.Atof();
1340  }
1341  }
1342 
1343  if (tokens) {
1344  delete tokens;
1345  tokens = nullptr;
1346  }
1347  } else if (line.Contains("SIMPLEX", TString::kIgnoreCase)) {
1348  cmd.first = PMN_SIMPLEX;
1349  cmd.second = cmdLineNo;
1350  fCmdList.push_back(cmd);
1351  } else if (line.Contains("STRATEGY", TString::kIgnoreCase)) {
1352  TObjArray *tokens = nullptr;
1353  TObjString *ostr;
1354  TString str;
1355 
1356  tokens = line.Tokenize(" \t");
1357  if (tokens->GetEntries() == 2) {
1358  ostr = dynamic_cast<TObjString*>(tokens->At(1));
1359  str = ostr->GetString();
1360  if (str.CompareTo("0") == 0) { // low
1361  fStrategy = 0;
1362  } else if (str.CompareTo("1") == 0) { // default
1363  fStrategy = 1;
1364  } else if (str.CompareTo("2") == 0) { // high
1365  fStrategy = 2;
1366  } else if (str.CompareTo("LOW") == 0) { // low
1367  fStrategy = 0;
1368  } else if (str.CompareTo("DEFAULT") == 0) { // default
1369  fStrategy = 1;
1370  } else if (str.CompareTo("HIGH") == 0) { // high
1371  fStrategy = 2;
1372  }
1373  }
1374 
1375  if (tokens) {
1376  delete tokens;
1377  tokens = nullptr;
1378  }
1379  } else if (line.Contains("USER_COVARIANCE", TString::kIgnoreCase)) {
1380  cmd.first = PMN_USER_COVARIANCE;
1381  cmd.second = cmdLineNo;
1382  fCmdList.push_back(cmd);
1383  } else if (line.Contains("USER_PARAM_STATE", TString::kIgnoreCase)) {
1384  cmd.first = PMN_USER_PARAM_STATE;
1385  cmd.second = cmdLineNo;
1386  fCmdList.push_back(cmd);
1387  } else if (line.Contains("SECTOR", TString::kIgnoreCase)) {
1388  fSectorFlag = true;
1389  cmd.first = PMN_SECTOR;
1390  cmd.second = cmdLineNo;
1391  fCmdList.push_back(cmd);
1392 
1393  // check if the given sector arguments are valid time stamps, i.e. doubles and value < lgb time stamp
1394  TObjArray *tokens = nullptr;
1395  TObjString *ostr;
1396  TString str;
1397 
1398  tokens = line.Tokenize(" ,\t");
1399 
1400  if (tokens->GetEntries() == 1) { // no sector time stamps given -> issue an error
1401  std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo;
1402  std::cerr << std::endl << ">> " << line.Data();
1403  std::cerr << std::endl << ">> At least one sector time stamp is expected.";
1404  std::cerr << std::endl << ">> Will stop ...";
1405  std::cerr << std::endl;
1406  // cleanup
1407  if (tokens) {
1408  delete tokens;
1409  tokens = nullptr;
1410  }
1411  fIsValid = false;
1412  fSectorFlag = false;
1413  break;
1414  }
1415 
1416  Double_t dval;
1417  for (Int_t i=1; i<tokens->GetEntries(); i++) {
1418  // keep time range of sector
1420  // get parse tokens
1421  ostr = dynamic_cast<TObjString*>(tokens->At(i));
1422  str = ostr->GetString();
1423  if (str.IsFloat()) {
1424  dval = str.Atof();
1425  // check that the sector time stamp is smaller than all lgb time stamps
1426  for (UInt_t j=0; j<fOriginalFitRange.size(); j++) {
1427  if (dval > fOriginalFitRange[j].second) {
1428  std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo;
1429  std::cerr << std::endl << ">> " << line.Data();
1430  std::cerr << std::endl << ">> The sector time stamp " << dval << " is > as the lgb time stamp (" << fOriginalFitRange[j].second << ") of run " << j << ".";
1431  std::cerr << std::endl << ">> Will stop ...";
1432  std::cerr << std::endl;
1433  // cleanup
1434  if (tokens) {
1435  delete tokens;
1436  tokens = nullptr;
1437  }
1438  fIsValid = false;
1439  fSectorFlag = false;
1440  return fIsValid;
1441  }
1442  sec.SetRunFirstTime(fOriginalFitRange[j].first, j); // keep fgb time stamp for sector
1443  }
1444  sec.SetSectorTime(dval);
1445  fSector.push_back(sec);
1446  } else { // sector element is NOT a float
1447  std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo;
1448  std::cerr << std::endl << ">> " << line.Data();
1449  std::cerr << std::endl << ">> The sector time stamp '" << str << "' is not a number.";
1450  std::cerr << std::endl << ">> Will stop ...";
1451  std::cerr << std::endl;
1452  // cleanup
1453  if (tokens) {
1454  delete tokens;
1455  tokens = nullptr;
1456  }
1457  fIsValid = false;
1458  fSectorFlag = false;
1459  break;
1460  }
1461  }
1462 
1463  if (tokens) {
1464  delete tokens;
1465  tokens = nullptr;
1466  }
1467  } else { // unkown command
1468  std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo << " an unkown command is found:";
1469  std::cerr << std::endl << ">> " << line.Data();
1470  std::cerr << std::endl << ">> Will stop ...";
1471  std::cerr << std::endl;
1472  fIsValid = false;
1473  break;
1474  }
1475  }
1476 
1477  // Check that in case release/restore is present, that it is followed by a minimizer before minos is called.
1478  // If this is not the case, place a warning
1479  Bool_t fixFlag = false;
1480  Bool_t releaseFlag = false;
1481  Bool_t minimizerFlag = false;
1482  for (it = fCmdLines.begin(); it != fCmdLines.end(); ++it) {
1483  if (line.Contains("FIX", TString::kIgnoreCase))
1484  fixFlag = true;
1485  else if (line.Contains("RELEASE", TString::kIgnoreCase) ||
1486  line.Contains("RESTORE", TString::kIgnoreCase))
1487  releaseFlag = true;
1488  else if (line.Contains("MINIMIZE", TString::kIgnoreCase) ||
1489  line.Contains("MIGRAD", TString::kIgnoreCase) ||
1490  line.Contains("SIMPLEX", TString::kIgnoreCase)) {
1491  if (releaseFlag)
1492  minimizerFlag = true;
1493  } else if (line.Contains("MINOS", TString::kIgnoreCase)) {
1494  if (fixFlag && releaseFlag && !minimizerFlag) {
1495  std::cerr << std::endl << ">> PFitter::CheckCommands(): **WARNING** RELEASE/RESTORE command present";
1496  std::cerr << std::endl << ">> without minimizer command (MINIMIZE/MIGRAD/SIMPLEX) between";
1497  std::cerr << std::endl << ">> RELEASE/RESTORE and MINOS. Behaviour might be different to the";
1498  std::cerr << std::endl << ">> expectation of the user ?!?" << std::endl;
1499  }
1500  fixFlag = false;
1501  releaseFlag = false;
1502  minimizerFlag = false;
1503  }
1504  }
1505 
1506  return fIsValid;
1507 }
1508 
1509 //--------------------------------------------------------------------------
1510 // SetParameters
1511 //--------------------------------------------------------------------------
1519 {
1520  for (UInt_t i=0; i<fParams.size(); i++) {
1521  // check if parameter is fixed
1522  if (fParams[i].fStep == 0.0) { // add fixed parameter
1523  fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue);
1524  } else { // add free parameter
1525  // check if boundaries are given
1526  if (fParams[i].fNoOfParams > 5) { // boundaries given
1527  if (fParams[i].fLowerBoundaryPresent &&
1528  fParams[i].fUpperBoundaryPresent) { // upper and lower boundaries given
1529  fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue, fParams[i].fStep,
1530  fParams[i].fLowerBoundary, fParams[i].fUpperBoundary);
1531  } else if (fParams[i].fLowerBoundaryPresent &&
1532  !fParams[i].fUpperBoundaryPresent) { // lower boundary limited
1533  fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue, fParams[i].fStep);
1534  fMnUserParams.SetLowerLimit(fParams[i].fName.Data(), fParams[i].fLowerBoundary);
1535  } else { // upper boundary limited
1536  fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue, fParams[i].fStep);
1537  fMnUserParams.SetUpperLimit(fParams[i].fName.Data(), fParams[i].fUpperBoundary);
1538  }
1539  } else { // no boundaries given
1540  fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue, fParams[i].fStep);
1541  }
1542  }
1543  }
1544 
1545  // check if there is an unused parameter, if so, fix it
1546  for (UInt_t i=0; i<fParams.size(); i++) {
1547  // parameter not used in the whole theory and not already fixed!!
1548  if ((fRunInfo->ParameterInUse(i) == 0) && (fParams[i].fStep != 0.0)) {
1549  fMnUserParams.Fix(i); // fix the unused parameter so that minuit will not vary it
1550  std::cerr << std::endl << "**WARNING** : Parameter No " << i+1 << " is not used at all, will fix it";
1551  std::cerr << std::endl;
1552  }
1553  }
1554 
1555  return true;
1556 }
1557 
1558 //--------------------------------------------------------------------------
1559 // ExecuteContours
1560 //--------------------------------------------------------------------------
1567 {
1568  std::cout << ">> PFitter::ExecuteContours() ..." << std::endl;
1569 
1570  // if already some minimization is done use the minuit2 output as input
1571  if (!fFcnMin) {
1572  std::cerr << std::endl << "**WARNING**: CONTOURS musn't be called before any minimization (MINIMIZE/MIGRAD/SIMPLEX) is done!!";
1573  std::cerr << std::endl;
1574  return false;
1575  }
1576 
1577  // check if minimum was valid
1578  if (!fFcnMin->IsValid()) {
1579  std::cerr << std::endl << "**ERROR**: CONTOURS cannot started since the previous minimization failed :-(";
1580  std::cerr << std::endl;
1581  return false;
1582  }
1583 
1584  ROOT::Minuit2::MnContours contours((*fFitterFcn), *fFcnMin);
1585 
1587 
1588  return true;
1589 }
1590 
1591 //--------------------------------------------------------------------------
1592 // ExecuteFitRange
1593 //--------------------------------------------------------------------------
1601 Bool_t PFitter::ExecuteFitRange(UInt_t lineNo)
1602 {
1603  std::cout << ">> PFitter::ExecuteFitRange(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
1604 
1605  if (fCmdLines[lineNo].fLine.Contains("fgb", TString::kIgnoreCase)) { // fit range given in bins
1606  fRunListCollection->SetFitRange(fCmdLines[lineNo].fLine);
1607  return true;
1608  }
1609 
1610  TObjArray *tokens = nullptr;
1611  TObjString *ostr;
1612  TString str;
1613 
1614  tokens = fCmdLines[lineNo].fLine.Tokenize(", \t");
1615 
1616  PMsrRunList *runList = fRunInfo->GetMsrRunList();
1617 
1618  // execute command, no error checking needed since this has been already carried out in CheckCommands()
1619  if (tokens->GetEntries() == 2) { // reset command
1621  } else if (tokens->GetEntries() == 3) { // single fit range for all runs
1622  Double_t start = 0.0, end = 0.0;
1623  PDoublePair fitRange;
1624  PDoublePairVector fitRangeVector;
1625 
1626  ostr = dynamic_cast<TObjString*>(tokens->At(1));
1627  str = ostr->GetString();
1628  start = str.Atof();
1629  ostr = dynamic_cast<TObjString*>(tokens->At(2));
1630  str = ostr->GetString();
1631  end = str.Atof();
1632 
1633  fitRange.first = start;
1634  fitRange.second = end;
1635  fitRangeVector.push_back(fitRange);
1636  fRunListCollection->SetFitRange(fitRangeVector);
1637 
1638  } else { // individual fit ranges for each run
1639  Double_t start = 0.0, end = 0.0;
1640  PDoublePair fitRange;
1641  PDoublePairVector fitRangeVector;
1642 
1643  for (UInt_t i=0; i<runList->size(); i++) {
1644  ostr = dynamic_cast<TObjString*>(tokens->At(2*i+1));
1645  str = ostr->GetString();
1646  start = str.Atof();
1647  ostr = dynamic_cast<TObjString*>(tokens->At(2*i+2));
1648  str = ostr->GetString();
1649  end = str.Atof();
1650 
1651  fitRange.first = start;
1652  fitRange.second = end;
1653  fitRangeVector.push_back(fitRange);
1654  }
1655 
1656  fRunListCollection->SetFitRange(fitRangeVector);
1657  }
1658 
1659  return true;
1660 }
1661 
1662 //--------------------------------------------------------------------------
1663 // ExecuteFix
1664 //--------------------------------------------------------------------------
1672 Bool_t PFitter::ExecuteFix(UInt_t lineNo)
1673 {
1674  std::cout << ">> PFitter::ExecuteFix(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
1675 
1676  TObjArray *tokens = nullptr;
1677  TObjString *ostr;
1678  TString str;
1679 
1680  tokens = fCmdLines[lineNo].fLine.Tokenize(", \t");
1681 
1682  for (Int_t i=1; i<tokens->GetEntries(); i++) {
1683  ostr = dynamic_cast<TObjString*>(tokens->At(i));
1684  str = ostr->GetString();
1685 
1686  if (str.IsDigit()) { // token is a parameter number
1687  fMnUserParams.Fix(static_cast<UInt_t>(str.Atoi())-1);
1688  } else { // token is a parameter name
1689  fMnUserParams.Fix(str.Data());
1690  }
1691  }
1692 
1693  // clean up
1694  if (tokens) {
1695  delete tokens;
1696  tokens = nullptr;
1697  }
1698 
1699  return true;
1700 }
1701 
1702 //--------------------------------------------------------------------------
1703 // ExecuteHesse
1704 //--------------------------------------------------------------------------
1711 {
1712  std::cout << ">> PFitter::ExecuteHesse(): will call hesse ..." << std::endl;
1713 
1714  // create the hesse object
1715  ROOT::Minuit2::MnHesse hesse;
1716 
1717  // specify maximal number of function calls
1718  UInt_t maxfcn = std::numeric_limits<UInt_t>::max();
1719 
1720  // call hesse
1721  Double_t start=0.0, end=0.0;
1722  start=MilliTime();
1723  ROOT::Minuit2::MnUserParameterState mnState = hesse((*fFitterFcn), fMnUserParams, maxfcn);
1724  end=MilliTime();
1725  std::cout << ">> PFitter::ExecuteMinimize(): execution time for Hesse = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
1726  TString str = TString::Format("Hesse: %.3f sec", (end-start)/1.0e3);
1727  fElapsedTime.push_back(str);
1728  if (!mnState.IsValid()) {
1729  std::cerr << std::endl << ">> PFitter::ExecuteHesse(): **WARNING** Hesse encountered a problem! The state found is invalid.";
1730  std::cerr << std::endl;
1731  return false;
1732  }
1733  if (!mnState.HasCovariance()) {
1734  std::cerr << std::endl << ">> PFitter::ExecuteHesse(): **WARNING** Hesse encountered a problem! No covariance matrix available.";
1735  std::cerr << std::endl;
1736  return false;
1737  }
1738 
1739  // fill parabolic errors
1740  for (UInt_t i=0; i<fParams.size(); i++) {
1741  fRunInfo->SetMsrParamStep(i, mnState.Error(i));
1743  }
1744 
1745  if (fPrintLevel >= 2)
1746  std::cout << mnState << std::endl;
1747 
1748  return true;
1749 }
1750 
1751 //--------------------------------------------------------------------------
1752 // ExecuteMigrad
1753 //--------------------------------------------------------------------------
1760 {
1761  std::cout << ">> PFitter::ExecuteMigrad(): will call migrad ..." << std::endl;
1762 
1763  // create migrad object
1764  // strategy is by default = 'default'
1765  ROOT::Minuit2::MnMigrad migrad((*fFitterFcn), fMnUserParams, fStrategy);
1766 
1767  // minimize
1768  // maxfcn is MINUIT2 Default maxfcn
1769  UInt_t maxfcn = std::numeric_limits<UInt_t>::max();
1770  // tolerance = MINUIT2 Default tolerance
1771  Double_t tolerance = 0.1;
1772  // keep track of elapsed time
1773  Double_t start=0.0, end=0.0;
1774  start=MilliTime();
1775  ROOT::Minuit2::FunctionMinimum min = migrad(maxfcn, tolerance);
1776  end=MilliTime();
1777  std::cout << ">> PFitter::ExecuteMinimize(): execution time for Migrad = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
1778  TString str = TString::Format("Migrad: %.3f sec", (end-start)/1.0e3);
1779  fElapsedTime.push_back(str);
1780  if (!min.IsValid()) {
1781  std::cerr << std::endl << ">> PFitter::ExecuteMigrad(): **WARNING**: Fit did not converge, sorry ...";
1782  std::cerr << std::endl;
1783  fIsValid = false;
1784  return false;
1785  }
1786 
1787  // keep FunctionMinimum object
1788  fFcnMin.reset(new ROOT::Minuit2::FunctionMinimum(min));
1789 
1790  // keep user parameters
1791  if (fFcnMin)
1792  fMnUserParams = fFcnMin->UserParameters();
1793 
1794  // fill run info
1795  for (UInt_t i=0; i<fParams.size(); i++) {
1796  Double_t dval = min.UserState().Value(i);
1797  if (fPhase[i]) {
1798  Int_t m = (Int_t)(dval/360.0);
1799  dval = dval - m*360.0;
1800  }
1801  fRunInfo->SetMsrParamValue(i, dval);
1802  fRunInfo->SetMsrParamStep(i, min.UserState().Error(i));
1804  }
1805 
1806  // handle statistics
1807  Double_t minVal = min.Fval();
1808  UInt_t ndf = fFitterFcn->GetTotalNoOfFittedBins();
1809  // subtract number of varied parameters from total no of fitted bins -> ndf
1810  for (UInt_t i=0; i<fParams.size(); i++) {
1811  if ((min.UserState().Error(i) != 0.0) && !fMnUserParams.Parameters().at(i).IsFixed())
1812  ndf -= 1;
1813  }
1814 
1815  // feed run info with new statistics info
1816  fRunInfo->SetMsrStatisticMin(minVal);
1818 
1819  fConverged = true;
1820 
1821  if (fPrintLevel >= 2)
1822  std::cout << *fFcnMin << std::endl;
1823 
1824  return true;
1825 }
1826 
1827 //--------------------------------------------------------------------------
1828 // ExecuteMinimize
1829 //--------------------------------------------------------------------------
1836 {
1837  std::cout << ">> PFitter::ExecuteMinimize(): will call minimize ..." << std::endl;
1838 
1839  // create minimizer object
1840  // strategy is by default = 'default'
1841  ROOT::Minuit2::MnMinimize minimize((*fFitterFcn), fMnUserParams, fStrategy);
1842 
1843  // minimize
1844  // maxfcn is MINUIT2 Default maxfcn
1845  UInt_t maxfcn = std::numeric_limits<UInt_t>::max();
1846 
1847  // tolerance = MINUIT2 Default tolerance
1848  Double_t tolerance = 0.1;
1849  // keep track of elapsed time
1850  Double_t start=0.0, end=0.0;
1851  start = MilliTime();
1852  ROOT::Minuit2::FunctionMinimum min = minimize(maxfcn, tolerance);
1853  end = MilliTime();
1854  std::cout << ">> PFitter::ExecuteMinimize(): execution time for Minimize = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
1855  TString str = TString::Format("Minimize: %.3f sec", (end-start)/1.0e3);
1856  fElapsedTime.push_back(str);
1857  if (!min.IsValid()) {
1858  std::cerr << std::endl << ">> PFitter::ExecuteMinimize(): **WARNING**: Fit did not converge, sorry ...";
1859  std::cerr << std::endl;
1860  fIsValid = false;
1861  return false;
1862  }
1863 
1864  // keep FunctionMinimum object
1865  fFcnMin.reset(new ROOT::Minuit2::FunctionMinimum(min));
1866 
1867  // keep user parameters
1868  if (fFcnMin)
1869  fMnUserParams = fFcnMin->UserParameters();
1870 
1871  // fill run info
1872  for (UInt_t i=0; i<fParams.size(); i++) {
1873  Double_t dval = min.UserState().Value(i);
1874  if (fPhase[i]) {
1875  Int_t m = (Int_t)(dval/360.0);
1876  dval = dval - m*360.0;
1877  }
1878  fRunInfo->SetMsrParamValue(i, dval);
1879  fRunInfo->SetMsrParamStep(i, min.UserState().Error(i));
1881  }
1882 
1883  // handle statistics
1884  Double_t minVal = min.Fval();
1885  UInt_t ndf = fFitterFcn->GetTotalNoOfFittedBins();
1886  // subtract number of varied parameters from total no of fitted bins -> ndf
1887  for (UInt_t i=0; i<fParams.size(); i++) {
1888  if ((min.UserState().Error(i) != 0.0) && !fMnUserParams.Parameters().at(i).IsFixed())
1889  ndf -= 1;
1890  }
1891 
1892  // feed run info with new statistics info
1893  fRunInfo->SetMsrStatisticMin(minVal);
1895 
1896  fConverged = true;
1897 
1898  if (fPrintLevel >= 2)
1899  std::cout << *fFcnMin << std::endl;
1900 
1901  return true;
1902 }
1903 
1904 //--------------------------------------------------------------------------
1905 // ExecuteMinos
1906 //--------------------------------------------------------------------------
1913 {
1914  std::cout << ">> PFitter::ExecuteMinos(): will call minos ..." << std::endl;
1915 
1916  // if already some minimization is done use the minuit2 output as input
1917  if (!fFcnMin) {
1918  std::cerr << std::endl << "**ERROR**: MINOS musn't be called before any minimization (MINIMIZE/MIGRAD/SIMPLEX) is done!!";
1919  std::cerr << std::endl;
1920  return false;
1921  }
1922 
1923  // check if minimum was valid
1924  if (!fFcnMin->IsValid()) {
1925  std::cerr << std::endl << "**ERROR**: MINOS cannot started since the previous minimization failed :-(";
1926  std::cerr << std::endl;
1927  return false;
1928  }
1929 
1930  // make minos analysis
1931  Double_t start=0.0, end=0.0;
1932  start=MilliTime();
1933  ROOT::Minuit2::MnMinos minos((*fFitterFcn), (*fFcnMin));
1934 
1935  for (UInt_t i=0; i<fParams.size(); i++) {
1936  // only try to call minos if the parameter is not fixed!!
1937  // the 1st condition is from an user fixed variable,
1938  // the 2nd condition is from an all together unused variable
1939  // the 3rd condition is a variable fixed via the FIX command
1940  if ((fMnUserParams.Error(i) != 0.0) && (fRunInfo->ParameterInUse(i) != 0) && (!fMnUserParams.Parameters().at(i).IsFixed())) {
1941  std::cout << ">> PFitter::ExecuteMinos(): calculate errors for " << fParams[i].fName << std::endl;
1942 
1943  // 1-sigma MINOS errors
1944  ROOT::Minuit2::MinosError err = minos.Minos(i);
1945 
1946  if (err.IsValid()) {
1947  // fill msr-file structure
1948  fRunInfo->SetMsrParamStep(i, err.Lower());
1949  fRunInfo->SetMsrParamPosError(i, err.Upper());
1951  } else {
1953  }
1954  }
1955 
1956  if (fMnUserParams.Parameters().at(i).IsFixed()) {
1957  std::cerr << std::endl << ">> PFitter::ExecuteMinos(): **WARNING** Parameter " << fMnUserParams.Name(i) << " (ParamNo " << i+1 << ") is fixed!";
1958  std::cerr << std::endl << ">> Will set STEP to zero, i.e. making it a constant parameter";
1959  std::cerr << std::endl;
1960  fRunInfo->SetMsrParamStep(i, 0.0);
1962  }
1963  }
1964 
1965  end=MilliTime();
1966  std::cout << ">> PFitter::ExecuteMinimize(): execution time for Minos = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
1967  TString str = TString::Format("Minos: %.3f sec", (end-start)/1.0e3);
1968  fElapsedTime.push_back(str);
1969 
1970  return true;
1971 }
1972 
1973 //--------------------------------------------------------------------------
1974 // ExecutePlot
1975 //--------------------------------------------------------------------------
1982 {
1983  std::cout << ">> PFitter::ExecutePlot() ..." << std::endl;
1984 
1985  ROOT::Minuit2::MnPlot plot;
1986  plot(fScanData);
1987 
1988  return true;
1989 }
1990 
1991 //--------------------------------------------------------------------------
1992 // ExecutePrintLevel
1993 //--------------------------------------------------------------------------
2001 Bool_t PFitter::ExecutePrintLevel(UInt_t lineNo)
2002 {
2003  std::cout << ">> PFitter::ExecutePrintLevel(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
2004 
2005  TObjArray *tokens = nullptr;
2006  TObjString *ostr;
2007  TString str;
2008 
2009  tokens = fCmdLines[lineNo].fLine.Tokenize(", \t");
2010 
2011  if (tokens->GetEntries() < 2) {
2012  std::cerr << std::endl << "**ERROR** from PFitter::ExecutePrintLevel(): SYNTAX: PRINT_LEVEL <N>, where <N>=0-3" << std::endl << std::endl;
2013  return false;
2014  }
2015 
2016  ostr = (TObjString*)tokens->At(1);
2017  str = ostr->GetString();
2018 
2019  Int_t ival;
2020  if (str.IsDigit()) {
2021  ival = str.Atoi();
2022  if ((ival >=0) && (ival <= 3)) {
2023  fPrintLevel = (UInt_t) ival;
2024  } else {
2025  std::cerr << std::endl << "**ERROR** from PFitter::ExecutePrintLevel(): SYNTAX: PRINT_LEVEL <N>, where <N>=0-3";
2026  std::cerr << std::endl << " found <N>=" << ival << std::endl << std::endl;
2027  return false;
2028  }
2029  } else {
2030  std::cerr << std::endl << "**ERROR** from PFitter::ExecutePrintLevel(): SYNTAX: PRINT_LEVEL <N>, where <N>=0-3" << std::endl << std::endl;
2031  return false;
2032  }
2033 
2034 #ifdef ROOT_GRTEQ_24
2035  ROOT::Minuit2::MnPrint::SetGlobalLevel(fPrintLevel);
2036 #else
2037  ROOT::Minuit2::MnPrint::SetLevel(fPrintLevel);
2038 #endif
2039 
2040  // clean up
2041  if (tokens) {
2042  delete tokens;
2043  tokens = nullptr;
2044  }
2045 
2046  return true;
2047 }
2048 
2049 //--------------------------------------------------------------------------
2050 // ExecuteRelease
2051 //--------------------------------------------------------------------------
2059 Bool_t PFitter::ExecuteRelease(UInt_t lineNo)
2060 {
2061  TObjArray *tokens = nullptr;
2062  TObjString *ostr;
2063  TString str;
2064 
2065  tokens = fCmdLines[lineNo].fLine.Tokenize(", \t");
2066 
2067  std::cout << ">> PFitter::ExecuteRelease(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
2068 
2069  for (Int_t i=1; i<tokens->GetEntries(); i++) {
2070  ostr = dynamic_cast<TObjString*>(tokens->At(i));
2071  str = ostr->GetString();
2072 
2073  if (str.IsDigit()) { // token is a parameter number
2074  fMnUserParams.Release(static_cast<UInt_t>(str.Atoi())-1);
2075  // set the error to 2% of the value when releasing
2076  fMnUserParams.SetError(static_cast<UInt_t>(str.Atoi())-1, 0.02*fMnUserParams.Value(static_cast<UInt_t>(str.Atoi())-1));
2077  } else { // token is a parameter name
2078  fMnUserParams.Release(str.Data());
2079  // set the error to 2% of the value when releasing
2080  fMnUserParams.SetError(str.Data(), 0.02*fMnUserParams.Value(str.Data()));
2081  }
2082  }
2083 
2084  // clean up
2085  if (tokens) {
2086  delete tokens;
2087  tokens = nullptr;
2088  }
2089 
2090  return true;
2091 }
2092 
2093 //--------------------------------------------------------------------------
2094 // ExecuteRestore
2095 //--------------------------------------------------------------------------
2102 {
2103  std::cout << "PFitter::ExecuteRestore(): release all fixed parameters (RESTORE) ..." << std::endl;
2104 
2105  for (UInt_t i=0; i<fMnUserParams.Parameters().size(); i++) {
2106  if (fMnUserParams.Parameters().at(i).IsFixed()) {
2107  fMnUserParams.Release(i);
2108  fMnUserParams.SetError(i, 0.02*fMnUserParams.Value(i));
2109  }
2110  }
2111 
2112  return true;
2113 }
2114 
2115 //--------------------------------------------------------------------------
2116 // ExecuteScan
2117 //--------------------------------------------------------------------------
2124 {
2125  std::cout << ">> PFitter::ExecuteScan(): will call scan ..." << std::endl;
2126 
2127  ROOT::Minuit2::MnScan scan((*fFitterFcn), fMnUserParams);
2128 
2129  if (fScanAll) { // not clear at the moment what to be done here
2130  // TO BE IMPLEMENTED
2131  } else { // single parameter scan
2133  }
2134 
2135  fConverged = true;
2136 
2137  return true;
2138 }
2139 
2140 //--------------------------------------------------------------------------
2141 // ExecuteSave
2142 //--------------------------------------------------------------------------
2150 Bool_t PFitter::ExecuteSave(Bool_t firstSave)
2151 {
2152  // if any minimization was done, otherwise get out immediately
2153  if (!fFcnMin) {
2154  std::cout << std::endl << ">> PFitter::ExecuteSave(): nothing to be saved ...";
2155  return false;
2156  }
2157 
2158  ROOT::Minuit2::MnUserParameterState mnState = fFcnMin->UserState();
2159 
2160  // check if the user parameter state is valid
2161  if (!mnState.IsValid()) {
2162  std::cerr << std::endl << ">> PFitter::ExecuteSave: **WARNING** Minuit2 User Parameter State is not valid, i.e. nothing to be saved";
2163  std::cerr << std::endl;
2164  return false;
2165  }
2166 
2167  // handle expected chisq if applicable
2168  fParams = *(fRunInfo->GetMsrParamList()); // get the update parameters back
2169 
2170  // calculate expected chisq
2171  std::vector<Double_t> param;
2172  Double_t totalExpectedChisq = 0.0;
2173  std::vector<Double_t> expectedchisqPerRun;
2174  std::vector<UInt_t> ndfPerHisto;
2175 
2176  for (UInt_t i=0; i<fParams.size(); i++)
2177  param.push_back(fParams[i].fValue);
2178 
2179  // CalcExpectedChiSquare handles both, chisq and mlh
2180  fFitterFcn->CalcExpectedChiSquare(param, totalExpectedChisq, expectedchisqPerRun);
2181 
2182  // calculate chisq per run
2183  std::vector<Double_t> chisqPerRun;
2184  for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
2185  if (fUseChi2)
2186  chisqPerRun.push_back(fRunListCollection->GetSingleRunChisq(param, i));
2187  else
2188  chisqPerRun.push_back(fRunListCollection->GetSingleRunMaximumLikelihood(param, i));
2189  }
2190 
2191  if (totalExpectedChisq != 0.0) { // i.e. applicable for single histogram fits only
2192  // get the ndf's of the histos
2193  UInt_t ndf_run;
2194  for (UInt_t i=0; i<expectedchisqPerRun.size(); i++) {
2195  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2196  ndfPerHisto.push_back(ndf_run);
2197  }
2198 
2199  // feed the msr-file handler
2201  if (statistics) {
2202  statistics->fMinPerHisto = chisqPerRun;
2203  statistics->fMinExpected = totalExpectedChisq;
2204  statistics->fMinExpectedPerHisto = expectedchisqPerRun;
2205  statistics->fNdfPerHisto = ndfPerHisto;
2206  }
2207  } else if (chisqPerRun.size() > 1) { // in case expected chisq is not applicable like for asymmetry fits
2208  UInt_t ndf_run = 0;
2209  for (UInt_t i=0; i<chisqPerRun.size(); i++) {
2210  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2211  ndfPerHisto.push_back(ndf_run);
2212  }
2213 
2214  // feed the msr-file handler
2216  if (statistics) {
2217  statistics->fMinPerHisto = chisqPerRun;
2218  statistics->fNdfPerHisto = ndfPerHisto;
2219  }
2220  }
2221 
2222  // check if sector command has been requested
2223  if (fSectorFlag) {
2224  PDoubleVector error;
2225  for (UInt_t i=0; i<fParams.size(); i++)
2226  error.push_back(fParams[i].fStep);
2227 
2228  PrepareSector(param, error);
2229  }
2230 
2231  // clean up
2232  param.clear();
2233  expectedchisqPerRun.clear();
2234  ndfPerHisto.clear();
2235  chisqPerRun.clear();
2236 
2237  std::cout << ">> PFitter::ExecuteSave(): will write minuit2 output file ..." << std::endl;
2238 
2239  std::ofstream fout;
2240 
2241  // open minuit2 output file
2242  if (firstSave)
2243  fout.open("MINUIT2.OUTPUT", std::iostream::out);
2244  else
2245  fout.open("MINUIT2.OUTPUT", std::iostream::out | std::iostream::app);
2246 
2247  if (!fout.is_open()) {
2248  std::cerr << std::endl << "**ERROR** PFitter::ExecuteSave() couldn't open MINUIT2.OUTPUT file";
2249  std::cerr << std::endl;
2250  return false;
2251  }
2252 
2253  // write header
2254  TDatime dt;
2255  fout << std::endl << "*************************************************************************";
2256  fout << std::endl << " musrfit MINUIT2 output file from " << fRunInfo->GetFileName().Data() << " - " << dt.AsSQLString();
2257  fout << std::endl << "*************************************************************************";
2258  fout << std::endl;
2259 
2260  // write elapsed times
2261  fout << std::endl << " elapsed times:";
2262  for (UInt_t i=0; i<fElapsedTime.size(); i++) {
2263  fout << std::endl << " " << fElapsedTime[i];
2264  }
2265  fout << std::endl;
2266  fout << std::endl << "*************************************************************************";
2267  fout << std::endl;
2268  fElapsedTime.clear();
2269 
2270  // write global information
2271  fout << std::endl << " Fval() = " << mnState.Fval() << ", Edm() = " << mnState.Edm() << ", NFcn() = " << mnState.NFcn();
2272  fout << std::endl;
2273  fout << std::endl << "*************************************************************************";
2274  fout << std::endl;
2275 
2276  // identifiy the longest variable name for proper formating reasons
2277  Int_t maxLength = 10;
2278  for (UInt_t i=0; i<fParams.size(); i++) {
2279  if (fParams[i].fName.Length() > maxLength)
2280  maxLength = fParams[i].fName.Length() + 1;
2281  }
2282 
2283  // write parameters
2284  fParams = *(fRunInfo->GetMsrParamList()); // get the update parameters back
2285  fout << std::endl << " PARAMETERS";
2286  fout << std::endl << "-------------------------------------------------------------------------";
2287  fout << std::endl << " ";
2288  for (Int_t j=0; j<=maxLength-4; j++)
2289  fout << " ";
2290  fout << "Parabolic Minos";
2291  fout << std::endl << " No Name";
2292  for (Int_t j=0; j<=maxLength-4; j++)
2293  fout << " ";
2294  fout << "Value Error Negative Positive Limits";
2295  for (UInt_t i=0; i<fParams.size(); i++) {
2296  // write no
2297  fout.setf(std::ios::right, std::ios::adjustfield);
2298  fout.width(3);
2299  fout << std::endl << i+1 << " ";
2300  // write name
2301  fout << fParams[i].fName.Data();
2302  for (Int_t j=0; j<=maxLength-fParams[i].fName.Length(); j++)
2303  fout << " ";
2304  // write value
2305  fout.setf(std::ios::left, std::ios::adjustfield);
2306  fout.precision(6);
2307  fout.width(10);
2308  fout << fParams[i].fValue << " ";
2309  // write parabolic error
2310  fout.setf(std::ios::left, std::ios::adjustfield);
2311  fout.precision(6);
2312  fout.width(10);
2313  if (fParams[i].fStep != 0.0)
2314  fout << fMnUserParams.Error(i) << " ";
2315  else
2316  fout << "---";
2317  // write minos errors
2318  if (fParams[i].fPosErrorPresent) {
2319  fout.setf(std::ios::left, std::ios::adjustfield);
2320  fout.precision(6);
2321  fout.width(12);
2322  fout << fParams[i].fStep;
2323  fout.setf(std::ios::left, std::ios::adjustfield);
2324  fout.precision(6);
2325  fout.width(11);
2326  fout << fParams[i].fPosError << " ";
2327  } else {
2328  fout.setf(std::ios::left, std::ios::adjustfield);
2329  fout.width(12);
2330  fout << "---";
2331  fout.setf(std::ios::left, std::ios::adjustfield);
2332  fout.width(12);
2333  fout << "---";
2334  }
2335  // write limits
2336  if (fParams[i].fNoOfParams > 5) {
2337  fout.setf(std::ios::left, std::ios::adjustfield);
2338  fout.width(7);
2339  if (fParams[i].fLowerBoundaryPresent)
2340  fout << fParams[i].fLowerBoundary;
2341  else
2342  fout << "---";
2343  fout.setf(std::ios::left, std::ios::adjustfield);
2344  fout.width(7);
2345  if (fParams[i].fUpperBoundaryPresent)
2346  fout << fParams[i].fUpperBoundary;
2347  else
2348  fout << "---";
2349  } else {
2350  fout.setf(std::ios::left, std::ios::adjustfield);
2351  fout.width(7);
2352  fout << "---";
2353  fout.setf(std::ios::left, std::ios::adjustfield);
2354  fout.width(7);
2355  fout << "---";
2356  }
2357  }
2358  fout << std::endl;
2359  fout << std::endl << "*************************************************************************";
2360 
2361  // write covariance matrix
2362  fout << std::endl << " COVARIANCE MATRIX";
2363  fout << std::endl << "-------------------------------------------------------------------------";
2364  if (mnState.HasCovariance()) {
2365  ROOT::Minuit2::MnUserCovariance cov = mnState.Covariance();
2366  fout << std::endl << "from " << cov.Nrow() << " free parameters";
2367  for (UInt_t i=0; i<cov.Nrow(); i++) {
2368  fout << std::endl;
2369  for (UInt_t j=0; j<i; j++) {
2370  fout.setf(std::ios::left, std::ios::adjustfield);
2371  fout.precision(6);
2372  if (cov(i,j) > 0.0) {
2373  fout << " ";
2374  fout.width(13);
2375  } else {
2376  fout.width(14);
2377  }
2378  fout << cov(i,j);
2379  }
2380  }
2381  } else {
2382  fout << std::endl << " no covariance matrix available";
2383  }
2384  fout << std::endl;
2385  fout << std::endl << "*************************************************************************";
2386 
2387  // write correlation matrix
2388  fout << std::endl << " CORRELATION COEFFICIENTS";
2389  fout << std::endl << "-------------------------------------------------------------------------";
2390  if (mnState.HasGlobalCC() && mnState.HasCovariance()) {
2391  ROOT::Minuit2::MnGlobalCorrelationCoeff corr = mnState.GlobalCC();
2392  ROOT::Minuit2::MnUserCovariance cov = mnState.Covariance();
2393  PIntVector parNo;
2394  fout << std::endl << " No Global ";
2395  for (UInt_t i=0; i<fParams.size(); i++) {
2396  // only free parameters, i.e. not fixed, and not unsed ones!
2397  if ((fParams[i].fStep != 0) && (fRunInfo->ParameterInUse(i) > 0) && (!fMnUserParams.Parameters().at(i).IsFixed())) {
2398  fout.setf(std::ios::left, std::ios::adjustfield);
2399  fout.width(9);
2400  fout << i+1;
2401  parNo.push_back(i);
2402  }
2403  }
2404  // check that there is a correspondens between minuit2 and musrfit book keeping
2405  if (parNo.size() != cov.Nrow()) {
2406  std::cerr << std::endl << "**SEVERE ERROR** in PFitter::ExecuteSave(): minuit2 and musrfit book keeping to not correspond! Unable to write correlation matrix.";
2407  std::cerr << std::endl;
2408  } else { // book keeping is OK
2409  TString title("Minuit2 Output Correlation Matrix for ");
2410  title += fRunInfo->GetFileName();
2411  title += " - ";
2412  title += dt.AsSQLString();
2413  std::unique_ptr<TCanvas> ccorr = std::make_unique<TCanvas>("ccorr", "title", 500, 500);
2414  std::unique_ptr<TH2D> hcorr = std::make_unique<TH2D>("hcorr", title, cov.Nrow(), 0.0, cov.Nrow(), cov.Nrow(), 0.0, cov.Nrow());
2415  Double_t dval;
2416  for (UInt_t i=0; i<cov.Nrow(); i++) {
2417  // parameter number
2418  fout << std::endl << " ";
2419  fout.setf(std::ios::left, std::ios::adjustfield);
2420  fout.width(5);
2421  fout << parNo[i]+1;
2422  // global correlation coefficient
2423  fout.setf(std::ios::left, std::ios::adjustfield);
2424  fout.precision(6);
2425  fout.width(12);
2426  fout << corr.GlobalCC()[i];
2427  // correlations matrix
2428  for (UInt_t j=0; j<cov.Nrow(); j++) {
2429  fout.setf(std::ios::left, std::ios::adjustfield);
2430 // fout.precision(4);
2431  if (i==j) {
2432  fout.width(9);
2433  fout << " 1.0 ";
2434  hcorr->Fill((Double_t)i,(Double_t)i,1.0);
2435  } else {
2436  // check that errors are none zero
2437  if (fMnUserParams.Error(parNo[i]) == 0.0) {
2438  std::cerr << std::endl << "**SEVERE ERROR** in PFitter::ExecuteSave(): parameter no " << parNo[i]+1 << " has an error == 0. Cannot correctly handle the correlation matrix.";
2439  std::cerr << std::endl;
2440  dval = 0.0;
2441  } else if (fMnUserParams.Error(parNo[j]) == 0.0) {
2442  std::cerr << std::endl << "**SEVERE ERROR** in PFitter::ExecuteSave(): parameter no " << parNo[j]+1 << " has an error == 0. Cannot correctly handle the correlation matrix.";
2443  std::cerr << std::endl;
2444  dval = 0.0;
2445  } else {
2446  dval = cov(i,j)/(fMnUserParams.Error(parNo[i])*fMnUserParams.Error(parNo[j]));
2447  }
2448  hcorr->Fill((Double_t)i,(Double_t)j,dval);
2449  // handle precision, ugly but ...
2450  if (dval < 1.0e-2) {
2451  fout.precision(2);
2452  } else {
2453  fout.precision(4);
2454  }
2455  // handle sign
2456  if (dval > 0.0) {
2457  fout << " ";
2458  fout.width(7);
2459  } else {
2460  fout.width(8);
2461  }
2462  fout << dval << " ";
2463  }
2464  }
2465  }
2466  // write correlation matrix into a root file
2467  TFile ff("MINUIT2.root", "recreate");
2468  ccorr->Draw();
2469  if (cov.Nrow() <= 6)
2470  hcorr->Draw("COLZTEXT");
2471  else
2472  hcorr->Draw("COLZ");
2473  ccorr->Write("ccorr", TObject::kOverwrite, sizeof(ccorr));
2474  hcorr->Write("hcorr", TObject::kOverwrite, sizeof(hcorr));
2475  ff.Close();
2476  }
2477  parNo.clear(); // clean up
2478  } else {
2479  fout << std::endl << " no correlation coefficients available";
2480  }
2481 
2482  fout << std::endl;
2483  fout << std::endl << "*************************************************************************";
2484  fout << std::endl << " chisq/maxLH RESULT ";
2485  fout << std::endl << "*************************************************************************";
2487 
2488  // get time range and write it
2489  Double_t fitStartTime = PMUSR_UNDEFINED, fitEndTime = PMUSR_UNDEFINED;
2490  // first check if there is a global block with a valid time range
2491  PMsrGlobalBlock *global = fRunInfo->GetMsrGlobal();
2492  fitStartTime = global->GetFitRange(0);
2493  fitEndTime = global->GetFitRange(1);
2494  if (fitStartTime == PMUSR_UNDEFINED) { // no global time range, hence take the one from the first run block
2496  fitStartTime = run->at(0).GetFitRange(0);
2497  fitEndTime = run->at(0).GetFitRange(1);
2498  }
2499  fout.setf(std::ios::fixed, std::ios::floatfield);
2500  fout << std::endl << " Time Range: " << fitStartTime << ", " << fitEndTime << std::endl;
2501  if (fUseChi2) {
2502  fout.setf(std::ios::fixed, std::ios::floatfield);
2503  fout << std::endl << " chisq = " << std::setprecision(4) << statistics->fMin << ", NDF = " << statistics->fNdf << ", chisq/NDF = " << std::setprecision(6) << statistics->fMin/statistics->fNdf;
2504  if (statistics->fMinExpected > 0)
2505  fout << std::endl << " chisq_e = " << std::setprecision(4) << statistics->fMinExpected << ", NDF = " << statistics->fNdf << ", chisq_e/NDF = " << std::setprecision(6) << statistics->fMinExpected/statistics->fNdf;
2506  } else { // maxLH
2507  fout.setf(std::ios::fixed, std::ios::floatfield);
2508  fout << std::endl << " maxLH = " << std::setprecision(4) << statistics->fMin << ", NDF = " << statistics->fNdf << ", maxLH/NDF = " << std::setprecision(6) << statistics->fMin/statistics->fNdf;
2509  if (statistics->fMinExpected > 0)
2510  fout << std::endl << " maxLH_e = " << std::setprecision(4) << statistics->fMinExpected << ", NDF = " << statistics->fNdf << ", maxLH_e/NDF = " << std::setprecision(6) << statistics->fMinExpected/statistics->fNdf;
2511  }
2512 
2513  if (fSectorFlag)
2514  ExecuteSector(fout);
2515 
2516  fout << std::endl;
2517  fout << std::endl << "*************************************************************************";
2518  fout << std::endl << " DONE ";
2519  fout << std::endl << "*************************************************************************";
2520  fout << std::endl << std::endl;
2521 
2522  // close MINUIT2.OUTPUT file
2523  fout.close();
2524 
2525  return true;
2526 }
2527 
2528 //--------------------------------------------------------------------------
2529 // ExecuteSimplex
2530 //--------------------------------------------------------------------------
2537 {
2538  std::cout << ">> PFitter::ExecuteSimplex(): will call simplex ..." << std::endl;
2539 
2540  // create minimizer object
2541  // strategy is by default = 'default'
2542  ROOT::Minuit2::MnSimplex simplex((*fFitterFcn), fMnUserParams, fStrategy);
2543 
2544  // minimize
2545  // maxfcn is 10*MINUIT2 Default maxfcn
2546  UInt_t maxfcn = std::numeric_limits<UInt_t>::max();
2547  // tolerance = MINUIT2 Default tolerance
2548  Double_t tolerance = 0.1;
2549  // keep track of elapsed time
2550  Double_t start=0.0, end=0.0;
2551  start=MilliTime();
2552  ROOT::Minuit2::FunctionMinimum min = simplex(maxfcn, tolerance);
2553  end=MilliTime();
2554  std::cout << ">> PFitter::ExecuteMinimize(): execution time for Simplex = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
2555  TString str = TString::Format("Simplex: %.3f sec", (end-start)/1.0e3);
2556  fElapsedTime.push_back(str);
2557  if (!min.IsValid()) {
2558  std::cerr << std::endl << ">> PFitter::ExecuteSimplex(): **WARNING**: Fit did not converge, sorry ...";
2559  std::cerr << std::endl;
2560  fIsValid = false;
2561  return false;
2562  }
2563 
2564  // keep FunctionMinimum object
2565  fFcnMin.reset(new ROOT::Minuit2::FunctionMinimum(min));
2566 
2567  // keep user parameters
2568  if (fFcnMin)
2569  fMnUserParams = fFcnMin->UserParameters();
2570 
2571  // fill run info
2572  for (UInt_t i=0; i<fParams.size(); i++) {
2573  Double_t dval = min.UserState().Value(i);
2574  if (fPhase[i]) {
2575  Int_t m = (Int_t)(dval/360.0);
2576  dval = dval - m*360.0;
2577  }
2578  fRunInfo->SetMsrParamValue(i, dval);
2579  fRunInfo->SetMsrParamStep(i, min.UserState().Error(i));
2581  }
2582 
2583  // handle statistics
2584  Double_t minVal = min.Fval();
2585  UInt_t ndf = fFitterFcn->GetTotalNoOfFittedBins();
2586  // subtract number of varied parameters from total no of fitted bins -> ndf
2587  for (UInt_t i=0; i<fParams.size(); i++) {
2588  if ((min.UserState().Error(i) != 0.0) && !fMnUserParams.Parameters().at(i).IsFixed())
2589  ndf -= 1;
2590  }
2591 
2592  // feed run info with new statistics info
2593  fRunInfo->SetMsrStatisticMin(minVal);
2595 
2596  fConverged = true;
2597 
2598  if (fPrintLevel >= 2)
2599  std::cout << *fFcnMin << std::endl;
2600 
2601  return true;
2602 }
2603 
2604 //--------------------------------------------------------------------------
2605 // PrepareSector
2606 //--------------------------------------------------------------------------
2614 {
2615  Double_t val;
2616  UInt_t ndf;
2617 
2618  Int_t usedParams = 0;
2619  for (UInt_t i=0; i<error.size(); i++) {
2620  if (error[i] != 0.0)
2621  usedParams++;
2622  }
2623 
2624  PDoublePairVector secFitRange;
2625  secFitRange.resize(1);
2626 
2627  if (fUseChi2) {
2628  Double_t totalExpectedChisq = 0.0;
2629  PDoubleVector expectedChisqPerRun;
2630  PDoubleVector chisqPerRun;
2631  for (UInt_t k=0; k<fSector.size(); k++) {
2632  // set sector fit range
2633  secFitRange[0].first = fSector[k].GetTimeRangeFirst(0);
2634  secFitRange[0].second = fSector[k].GetTimeRangeLast();
2635  fRunListCollection->SetFitRange(secFitRange);
2636  // calculate chisq
2637  val = (*fFitterFcn)(param);
2638  fSector[k].SetChisq(val);
2639  // calculate NDF
2640  ndf = static_cast<UInt_t>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
2641  fSector[k].SetNDF(ndf);
2642  // calculate expected chisq
2643  totalExpectedChisq = 0.0;
2644  fFitterFcn->CalcExpectedChiSquare(param, totalExpectedChisq, expectedChisqPerRun);
2645  fSector[k].SetExpectedChisq(totalExpectedChisq);
2646  // calculate chisq per run
2647  for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
2648  chisqPerRun.push_back(fRunListCollection->GetSingleRunChisq(param, i));
2649  fSector[k].SetChisq(chisqPerRun[i], i);
2650  fSector[k].SetExpectedChisq(expectedChisqPerRun[i], i);
2651  }
2652 
2653  if (totalExpectedChisq != 0.0) {
2654  UInt_t ndf_run = 0;
2655  for (UInt_t i=0; i<expectedChisqPerRun.size(); i++) {
2656  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2657  if (ndf_run > 0) {
2658  fSector[k].SetNDF(ndf_run, i);
2659  }
2660  }
2661  } else if (chisqPerRun.size() > 0) { // in case expected chisq is not applicable like for asymmetry fits
2662  UInt_t ndf_run = 0;
2663  for (UInt_t i=0; i<chisqPerRun.size(); i++) {
2664  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2665  if (ndf_run > 0) {
2666  fSector[k].SetNDF(ndf_run, i);
2667  }
2668  }
2669  }
2670  // clean up
2671  chisqPerRun.clear();
2672  expectedChisqPerRun.clear();
2673  }
2674  } else {
2675  Double_t totalExpectedMaxLH = 0.0;
2676  PDoubleVector expectedMaxLHPerRun;
2677  PDoubleVector maxLHPerRun;
2678  for (UInt_t k=0; k<fSector.size(); k++) {
2679  // set sector fit range
2680  secFitRange[0].first = fSector[k].GetTimeRangeFirst(0);
2681  secFitRange[0].second = fSector[k].GetTimeRangeLast();
2682  fRunListCollection->SetFitRange(secFitRange);
2683  // calculate maxLH
2684  val = (*fFitterFcn)(param);
2685  fSector[k].SetChisq(val);
2686  // calculate NDF
2687  ndf = static_cast<UInt_t>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
2688  fSector[k].SetNDF(ndf);
2689  // calculate expected maxLH
2690  totalExpectedMaxLH = 0.0;
2691  fFitterFcn->CalcExpectedChiSquare(param, totalExpectedMaxLH, expectedMaxLHPerRun);
2692  fSector[k].SetExpectedChisq(totalExpectedMaxLH);
2693  // calculate maxLH per run
2694  for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
2695  maxLHPerRun.push_back(fRunListCollection->GetSingleRunMaximumLikelihood(param, i));
2696  fSector[k].SetChisq(maxLHPerRun[i], i);
2697  fSector[k].SetExpectedChisq(expectedMaxLHPerRun[i], i);
2698  }
2699 
2700  if (totalExpectedMaxLH != 0.0) {
2701  UInt_t ndf_run = 0;
2702  for (UInt_t i=0; i<expectedMaxLHPerRun.size(); i++) {
2703  ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2704  if (ndf_run > 0) {
2705  fSector[k].SetNDF(ndf_run, i);
2706  }
2707  }
2708  }
2709 
2710  // clean up
2711  maxLHPerRun.clear();
2712  expectedMaxLHPerRun.clear();
2713  }
2714  }
2715 }
2716 
2717 //--------------------------------------------------------------------------
2718 // ExecuteSector
2719 //--------------------------------------------------------------------------
2726 Bool_t PFitter::ExecuteSector(std::ofstream &fout)
2727 {
2728  fout << std::endl;
2729  fout << std::endl << "*************************************************************************";
2730  fout << std::endl << " SECTOR RESULTS";
2731  fout << std::endl << "*************************************************************************";
2732 
2733  if (fUseChi2) {
2734  for (UInt_t i=0; i<fSector.size(); i++) {
2735  fout << std::endl;
2736  fout << " Sector " << i+1 << ": FitRange: " << fSector[i].GetTimeRangeFirst(0) << ", " << fSector[i].GetTimeRangeLast() << std::endl;
2737  fout << " chisq = " << fSector[i].GetChisq() << ", NDF = " << fSector[i].GetNDF() << ", chisq/NDF = " << fSector[i].GetChisq()/fSector[i].GetNDF();
2738 
2739  if (fSector[i].GetExpectedChisq() > 0) {
2740  fout << std::endl << " expected chisq = " << fSector[i].GetExpectedChisq() << ", NDF = " << fSector[i].GetNDF() << ", expected chisq/NDF = " << fSector[i].GetExpectedChisq()/fSector[i].GetNDF();
2741  for (UInt_t j=0; j<fSector[i].GetNoRuns(); j++) {
2742  fout << std::endl << " run block " << j+1 << " (NDF/red.chisq/red.chisq_e) = (" << fSector[i].GetNDF(j) << "/" << fSector[i].GetChisq(j)/fSector[i].GetNDF(j) << "/" << fSector[i].GetExpectedChisq(j)/fSector[i].GetNDF(j) << ")";
2743  }
2744  } else if (fSector[i].GetNoRuns() > 0) { // in case expected chisq is not applicable like for asymmetry fits
2745  for (UInt_t j=0; j<fSector[i].GetNoRuns(); j++) {
2746  fout << std::endl << " run block " << j+1 << " (NDF/red.chisq) = (" << fSector[i].GetNDF(j) << "/" << fSector[i].GetChisq(j)/fSector[i].GetNDF(j) << ")";
2747  }
2748  }
2749  fout << std::endl << "++++";
2750  }
2751  } else { // max log likelihood
2752  for (UInt_t i=0; i<fSector.size(); i++) {
2753  fout << std::endl;
2754  fout << " Sector " << i+1 << ": FitRange: " << fSector[i].GetTimeRangeFirst(0) << ", " << fSector[i].GetTimeRangeLast() << std::endl;
2755  fout << " maxLH = " << fSector[i].GetChisq() << ", NDF = " << fSector[i].GetNDF() << ", maxLH/NDF = " << fSector[i].GetChisq()/fSector[i].GetNDF();
2756 
2757  if (fSector[i].GetExpectedChisq() > 0) {
2758  fout << std::endl << " expected maxLH = " << fSector[i].GetExpectedChisq() << ", NDF = " << fSector[i].GetNDF() << ", expected maxLH/NDF = " << fSector[i].GetExpectedChisq()/fSector[i].GetNDF();
2759  for (UInt_t j=0; j<fSector[i].GetNoRuns(); j++) {
2760  fout << std::endl << " run block " << j+1 << " (NDF/red.maxLH/red.maxLH_e) = (" << fSector[i].GetNDF(j) << "/" << fSector[i].GetChisq(j)/fSector[i].GetNDF(j) << "/" << fSector[i].GetExpectedChisq(j)/fSector[i].GetNDF(j) << ")";
2761  }
2762  } else if (fSector[i].GetNoRuns() > 0) { // in case expected chisq is not applicable like for asymmetry fits
2763  for (UInt_t j=0; j<fSector[i].GetNoRuns(); j++) {
2764  fout << std::endl << " run block " << j+1 << " (NDF/red.maxLH) = (" << fSector[i].GetNDF(j) << "/" << fSector[i].GetChisq(j)/fSector[i].GetNDF(j) << ")";
2765  }
2766  }
2767  fout << std::endl << "++++";
2768  }
2769  }
2770 
2771  return true;
2772 }
2773 
2774 //--------------------------------------------------------------------------
2775 // MilliTime
2776 //--------------------------------------------------------------------------
2783 {
2784  struct timeval now;
2785  gettimeofday(&now, nullptr);
2786 
2787  return ((Double_t)now.tv_sec * 1.0e6 + (Double_t)now.tv_usec)/1.0e3;
2788 }
2789 
2790 //-------------------------------------------------------------------------------------------------
2791 // end
2792 //-------------------------------------------------------------------------------------------------
Bool_t fIsValid
flag. true: the fit is valid.
Definition: PFitter.h:123
#define PMN_FIX
Definition: PFitter.h:47
#define PMN_SAVE
Definition: PFitter.h:56
Bool_t SetParameters()
Definition: PFitter.cpp:1518
PFitter(PMsrHandler *runInfo, PRunListCollection *runListCollection, Bool_t chisq_only=false)
Definition: PFitter.cpp:267
Bool_t ExecuteSimplex()
Definition: PFitter.cpp:2536
virtual void SetFitRange(const PDoublePairVector fitRange)
std::pair< Double_t, Double_t > PDoublePair
Definition: PMusr.h:202
Double_t GetTimeRangeFirst(UInt_t idx)
Definition: PFitter.cpp:193
Bool_t ExecuteSave(Bool_t first)
Definition: PFitter.cpp:2150
Bool_t ExecuteMinimize()
Definition: PFitter.cpp:1835
PDoubleVector fFirst
time stamp for fgb for a given run
Definition: PFitter.h:101
std::unique_ptr< PFitterFcn > fFitterFcn
pointer to the fitter function object
Definition: PFitter.h:140
PIntPairVector fCmdList
command list, first=cmd, second=cmd line index
Definition: PFitter.h:138
std::vector< bool > fPhase
flag array in which an entry is true if the related parameter value is a phase
Definition: PFitter.h:160
Bool_t fIsScanOnly
flag. true: scan along some parameters (no fitting).
Definition: PFitter.h:124
Bool_t fChisqOnly
flag. true: calculate chi^2 only (no fitting).
Definition: PFitter.h:126
std::vector< PMsrRunBlock > PMsrRunList
Definition: PMusr.h:754
void PrepareSector(PDoubleVector &param, PDoubleVector &error)
Definition: PFitter.cpp:2613
#define PMN_MINOS
Definition: PFitter.h:52
Bool_t ExecuteContours()
Definition: PFitter.cpp:1566
PDoubleVector fMinPerHisto
chisq or max. likelihood per histo
Definition: PMusr.h:814
PMsrLines fCmdLines
all the Minuit commands from the msr-file
Definition: PFitter.h:137
#define PMN_USER_COVARIANCE
Definition: PFitter.h:60
PIntVector GetParFromMap(const TString mapStr)
Definition: PFitter.cpp:497
PStringVector fElapsedTime
Definition: PFitter.h:155
#define PMN_HESSE
Definition: PFitter.h:48
Bool_t DoFit()
Definition: PFitter.cpp:546
#define PMN_SIMPLEX
Definition: PFitter.h:58
PDoubleVector fChisqRun
chisq or maxLH for the sector and run
Definition: PFitter.h:102
#define PMN_RESTORE
Definition: PFitter.h:55
Double_t fMin
chisq or max. likelihood
Definition: PMusr.h:813
void SetChisq(Double_t chisq)
Definition: PFitter.h:78
Bool_t ExecuteRelease(UInt_t lineNo)
Definition: PFitter.cpp:2059
PMsrHandler * fRunInfo
pointer to the msr-file handler
Definition: PFitter.h:132
PDoublePairVector fScanData
keeps the scan/contour data
Definition: PFitter.h:151
Bool_t fValid
flag showing if the statistics block is valid, i.e. a fit took place which converged ...
Definition: PMusr.h:809
Bool_t ExecuteFix(UInt_t lineNo)
Definition: PFitter.cpp:1672
#define PMN_RELEASE
Definition: PFitter.h:54
std::vector< Int_t > PIntVector
Definition: PMusr.h:178
void SetExpectedChisq(Double_t expChisq)
Definition: PFitter.h:80
UInt_t fStrategy
fitting strategy (see minuit2 manual).
Definition: PFitter.h:130
Bool_t ExecuteMinos()
Definition: PFitter.cpp:1912
#define PMN_MINIMIZE
Definition: PFitter.h:51
Bool_t ExecuteScan()
Definition: PFitter.cpp:2123
virtual void SetMsrStatisticMin(Double_t min)
Definition: PMsrHandler.h:90
PDoubleVector fExpectedChisqRun
expected chisq or maxLH for the sector and run
Definition: PFitter.h:103
std::vector< Double_t > PDoubleVector
Definition: PMusr.h:196
virtual void SetMsrStatisticNdf(UInt_t ndf)
Definition: PMsrHandler.h:91
Bool_t ExecuteSector(std::ofstream &fout)
Definition: PFitter.cpp:2726
Bool_t CheckCommands()
Definition: PFitter.cpp:831
virtual PMsrRunList * GetMsrRunList()
Definition: PMsrHandler.h:63
UInt_t fNDF
NDF for the sector.
Definition: PFitter.h:100
virtual PMsrStatisticStructure * GetMsrStatistic()
Definition: PMsrHandler.h:67
Double_t fExpectedChisq
keep the expected chisq or maxLH for the sector
Definition: PFitter.h:99
virtual UInt_t GetNoOfRuns()
Definition: PMsrHandler.h:71
Bool_t fUseChi2
flag. true: chi^2 fit. false: log-max-likelihood
Definition: PFitter.h:127
virtual UInt_t GetNoOfParams()
Definition: PMsrHandler.h:73
#define PMN_PRINT
Definition: PFitter.h:62
ROOT::Minuit2::MnUserParameters fMnUserParams
minuit2 input parameter list
Definition: PFitter.h:142
virtual Int_t ParameterInUse(UInt_t paramNo)
Double_t GetChisq()
Definition: PFitter.h:87
PMsrParamList fParams
msr-file parameters
Definition: PFitter.h:135
virtual PMsrGlobalBlock * GetMsrGlobal()
Definition: PMsrHandler.h:62
#define PMN_CONTOURS
Definition: PFitter.h:44
#define PMN_PLOT
Definition: PFitter.h:53
virtual ~PFitter()
Definition: PFitter.cpp:326
std::vector< PMsrLineStructure > PMsrLines
Definition: PMusr.h:539
Double_t fScanHigh
scan range high. default=0.0 which means 2 std dev. (see MnScan/MnContours in the minuit2 user manual...
Definition: PFitter.h:150
virtual Double_t GetSingleRunChisq(const std::vector< Double_t > &par, const UInt_t idx) const
PDoubleVector fMinExpectedPerHisto
expected pre histo chi2 or max. likelihood
Definition: PMusr.h:817
Bool_t ExecuteMigrad()
Definition: PFitter.cpp:1759
virtual Bool_t SetMsrParamStep(UInt_t i, Double_t value)
UInt_t fScanNoPoints
number of points in a scan/contour (see MnScan/MnContours in the minuit2 user manual) ...
Definition: PFitter.h:148
#define PMN_EIGEN
Definition: PFitter.h:45
#define PMUSR_UNDEFINED
Definition: PMusr.h:89
Double_t GetExpectedChisq()
Definition: PFitter.h:89
Bool_t ExecutePlot()
Definition: PFitter.cpp:1981
Bool_t fSectorFlag
sector command present flag
Definition: PFitter.h:157
Bool_t IsValid()
Definition: PFitter.h:117
virtual Bool_t SetMsrParamValue(UInt_t i, Double_t value)
Bool_t fChisq
flag telling if min = chi2 or min = max.likelihood
Definition: PMusr.h:812
void SetNDF(UInt_t ndf)
Definition: PFitter.h:82
#define PMN_MACHINE_PRECISION
Definition: PFitter.h:49
#define PMN_USER_PARAM_STATE
Definition: PFitter.h:61
virtual PMsrLines * GetMsrTheory()
Definition: PMsrHandler.h:60
UInt_t GetNDF()
Definition: PFitter.h:91
virtual UInt_t GetNoOfFitParameters(UInt_t idx)
Double_t fMinExpected
expected total chi2 or max. likelihood
Definition: PMusr.h:816
std::vector< PDoublePair > PDoublePairVector
Definition: PMusr.h:208
UInt_t fNoOfRuns
number of runs presesent
Definition: PFitter.h:96
PSectorChisq(UInt_t noOfRuns)
Definition: PFitter.cpp:79
PRunListCollection * fRunListCollection
pointer to the run list collection
Definition: PFitter.h:133
Bool_t ExecuteFitRange(UInt_t lineNo)
Definition: PFitter.cpp:1601
PUIntVector fNDFRun
NDF for the sector and run.
Definition: PFitter.h:104
void SetRunFirstTime(Double_t first, UInt_t idx)
Definition: PFitter.cpp:107
UInt_t fScanParameter[2]
scan parameter. idx=0: used for scan and contour, idx=1: used for contour (see MnScan/MnContours in t...
Definition: PFitter.h:147
virtual PMsrParamList * GetMsrParamList()
Definition: PMsrHandler.h:59
Double_t fScanLow
scan range low. default=0.0 which means 2 std dev. (see MnScan/MnContours in the minuit2 user manual)...
Definition: PFitter.h:149
#define PMN_FIT_RANGE
Definition: PFitter.h:46
Double_t fChisq
chisq or maxLH for the sector
Definition: PFitter.h:98
Bool_t fScanAll
flag. false: single parameter scan, true: not implemented yet (see MnScan/MnContours in the minuit2 u...
Definition: PFitter.h:146
UInt_t fNdf
number of degrees of freedom
Definition: PMusr.h:815
#define PMN_INTERACTIVE
Definition: PFitter.h:43
#define PMN_SECTOR
Definition: PFitter.h:63
PIntVector GetParFromFun(const TString funStr)
Definition: PFitter.cpp:430
virtual PMsrLines * GetMsrFunctions()
Definition: PMsrHandler.h:61
Double_t MilliTime()
Definition: PFitter.cpp:2782
#define PMN_SCAN
Definition: PFitter.h:57
UInt_t fPrintLevel
tag, showing the level of messages whished. 0=minimum, 1=standard, 2=maximum
Definition: PFitter.h:128
return status
void GetPhaseParams()
Definition: PFitter.cpp:342
virtual PMsrLines * GetMsrCommands()
Definition: PMsrHandler.h:64
virtual Bool_t SetMsrParamPosErrorPresent(UInt_t i, Bool_t value)
Bool_t fConverged
flag. true: the fit has converged.
Definition: PFitter.h:125
virtual Double_t GetFitRange(UInt_t idx)
Definition: PMusr.cpp:1051
Double_t fLast
requested time stamp
Definition: PFitter.h:97
PUIntVector fNdfPerHisto
number of degrees of freedom per histo
Definition: PMusr.h:818
Bool_t ExecutePrintLevel(UInt_t lineNo)
Definition: PFitter.cpp:2001
#define PMN_MIGRAD
Definition: PFitter.h:50
virtual Bool_t SetMsrParamPosError(UInt_t i, Double_t value)
PDoublePairVector fOriginalFitRange
keeps the original fit range in case there is a range command in the COMMAND block ...
Definition: PFitter.h:153
Bool_t ExecuteRestore()
Definition: PFitter.cpp:2101
virtual Double_t GetSingleRunMaximumLikelihood(const std::vector< Double_t > &par, const UInt_t idx) const
std::pair< Int_t, Int_t > PIntPair
Definition: PMusr.h:184
std::vector< PSectorChisq > fSector
stores all chisq/maxLH sector information
Definition: PFitter.h:158
virtual const TString & GetFileName() const
Definition: PMsrHandler.h:74
std::unique_ptr< ROOT::Minuit2::FunctionMinimum > fFcnMin
function minimum object
Definition: PFitter.h:143
Bool_t ExecuteHesse()
Definition: PFitter.cpp:1710