musrfit 1.10.0
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-2026 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#include <cmath>
43
44#include <boost/variant/variant.hpp>
45
46#include <sys/time.h>
47
48#include "Minuit2/FunctionMinimum.h"
49#include "Minuit2/MnContours.h"
50#include "Minuit2/MnHesse.h"
51#include "Minuit2/MnMinimize.h"
52#include "Minuit2/MnMigrad.h"
53#include "Minuit2/MnMinos.h"
54#include "Minuit2/MnPlot.h"
55#include "Minuit2/MnPrint.h"
56#include "Minuit2/MnScan.h"
57#include "Minuit2/MnSimplex.h"
58#include "Minuit2/MnStrategy.h"
59#include "Minuit2/MnUserParameterState.h"
60#include "Minuit2/MinosError.h"
61
62#include <TCanvas.h>
63#include <TH2.h>
64#include <TFile.h>
65#include <TDatime.h>
66#include <TString.h>
67
68#include "PFitter.h"
69#include "PStringUtils.h"
70
71
72//+++ PSectorChisq class +++++++++++++++++++++++++++++++++++++++++++++++++++
73
74//--------------------------------------------------------------------------
75// Constructor
76//--------------------------------------------------------------------------
80PSectorChisq::PSectorChisq(UInt_t noOfRuns) : fNoOfRuns(noOfRuns)
81{
82 // init
83 fLast = 0.0;
84 fChisq = 0.0;
85 fExpectedChisq = 0.0;
86 fNDF = 0;
87 fFirst.resize(fNoOfRuns);
88 fChisqRun.resize(fNoOfRuns);
90 fNDFRun.resize(fNoOfRuns);
91 for (UInt_t i=0; i<fNoOfRuns; i++) {
92 fFirst[i] = 0.0;
93 fChisqRun[i] = 0.0;
94 fExpectedChisqRun[i] = 0.0;
95 fNDFRun[i] = 0;
96 }
97}
98
99//--------------------------------------------------------------------------
100// SetRunFirstTime
101//--------------------------------------------------------------------------
108void PSectorChisq::SetRunFirstTime(Double_t first, UInt_t idx)
109{
110 if (idx > fNoOfRuns) {
111 std::cerr << "**WARNING** from PSectorChisq::SetRunFirstTime. It tries to set" << std::endl;
112 std::cerr << " a fgb time stamp with idx=" << idx << " which is larger than #RUNS=" << fNoOfRuns << "." << std::endl;
113 std::cerr << " Will ignore it, but you better check what is going on!" << std::endl;
114 return;
115 }
116
117 fFirst[idx] = first;
118}
119
120//--------------------------------------------------------------------------
121// SetChisq
122//--------------------------------------------------------------------------
129void PSectorChisq::SetChisq(Double_t chisq, UInt_t idx)
130{
131 if (idx > fNoOfRuns) {
132 std::cerr << "**WARNING** from PSectorChisq::SetChisq. It tries to set" << std::endl;
133 std::cerr << " a chisq with idx=" << idx << " which is larger than #RUNS=" << fNoOfRuns << "." << std::endl;
134 std::cerr << " Will ignore it, but you better check what is going on!" << std::endl;
135 return;
136 }
137
138 fChisqRun[idx] = chisq;
139}
140
141//--------------------------------------------------------------------------
142// SetExpectedChisq
143//--------------------------------------------------------------------------
150void PSectorChisq::SetExpectedChisq(Double_t chisq, UInt_t idx)
151{
152 if (idx > fNoOfRuns) {
153 std::cerr << "**WARNING** from PSectorChisq::SetExpectedChisq. It tries to set" << std::endl;
154 std::cerr << " a chisq with idx=" << idx << " which is larger than #RUNS=" << fNoOfRuns << "." << std::endl;
155 std::cerr << " Will ignore it, but you better check what is going on!" << std::endl;
156 return;
157 }
158
159 fExpectedChisqRun[idx] = chisq;
160}
161
162//--------------------------------------------------------------------------
163// SetNDF
164//--------------------------------------------------------------------------
171void PSectorChisq::SetNDF(UInt_t ndf, UInt_t idx)
172{
173 if (idx > fNoOfRuns) {
174 std::cerr << "**WARNING** from PSectorChisq::SetNDF. It tries to set" << std::endl;
175 std::cerr << " a NDF with idx=" << idx << " which is larger than #RUNS=" << fNoOfRuns << "." << std::endl;
176 std::cerr << " Will ignore it, but you better check what is going on!" << std::endl;
177 return;
178 }
179
180 fNDFRun[idx] = ndf;
181}
182
183//--------------------------------------------------------------------------
184// GetTimeRangeFirst
185//--------------------------------------------------------------------------
195{
196 if (idx > fNoOfRuns)
197 return PMUSR_UNDEFINED;
198
199 return fFirst[idx];
200}
201
202//--------------------------------------------------------------------------
203// GetChisq
204//--------------------------------------------------------------------------
212Double_t PSectorChisq::GetChisq(UInt_t idx)
213{
214 if (idx >= fNoOfRuns)
215 return -1.0;
216
217 return fChisqRun[idx];
218}
219
220//--------------------------------------------------------------------------
221// GetExpectedChisq
222//--------------------------------------------------------------------------
231{
232 if (idx >= fNoOfRuns)
233 return -1.0;
234
235 return fExpectedChisqRun[idx];
236}
237
238//--------------------------------------------------------------------------
239// GetNDF
240//--------------------------------------------------------------------------
248UInt_t PSectorChisq::GetNDF(UInt_t idx)
249{
250 if (idx >= fNoOfRuns)
251 return 0;
252
253 return fNDFRun[idx];
254}
255
256//+++ PFitter class ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
257
258//--------------------------------------------------------------------------
259// Constructor
260//--------------------------------------------------------------------------
289PFitter::PFitter(PMsrHandler *runInfo, PRunListCollection *runListCollection, Bool_t chisq_only, Bool_t yaml_out) :
290 fChisqOnly(chisq_only), fYamlOut(yaml_out), fRunInfo(runInfo), fRunListCollection(runListCollection)
291{
292 // initialize variables
293 fIsScanOnly = true;
294 fConverged = false;
295 fUseChi2 = true; // chi^2 is the default
296
297 fStrategy = 1; // 0=low, 1=default, 2=high
298
299 fSectorFlag = false;
300
301 fParams = *(runInfo->GetMsrParamList());
302 fCmdLines = *runInfo->GetMsrCommands();
303
304 // init class variables
305 fScanAll = true;
306 fScanParameter[0] = 0;
307 fScanParameter[1] = 0;
308 fScanNoPoints = 41; // minuit2 default
309 fScanLow = 0.0; // minuit2 default, i.e. 2 std deviations
310 fScanHigh = 0.0; // minuit2 default, i.e. 2 std deviations
311 fPrintLevel = 1.0;
312
313 // keep all the fit ranges in case RANGE command is present
314 PDoublePair rangeGlob;
315 PMsrGlobalBlock *global = fRunInfo->GetMsrGlobal();
316 rangeGlob.first = global->GetFitRange(0);
317 rangeGlob.second = global->GetFitRange(1);
318
319 PMsrRunList *runs = fRunInfo->GetMsrRunList();
320 PDoublePair range;
321 for (UInt_t i=0; i<runs->size(); i++) {
322 range.first = (*runs)[i].GetFitRange(0);
323 range.second = (*runs)[i].GetFitRange(1);
324 if (range.first == PMUSR_UNDEFINED)
325 fOriginalFitRange.push_back(rangeGlob);
326 else
327 fOriginalFitRange.push_back(range);
328 }
329
330 // check msr minuit commands
331 if (!CheckCommands()) {
332 return;
333 }
334
335 // create phase bool array
337
338 // create fit function object
339 fFitterFcn = std::make_unique<PFitterFcn>(runListCollection, fUseChi2);
340}
341
342//--------------------------------------------------------------------------
343// Destructor
344//--------------------------------------------------------------------------
352{
353 fCmdList.clear();
354
355 fScanData.clear();
356
357 fElapsedTime.clear();
358}
359
360//--------------------------------------------------------------------------
361// GetPhaseParams (private)
362//--------------------------------------------------------------------------
390{
391 fPhase.resize(fRunInfo->GetNoOfParams());
392 for (unsigned int i=0; i<fPhase.size(); i++)
393 fPhase[i] = false;
394
395 // analyze theory block for parameters. Phases are present in the following
396 // default functions:
397 // user functions cannot be checked!
398 PMsrLines *theo = fRunInfo->GetMsrTheory();
399 TString str;
400 int pos = -1;
401 for (unsigned int i=0; i<theo->size(); i++) {
402 pos = -1;
403 TString line = theo->at(i).fLine;
404 if (line.Contains("TFieldCos") || line.Contains("tf ") ||
405 line.Contains("bessel") || line.Contains("b ") ||
406 line.Contains("skewedGss") || line.Contains("skg ") ||
407 line.Contains("staticNKTF") || line.Contains("snktf ") ||
408 line.Contains("dynamicNKTF") || line.Contains("dnktf ")) { // phase is 1st param
409 pos = 1;
410 }
411 if (line.Contains("internFld") || line.Contains("if ") ||
412 line.Contains("internBsl") || line.Contains("ib ")) { // phase is 2nd param
413 pos = 2;
414 }
415 if (line.Contains("muMinusExpTF") || line.Contains("mmsetf ")) { // phase is 5th param
416 pos = 5;
417 }
418
419 if (pos == -1)
420 continue;
421
422 // extract phase token
423 std::vector<std::string> tok = PStringUtils::Split(line.Data(), " \t");
424 if (static_cast<int>(tok.size()) > pos) {
425 str = tok[pos].c_str();
426 }
427
428 // decode phase token. It can be funX, mapX, or a number
429 if (str.Contains("fun")) { // function
430 PIntVector parVec = GetParFromFun(str);
431 for (int i=0; i<parVec.size(); i++) {
432 if (parVec[i] <= fRunInfo->GetNoOfParams())
433 fPhase[parVec[i]-1] = true;
434 }
435 } else if (str.Contains("map")) { // map
436 PIntVector parVec = GetParFromMap(str);
437 for (int i=0; i<parVec.size(); i++) {
438 if (parVec[i] <= fRunInfo->GetNoOfParams())
439 fPhase[parVec[i]-1] = true;
440 }
441 } else { // must be a number
442 int idx = str.Atoi();
443 if (idx == 0) { // something went wrong, str is not an integer
444 std::cerr << "PFitter::GetPhaseParams(): **ERROR** str=" << str.View() << " is not an integer!" << std::endl;
445 return;
446 }
447 idx -= 1; // param start at 1, vector at 0
448 if (idx >= fRunInfo->GetNoOfParams()) { // idx is out-of-range
449 std::cerr << "PFitter::GetPhaseParams(): **ERROR** idx=" << idx << " is > #param = " << fRunInfo->GetNoOfParams() << "!" << std::endl;
450 return;
451 }
452 fPhase[idx] = true;
453 }
454 }
455}
456
457//--------------------------------------------------------------------------
458// GetParFromFun (private)
459//--------------------------------------------------------------------------
479{
480 PIntVector parVec;
481
482 PMsrLines *funList = fRunInfo->GetMsrFunctions();
483 TString str;
484
485 for (int i=0; i<funList->size(); i++) {
486 if (funList->at(i).fLine.Contains(funStr)) {
487 // tokenize function string
488 std::vector<std::string> tok = PStringUtils::Split(funList->at(i).fLine.Data(), " =+-*/");
489
490 for (int j=1; j<static_cast<int>(tok.size()); j++) {
491 str = tok[j].c_str();
492 // parse tok for parX
493 if (str.Contains("par")) {
494 // find start idx of par in token
495 Ssiz_t idx = str.Index("par");
496 idx += 3;
497 TString parStr("");
498 do {
499 parStr += str[idx];
500 } while (isdigit(str[idx++]));
501 parVec.push_back(parStr.Atoi());
502 }
503 // parse tok for mapX
504 if (str.Contains("map")) {
505 // find start idx of par in token
506 Ssiz_t idx = str.Index("map");
507 idx += 3;
508 TString mapStr("map");
509 do {
510 mapStr += str[idx];
511 } while (isdigit(str[idx++]));
512 PIntVector mapParVec = GetParFromMap(mapStr);
513 for (int k=0; k<mapParVec.size(); k++) {
514 parVec.push_back(mapParVec[k]);
515 }
516 }
517 }
518 }
519 }
520
521 return parVec;
522}
523
524//--------------------------------------------------------------------------
525// GetParFromMap (private)
526//--------------------------------------------------------------------------
549{
550 PIntVector parVec;
551
552 TString str = mapStr;
553 str.Remove(0,3); // remove map from string
554
555 int idx=str.Atoi();
556 if (idx == 0) {
557 std::cerr << "PFitter::GetParFromMap(): **ERROR** couldn't get propper index from mapX!" << std::endl;
558 return parVec;
559 }
560
561 idx -= 1; // map starts at 1, map vector at 0
562
563 // go through all the runs and collect the parameters from the map vectors
564 PMsrRunList *runList = fRunInfo->GetMsrRunList();
565 if (runList == nullptr) {
566 std::cerr << "PFitter::GetParFromMap(): **ERROR** couldn't get required run list information!" << std::endl;
567 return parVec;
568 }
569
570 PIntVector *map = nullptr;
571 for (int i=0; i<runList->size(); i++) {
572 map = runList->at(i).GetMap();
573 if (map == nullptr) {
574 std::cerr << "PFitter::GetParFromMap(): **ERROR** couldn't get required map information (idx=" << i << ")!" << std::endl;
575 parVec.clear();
576 return parVec;
577 }
578 if (idx >= map->size()) {
579 std::cerr << "PFitter::GetParFromMap(): **ERROR** requested map index (idx=" << idx << ") out-of-range (" << map->size() << ")!" << std::endl;
580 parVec.clear();
581 return parVec;
582 }
583 parVec.push_back(map->at(idx));
584 }
585
586 return parVec;
587}
588
589//--------------------------------------------------------------------------
590// DoFit
591//--------------------------------------------------------------------------
626{
627 // feed minuit parameters
629
630 // check if only chisq/maxLH shall be calculated once
631 if (fChisqOnly) {
632 std::vector<Double_t> param = fMnUserParams.Params();
633 std::vector<Double_t> error = fMnUserParams.Errors();
634 Int_t usedParams = 0;
635 for (UInt_t i=0; i<error.size(); i++) {
636 if (error[i] != 0.0)
637 usedParams++;
638 }
639 UInt_t ndf = static_cast<int>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
640 Double_t val = (*fFitterFcn)(param);
641 if (fUseChi2) {
642 // calculate expected chisq
643 Double_t totalExpectedChisq = 0.0;
644 PDoubleVector expectedChisqPerRun;
645 fFitterFcn->CalcExpectedChiSquare(param, totalExpectedChisq, expectedChisqPerRun);
646 // calculate chisq per run
647 std::vector<Double_t> chisqPerRun;
648 for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
649 chisqPerRun.push_back(fRunListCollection->GetSingleRunChisq(param, i));
650 }
651
652 std::cout << std::endl << std::endl << ">> chisq = " << val << ", NDF = " << ndf << ", chisq/NDF = " << val/ndf;
653
654 if (totalExpectedChisq != 0.0) {
655 std::cout << std::endl << ">> expected chisq = " << totalExpectedChisq << ", NDF = " << ndf << ", expected chisq/NDF = " << totalExpectedChisq/ndf;
656 UInt_t ndf_run = 0;
657 for (UInt_t i=0; i<expectedChisqPerRun.size(); i++) {
658 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
659 if (ndf_run > 0)
660 std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.chisq/red.chisq_e) = (" << ndf_run << "/" << chisqPerRun[i]/ndf_run << "/" << expectedChisqPerRun[i]/ndf_run << ")";
661 }
662 } else if (chisqPerRun.size() > 0) { // in case expected chisq is not applicable like for asymmetry fits
663 UInt_t ndf_run = 0;
664 for (UInt_t i=0; i<chisqPerRun.size(); i++) {
665 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
666 if (ndf_run > 0)
667 std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.chisq) = (" << ndf_run << "/" << chisqPerRun[i]/ndf_run << ")";
668 }
669 }
670
671 // clean up
672 chisqPerRun.clear();
673 expectedChisqPerRun.clear();
674
675 if (fSectorFlag) {
676 PDoublePairVector secFitRange;
677 secFitRange.resize(1);
678 for (UInt_t k=0; k<fSector.size(); k++) {
679 // set sector fit range
680 secFitRange[0].first = fSector[k].GetTimeRangeFirst(0);
681 secFitRange[0].second = fSector[k].GetTimeRangeLast();
682 fRunListCollection->SetFitRange(secFitRange);
683 // calculate chisq
684 val = (*fFitterFcn)(param);
685 // calculate NDF
686 ndf = static_cast<UInt_t>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
687 // calculate expected chisq
688 totalExpectedChisq = 0.0;
689 fFitterFcn->CalcExpectedChiSquare(param, totalExpectedChisq, expectedChisqPerRun);
690 // calculate chisq per run
691 for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
692 chisqPerRun.push_back(fRunListCollection->GetSingleRunChisq(param, i));
693 }
694
695 std::cout << std::endl;
696 std::cout << "++++" << std::endl;
697 std::cout << ">> Sector " << k+1 << ": FitRange: " << secFitRange[0].first << ", " << secFitRange[0].second << std::endl;
698 std::cout << ">> chisq = " << val << ", NDF = " << ndf << ", chisq/NDF = " << val/ndf;
699
700 if (totalExpectedChisq != 0.0) {
701 std::cout << std::endl << ">> expected chisq = " << totalExpectedChisq << ", NDF = " << ndf << ", expected chisq/NDF = " << totalExpectedChisq/ndf;
702 UInt_t ndf_run = 0;
703 for (UInt_t i=0; i<expectedChisqPerRun.size(); i++) {
704 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
705 if (ndf_run > 0)
706 std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.chisq/red.chisq_e) = (" << ndf_run << "/" << chisqPerRun[i]/ndf_run << "/" << expectedChisqPerRun[i]/ndf_run << ")";
707 }
708 } else if (chisqPerRun.size() > 0) { // in case expected chisq is not applicable like for asymmetry fits
709 UInt_t ndf_run = 0;
710 for (UInt_t i=0; i<chisqPerRun.size(); i++) {
711 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
712 if (ndf_run > 0)
713 std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.chisq) = (" << ndf_run << "/" << chisqPerRun[i]/ndf_run << ")";
714 }
715 }
716 // clean up
717 chisqPerRun.clear();
718 expectedChisqPerRun.clear();
719 }
720 }
721 } else { // max. log likelihood
722 // calculate expected maxLH
723 Double_t totalExpectedMaxLH = 0.0;
724 std::vector<Double_t> expectedMaxLHPerRun;
725 fFitterFcn->CalcExpectedChiSquare(param, totalExpectedMaxLH, expectedMaxLHPerRun);
726 // calculate maxLH per run
727 std::vector<Double_t> maxLHPerRun;
728 for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
729 maxLHPerRun.push_back(fRunListCollection->GetSingleRunMaximumLikelihood(param, i));
730 }
731
732 std::cout << std::endl << std::endl << ">> maxLH = " << val << ", NDF = " << ndf << ", maxLH/NDF = " << val/ndf;
733
734 if (totalExpectedMaxLH != 0.0) {
735 std::cout << std::endl << ">> expected maxLH = " << totalExpectedMaxLH << ", NDF = " << ndf << ", expected maxLH/NDF = " << totalExpectedMaxLH/ndf;
736 UInt_t ndf_run = 0;
737 for (UInt_t i=0; i<expectedMaxLHPerRun.size(); i++) {
738 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
739 if (ndf_run > 0)
740 std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.maxLH/red.maxLH_e) = (" << ndf_run << "/" << maxLHPerRun[i]/ndf_run << "/" << expectedMaxLHPerRun[i]/ndf_run << ")";
741 }
742 }
743
744 // clean up
745 maxLHPerRun.clear();
746 expectedMaxLHPerRun.clear();
747
748 if (fSectorFlag) {
749 PDoublePairVector secFitRange;
750 secFitRange.resize(1);
751 for (UInt_t k=0; k<fSector.size(); k++) {
752 // set sector fit range
753 secFitRange[0].first = fSector[k].GetTimeRangeFirst(0);
754 secFitRange[0].second = fSector[k].GetTimeRangeLast();
755 fRunListCollection->SetFitRange(secFitRange);
756 // calculate maxLH
757 val = (*fFitterFcn)(param);
758 // calculate NDF
759 ndf = static_cast<int>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
760 // calculate expected maxLH
761 totalExpectedMaxLH = 0.0;
762 fFitterFcn->CalcExpectedChiSquare(param, totalExpectedMaxLH, expectedMaxLHPerRun);
763 // calculate maxLH per run
764 for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
765 maxLHPerRun.push_back(fRunListCollection->GetSingleRunMaximumLikelihood(param, i));
766 }
767
768 std::cout << std::endl;
769 std::cout << "++++" << std::endl;
770 std::cout << ">> Sector " << k+1 << ": FitRange: " << secFitRange[0].first << ", " << secFitRange[0].second << std::endl;
771 std::cout << ">> maxLH = " << val << ", NDF = " << ndf << ", maxLH/NDF = " << val/ndf;
772
773 if (totalExpectedMaxLH != 0.0) {
774 std::cout << std::endl << ">> expected maxLH = " << totalExpectedMaxLH << ", NDF = " << ndf << ", expected maxLH/NDF = " << totalExpectedMaxLH/ndf;
775 UInt_t ndf_run = 0;
776 for (UInt_t i=0; i<expectedMaxLHPerRun.size(); i++) {
777 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
778 if (ndf_run > 0)
779 std::cout << std::endl << ">> run block " << i+1 << ": (NDF/red.maxLH/red.maxLH_e) = (" << ndf_run << "/" << maxLHPerRun[i]/ndf_run << "/" << expectedMaxLHPerRun[i]/ndf_run << ")";
780 }
781 }
782
783 // clean up
784 maxLHPerRun.clear();
785 expectedMaxLHPerRun.clear();
786 }
787 }
788 }
789 std::cout << std::endl << std::endl;
790 return true;
791 }
792
793 // debugging information
794 #ifdef HAVE_GOMP
795 std::cout << std::endl << ">> Number of available threads for the function optimization: " << omp_get_max_threads() << std::endl;
796 #endif
797
798 // real fit wanted
799 if (fUseChi2)
800 std::cout << std::endl << ">> Chi Square fit will be executed" << std::endl;
801 else
802 std::cout << std::endl << ">> Maximum Likelihood fit will be executed" << std::endl;
803
804 Bool_t status = true;
805 // init positive errors to default false, if minos is called, it will be set true there
806 for (UInt_t i=0; i<fParams.size(); i++) {
807 fRunInfo->SetMsrParamPosErrorPresent(i, false);
808 }
809
810 // walk through the command list and execute them
811 Bool_t firstSave = true;
812 for (UInt_t i=0; i<fCmdList.size(); i++) {
813 switch (fCmdList[i].first) {
814 case PMN_INTERACTIVE:
815 std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command INTERACTIVE is not yet implemented.";
816 std::cerr << std::endl;
817 break;
818 case PMN_CONTOURS:
820 break;
821 case PMN_FIT_RANGE:
822 status = ExecuteFitRange(fCmdList[i].second);
823 break;
824 case PMN_FIX:
825 status = ExecuteFix(fCmdList[i].second);
826 break;
827 case PMN_EIGEN:
828 std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command EIGEN is not yet implemented.";
829 std::cerr << std::endl;
830 break;
831 case PMN_HESSE:
833 break;
835 std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command MACHINE_PRECISION is not yet implemented.";
836 std::cerr << std::endl;
837 break;
838 case PMN_MIGRAD:
840 break;
841 case PMN_MINIMIZE:
843 break;
844 case PMN_MINOS:
846 break;
847 case PMN_PLOT:
849 break;
850 case PMN_RELEASE:
851 status = ExecuteRelease(fCmdList[i].second);
852 break;
853 case PMN_RESTORE:
855 break;
856 case PMN_SAVE:
857 status = ExecuteSave(firstSave);
858 if (firstSave)
859 firstSave = false;
860 break;
861 case PMN_SCAN:
863 break;
864 case PMN_SECTOR:
865 // nothing to be done here
866 break;
867 case PMN_SIMPLEX:
869 break;
871 std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command USER_COVARIANCE is not yet implemented.";
872 std::cerr << std::endl;
873 break;
875 std::cerr << std::endl << "**WARNING** from PFitter::DoFit() : the command USER_PARAM_STATE is not yet implemented.";
876 std::cerr << std::endl;
877 break;
878 case PMN_PRINT:
879 status = ExecutePrintLevel(fCmdList[i].second);
880 break;
881 default:
882 std::cerr << std::endl << "**PANIC ERROR**: PFitter::DoFit(): You should never have reached this point";
883 std::cerr << std::endl;
884 exit(0);
885 }
886
887 // check if command has been successful
888 if (!status)
889 break;
890 }
891
892 if (IsValid()) {
893 fRunInfo->GetMsrStatistic()->fValid = true;
894 } else {
895 fRunInfo->GetMsrStatistic()->fValid = false;
896 }
897
898 return true;
899}
900
901//--------------------------------------------------------------------------
902// CheckCommands
903//--------------------------------------------------------------------------
932{
933 fIsValid = true;
934
935 // check if chisq or log max likelihood fit
936 fUseChi2 = fRunInfo->GetMsrStatistic()->fChisq;
937
938 // walk through the msr-file COMMAND block
939 PIntPair cmd;
940 PMsrLines::iterator it;
941 UInt_t cmdLineNo = 0;
942 TString line;
943 Ssiz_t pos;
944 for (it = fCmdLines.begin(); it != fCmdLines.end(); ++it) {
945 if (it == fCmdLines.begin())
946 cmdLineNo = 0;
947 else
948 cmdLineNo++;
949
950 // strip potential comments
951 line = it->fLine;
952 pos = line.First('#');
953 if (pos > 0) // comment present
954 line.Remove(pos,line.Length()-pos);
955
956 if (line.Contains("COMMANDS", TString::kIgnoreCase)) {
957 continue;
958 } else if (line.Contains("SET BATCH", TString::kIgnoreCase)) { // needed for backward compatibility
959 continue;
960 } else if (line.Contains("END RETURN", TString::kIgnoreCase)) { // needed for backward compatibility
961 continue;
962 } else if (line.Contains("CHI_SQUARE", TString::kIgnoreCase)) {
963 continue;
964 } else if (line.Contains("MAX_LIKELIHOOD", TString::kIgnoreCase)) {
965 continue;
966 } else if (line.Contains("SCALE_N0_BKG", TString::kIgnoreCase)) {
967 continue;
968 } else if (line.Contains("INTERACTIVE", TString::kIgnoreCase)) {
969 cmd.first = PMN_INTERACTIVE;
970 cmd.second = cmdLineNo;
971 fCmdList.push_back(cmd);
972 } else if (line.Contains("CONTOURS", TString::kIgnoreCase)) {
973 cmd.first = PMN_CONTOURS;
974 cmd.second = cmdLineNo;
975 fCmdList.push_back(cmd);
976 // filter out possible parameters for scan
977 std::vector<std::string> tokens;
978 TString str;
979 UInt_t ival;
980
981 tokens = PStringUtils::Split(line.Data(), ", \t");
982
983 for (Int_t i=0; i<static_cast<int>(tokens.size()); i++) {
984 str = tokens[i].c_str();
985
986 if ((i==1) || (i==2)) { // parX / parY
987 // check that token is a UInt_t
988 if (!str.IsDigit()) {
989 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
990 std::cerr << std::endl << ">> " << line.Data();
991 std::cerr << std::endl << ">> parameter number is not number!";
992 std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
993 std::cerr << std::endl;
994 fIsValid = false;
995 break;
996 }
997 ival = str.Atoi();
998 // check that parameter is within range
999 if ((ival < 1) || (ival > fParams.size())) {
1000 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1001 std::cerr << std::endl << ">> " << line.Data();
1002 std::cerr << std::endl << ">> parameter number is out of range [1," << fParams.size() << "]!";
1003 std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
1004 std::cerr << std::endl;
1005 fIsValid = false;
1006 break;
1007 }
1008 // keep parameter
1009 fScanParameter[i-1] = ival-1; // internally parameter number starts at 0
1010 fScanAll = false;
1011 }
1012
1013 if (i==3) {
1014 // check that token is a UInt_t
1015 if (!str.IsDigit()) {
1016 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1017 std::cerr << std::endl << ">> " << line.Data();
1018 std::cerr << std::endl << ">> number of points is not number!";
1019 std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
1020 std::cerr << std::endl;
1021 fIsValid = false;
1022 break;
1023 }
1024 ival = str.Atoi();
1025 if ((ival < 1) || (ival > 100)) {
1026 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1027 std::cerr << std::endl << ">> " << line.Data();
1028 std::cerr << std::endl << ">> number of scan points is out of range [1,100]!";
1029 std::cerr << std::endl << ">> command syntax for CONTOURS is: CONTOURS parameter-X parameter-Y [# of points]";
1030 std::cerr << std::endl;
1031 fIsValid = false;
1032 break;
1033 }
1034 fScanNoPoints = ival;
1035 }
1036 }
1037
1038 } else if (line.Contains("EIGEN", TString::kIgnoreCase)) {
1039 cmd.first = PMN_EIGEN;
1040 cmd.second = cmdLineNo;
1041 fCmdList.push_back(cmd);
1042 } else if (line.Contains("FIT_RANGE", TString::kIgnoreCase)) {
1043 // check the 5 options:
1044 // (i) FIT_RANGE RESET,
1045 // (ii) FIT_RANGE start end,
1046 // (iii) FIT_RANGE start1 end1 start2 end2 ... startN endN
1047 // (iv) FIT_RANGE fgb+n0 lgb-n1
1048 // (v) FIT_RANGE fgb+n00 lgb-n01 fgb+n10 lgb-n11 ... fgb+nN0 lgb-nN1
1049 std::vector<std::string> tokens;
1050 TString str;
1051
1052 tokens = PStringUtils::Split(line.Data(), ", \t");
1053
1054 if (static_cast<int>(tokens.size()) == 2) { // should only be RESET
1055 str = tokens[1].c_str();
1056 if (str.Contains("RESET", TString::kIgnoreCase)) {
1057 cmd.first = PMN_FIT_RANGE;
1058 cmd.second = cmdLineNo;
1059 fCmdList.push_back(cmd);
1060 } else {
1061 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1062 std::cerr << std::endl << ">> " << line.Data();
1063 std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE start end | FIT_RANGE s1 e1 s2 e2 .. sN eN,";
1064 std::cerr << std::endl << ">> with N the number of runs in the msr-file." << std::endl;
1065 std::cerr << std::endl << ">> Found " << str.Data() << ", instead of RESET" << std::endl;
1066 fIsValid = false;
1067 break;
1068 }
1069 } else if ((static_cast<int>(tokens.size()) > 1) && (static_cast<UInt_t>(static_cast<int>(tokens.size())) % 2) == 1) {
1070 if ((static_cast<int>(tokens.size()) > 3) && ((static_cast<UInt_t>(static_cast<int>(tokens.size()))-1)) != 2*fRunInfo->GetMsrRunList()->size()) {
1071 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1072 std::cerr << std::endl << ">> " << line.Data();
1073 std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE <start> <end> | FIT_RANGE <s1> <e1> <s2> <e2> .. <sN> <eN> |";
1074 std::cerr << std::endl << ">> FIT_RANGE fgb+<n0> lgb-<n1> | FIT_RANGE fgb+<n00> lgb-<n01> fgb+<n10> lgb-<n11> ... fgb+<nN0> lgb-<nN1>,";
1075 std::cerr << std::endl << ">> with N the number of runs in the msr-file.";
1076 std::cerr << std::endl << ">> Found N=" << (static_cast<int>(tokens.size())-1)/2 << ", # runs in msr-file=" << fRunInfo->GetMsrRunList()->size() << std::endl;
1077 fIsValid = false;
1078 break;
1079 } else {
1080 // check that all range entries are numbers or fgb+n0 / lgb-n1
1081 Bool_t ok = true;
1082 for (Int_t n=1; n<static_cast<int>(tokens.size()); n++) {
1083 str = tokens[n].c_str();
1084 if (!str.IsFloat()) {
1085 if ((n%2 == 1) && (!str.Contains("fgb", TString::kIgnoreCase)))
1086 ok = false;
1087 if ((n%2 == 0) && (!str.Contains("lgb", TString::kIgnoreCase)))
1088 ok = false;
1089 }
1090 if (!ok)
1091 break;
1092 }
1093
1094 if (ok) { // everything is fine
1095 cmd.first = PMN_FIT_RANGE;
1096 cmd.second = cmdLineNo;
1097 fCmdList.push_back(cmd);
1098 } else {
1099 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1100 std::cerr << std::endl << ">> " << line.Data();
1101 std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE <start> <end> | FIT_RANGE <s1> <e1> <s2> <e2> .. <sN> <eN> |";
1102 std::cerr << std::endl << ">> FIT_RANGE fgb+<n0> lgb-<n1> | FIT_RANGE fgb+<n00> lgb-<n01> fgb+<n10> lgb-<n11> ... fgb+<nN0> lgb-<nN1>,";
1103 std::cerr << std::endl << ">> with N the number of runs in the msr-file.";
1104 std::cerr << std::endl << ">> Found token '" << str.Data() << "', which is not a floating point number." << std::endl;
1105 fIsValid = false;
1106 break;
1107 }
1108 }
1109 } else {
1110 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1111 std::cerr << std::endl << ">> " << line.Data();
1112 std::cerr << std::endl << ">> Syntax: FIT_RANGE RESET | FIT_RANGE <start> <end> | FIT_RANGE <s1> <e1> <s2> <e2> .. <sN> <eN> |";
1113 std::cerr << std::endl << ">> FIT_RANGE fgb+<n0> lgb-<n1> | FIT_RANGE fgb+<n00> lgb-<n01> fgb+<n10> lgb-<n11> ... fgb+<nN0> lgb-<nN1>,";
1114 std::cerr << std::endl << ">> with N the number of runs in the msr-file.";
1115 fIsValid = false;
1116 break;
1117 }
1118
1119 } else if (line.Contains("FIX", TString::kIgnoreCase)) {
1120 // check if the given set of parameters (number or names) is present
1121 std::vector<std::string> tokens;
1122 TString str;
1123 UInt_t ival;
1124
1125 tokens = PStringUtils::Split(line.Data(), ", \t");
1126
1127 for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
1128 str = tokens[i].c_str();
1129
1130 if (str.IsDigit()) { // token might be a parameter number
1131 ival = str.Atoi();
1132 // check that ival is in the parameter list
1133 if (ival > fParams.size()) {
1134 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1135 std::cerr << std::endl << ">> " << line.Data();
1136 std::cerr << std::endl << ">> Parameter " << ival << " is out of the Parameter Range [1," << fParams.size() << "]";
1137 std::cerr << std::endl;
1138 fIsValid = false;
1139 break;
1140 }
1141 } else { // token might be a parameter name
1142 // check if token is present as parameter name
1143 Bool_t found = false;
1144 for (UInt_t j=0; j<fParams.size(); j++) {
1145 if (fParams[j].fName.CompareTo(str, TString::kIgnoreCase) == 0) { // found
1146 found = true;
1147 break;
1148 }
1149 }
1150 if (!found) {
1151 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1152 std::cerr << std::endl << ">> " << line.Data();
1153 std::cerr << std::endl << ">> Parameter '" << str.Data() << "' is NOT present as a parameter name";
1154 std::cerr << std::endl;
1155 fIsValid = false;
1156 break;
1157 }
1158 }
1159 }
1160
1161
1162 // everything looks fine, feed the command list
1163 cmd.first = PMN_FIX;
1164 cmd.second = cmdLineNo;
1165 fCmdList.push_back(cmd);
1166 } else if (line.Contains("HESSE", TString::kIgnoreCase)) {
1167 fIsScanOnly = false;
1168 cmd.first = PMN_HESSE;
1169 cmd.second = cmdLineNo;
1170 fCmdList.push_back(cmd);
1171 } else if (line.Contains("MACHINE_PRECISION", TString::kIgnoreCase)) {
1172 cmd.first = PMN_MACHINE_PRECISION;
1173 cmd.second = cmdLineNo;
1174 fCmdList.push_back(cmd);
1175 } else if (line.Contains("MIGRAD", TString::kIgnoreCase)) {
1176 fIsScanOnly = false;
1177 cmd.first = PMN_MIGRAD;
1178 cmd.second = cmdLineNo;
1179 fCmdList.push_back(cmd);
1180 } else if (line.Contains("MINIMIZE", TString::kIgnoreCase)) {
1181 fIsScanOnly = false;
1182 cmd.first = PMN_MINIMIZE;
1183 cmd.second = cmdLineNo;
1184 fCmdList.push_back(cmd);
1185 } else if (line.Contains("MINOS", TString::kIgnoreCase)) {
1186 fIsScanOnly = false;
1187 cmd.first = PMN_MINOS;
1188 cmd.second = cmdLineNo;
1189 fCmdList.push_back(cmd);
1190 } else if (line.Contains("MNPLOT", TString::kIgnoreCase)) {
1191 cmd.first = PMN_PLOT;
1192 cmd.second = cmdLineNo;
1193 fCmdList.push_back(cmd);
1194 } else if (line.Contains("PRINT_LEVEL", TString::kIgnoreCase)) {
1195 cmd.first = PMN_PRINT;
1196 cmd.second = cmdLineNo;
1197 fCmdList.push_back(cmd);
1198 } else if (line.Contains("RELEASE", TString::kIgnoreCase)) {
1199 // check if the given set of parameters (number or names) is present
1200 std::vector<std::string> tokens;
1201 TString str;
1202 UInt_t ival;
1203
1204 tokens = PStringUtils::Split(line.Data(), ", \t");
1205
1206 for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
1207 str = tokens[i].c_str();
1208
1209 if (str.IsDigit()) { // token might be a parameter number
1210 ival = str.Atoi();
1211 // check that ival is in the parameter list
1212 if (ival > fParams.size()) {
1213 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1214 std::cerr << std::endl << ">> " << line.Data();
1215 std::cerr << std::endl << ">> Parameter " << ival << " is out of the Parameter Range [1," << fParams.size() << "]";
1216 std::cerr << std::endl;
1217 fIsValid = false;
1218 break;
1219 }
1220 } else { // token might be a parameter name
1221 // check if token is present as parameter name
1222 Bool_t found = false;
1223 for (UInt_t j=0; j<fParams.size(); j++) {
1224 if (fParams[j].fName.CompareTo(str, TString::kIgnoreCase) == 0) { // found
1225 found = true;
1226 break;
1227 }
1228 }
1229 if (!found) {
1230 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1231 std::cerr << std::endl << ">> " << line.Data();
1232 std::cerr << std::endl << ">> Parameter '" << str.Data() << "' is NOT present as a parameter name";
1233 std::cerr << std::endl;
1234 fIsValid = false;
1235 break;
1236 }
1237 }
1238 }
1239
1240 cmd.first = PMN_RELEASE;
1241 cmd.second = cmdLineNo;
1242 fCmdList.push_back(cmd);
1243 } else if (line.Contains("RESTORE", TString::kIgnoreCase)) {
1244 cmd.first = PMN_RESTORE;
1245 cmd.second = cmdLineNo;
1246 fCmdList.push_back(cmd);
1247 } else if (line.Contains("SAVE", TString::kIgnoreCase)) {
1248 cmd.first = PMN_SAVE;
1249 cmd.second = cmdLineNo;
1250 fCmdList.push_back(cmd);
1251 } else if (line.Contains("SCAN", TString::kIgnoreCase)) {
1252 cmd.first = PMN_SCAN;
1253 cmd.second = cmdLineNo;
1254 fCmdList.push_back(cmd);
1255 // filter out possible parameters for scan
1256 std::vector<std::string> tokens;
1257 TString str;
1258 UInt_t ival;
1259
1260 tokens = PStringUtils::Split(line.Data(), ", \t");
1261
1262 for (Int_t i=0; i<static_cast<int>(tokens.size()); i++) {
1263 str = tokens[i].c_str();
1264 if (i==1) { // get parameter number
1265 // check that token is a UInt_t
1266 if (!str.IsDigit()) {
1267 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1268 std::cerr << std::endl << ">> " << line.Data();
1269 std::cerr << std::endl << ">> parameter number is not number!";
1270 std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1271 std::cerr << std::endl;
1272 fIsValid = false;
1273 break;
1274 }
1275 ival = str.Atoi();
1276 // check that parameter is within range
1277 if ((ival < 1) || (ival > fParams.size())) {
1278 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1279 std::cerr << std::endl << ">> " << line.Data();
1280 std::cerr << std::endl << ">> parameter number is out of range [1," << fParams.size() << "]!";
1281 std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1282 std::cerr << std::endl;
1283 fIsValid = false;
1284 break;
1285 }
1286 // keep parameter
1287 fScanParameter[0] = ival-1; // internally parameter number starts at 0
1288 fScanAll = false;
1289 }
1290
1291 if (i==2) { // get number of points
1292 // check that token is a UInt_t
1293 if (!str.IsDigit()) {
1294 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1295 std::cerr << std::endl << ">> " << line.Data();
1296 std::cerr << std::endl << ">> number of points is not number!";
1297 std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1298 std::cerr << std::endl;
1299 fIsValid = false;
1300 break;
1301 }
1302 ival = str.Atoi();
1303 if ((ival < 1) || (ival > 100)) {
1304 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1305 std::cerr << std::endl << ">> " << line.Data();
1306 std::cerr << std::endl << ">> number of scan points is out of range [1,100]!";
1307 std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1308 std::cerr << std::endl;
1309 fIsValid = false;
1310 break;
1311 }
1312 fScanNoPoints = ival;
1313 }
1314
1315 if (i==3) { // get low
1316 // check that token is a Double_t
1317 if (!str.IsFloat()) {
1318 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1319 std::cerr << std::endl << ">> " << line.Data();
1320 std::cerr << std::endl << ">> low is not a floating point number!";
1321 std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1322 std::cerr << std::endl;
1323 fIsValid = false;
1324 break;
1325 }
1326 fScanLow = str.Atof();
1327 }
1328
1329 if (i==4) { // get high
1330 // check that token is a Double_t
1331 if (!str.IsFloat()) {
1332 std::cerr << std::endl << ">> PFitter::CheckCommands: **ERROR** in line " << it->fLineNo;
1333 std::cerr << std::endl << ">> " << line.Data();
1334 std::cerr << std::endl << ">> high is not a floating point number!";
1335 std::cerr << std::endl << ">> command syntax for SCAN is: SCAN [parameter no [# of points [low high]]]";
1336 std::cerr << std::endl;
1337 fIsValid = false;
1338 break;
1339 }
1340 fScanHigh = str.Atof();
1341 }
1342 }
1343
1344 } else if (line.Contains("SIMPLEX", TString::kIgnoreCase)) {
1345 cmd.first = PMN_SIMPLEX;
1346 cmd.second = cmdLineNo;
1347 fCmdList.push_back(cmd);
1348 } else if (line.Contains("STRATEGY", TString::kIgnoreCase)) {
1349 std::vector<std::string> tokens;
1350 TString str;
1351
1352 tokens = PStringUtils::Split(line.Data(), " \t");
1353 if (static_cast<int>(tokens.size()) == 2) {
1354 str = tokens[1].c_str();
1355 if (str.CompareTo("0") == 0) { // low
1356 fStrategy = 0;
1357 } else if (str.CompareTo("1") == 0) { // default
1358 fStrategy = 1;
1359 } else if (str.CompareTo("2") == 0) { // high
1360 fStrategy = 2;
1361 } else if (str.CompareTo("LOW") == 0) { // low
1362 fStrategy = 0;
1363 } else if (str.CompareTo("DEFAULT") == 0) { // default
1364 fStrategy = 1;
1365 } else if (str.CompareTo("HIGH") == 0) { // high
1366 fStrategy = 2;
1367 }
1368 }
1369
1370 } else if (line.Contains("USER_COVARIANCE", TString::kIgnoreCase)) {
1371 cmd.first = PMN_USER_COVARIANCE;
1372 cmd.second = cmdLineNo;
1373 fCmdList.push_back(cmd);
1374 } else if (line.Contains("USER_PARAM_STATE", TString::kIgnoreCase)) {
1375 cmd.first = PMN_USER_PARAM_STATE;
1376 cmd.second = cmdLineNo;
1377 fCmdList.push_back(cmd);
1378 } else if (line.Contains("SECTOR", TString::kIgnoreCase)) {
1379 fSectorFlag = true;
1380 cmd.first = PMN_SECTOR;
1381 cmd.second = cmdLineNo;
1382 fCmdList.push_back(cmd);
1383
1384 // check if the given sector arguments are valid time stamps, i.e. doubles and value < lgb time stamp
1385 std::vector<std::string> tokens;
1386 TString str;
1387
1388 tokens = PStringUtils::Split(line.Data(), " ,\t");
1389
1390 if (static_cast<int>(tokens.size()) == 1) { // no sector time stamps given -> issue an error
1391 std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo;
1392 std::cerr << std::endl << ">> " << line.Data();
1393 std::cerr << std::endl << ">> At least one sector time stamp is expected.";
1394 std::cerr << std::endl << ">> Will stop ...";
1395 std::cerr << std::endl;
1396 fIsValid = false;
1397 fSectorFlag = false;
1398 break;
1399 }
1400
1401 Double_t dval;
1402 for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
1403 // keep time range of sector
1404 PSectorChisq sec(fRunInfo->GetNoOfRuns());
1405 // get parse tokens
1406 str = tokens[i].c_str();
1407 if (str.IsFloat()) {
1408 dval = str.Atof();
1409 // check that the sector time stamp is smaller than all lgb time stamps
1410 for (UInt_t j=0; j<fOriginalFitRange.size(); j++) {
1411 if (dval > fOriginalFitRange[j].second) {
1412 std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo;
1413 std::cerr << std::endl << ">> " << line.Data();
1414 std::cerr << std::endl << ">> The sector time stamp " << dval << " is > as the lgb time stamp (" << fOriginalFitRange[j].second << ") of run " << j << ".";
1415 std::cerr << std::endl << ">> Will stop ...";
1416 std::cerr << std::endl;
1417 fIsValid = false;
1418 fSectorFlag = false;
1419 return fIsValid;
1420 }
1421 sec.SetRunFirstTime(fOriginalFitRange[j].first, j); // keep fgb time stamp for sector
1422 }
1423 sec.SetSectorTime(dval);
1424 fSector.push_back(sec);
1425 } else { // sector element is NOT a float
1426 std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo;
1427 std::cerr << std::endl << ">> " << line.Data();
1428 std::cerr << std::endl << ">> The sector time stamp '" << str << "' is not a number.";
1429 std::cerr << std::endl << ">> Will stop ...";
1430 std::cerr << std::endl;
1431 fIsValid = false;
1432 fSectorFlag = false;
1433 break;
1434 }
1435 }
1436
1437 } else { // unkown command
1438 std::cerr << std::endl << ">> PFitter::CheckCommands(): **FATAL ERROR** in line " << it->fLineNo << " an unkown command is found:";
1439 std::cerr << std::endl << ">> " << line.Data();
1440 std::cerr << std::endl << ">> Will stop ...";
1441 std::cerr << std::endl;
1442 fIsValid = false;
1443 break;
1444 }
1445 }
1446
1447 // Check that in case release/restore is present, that it is followed by a minimizer before minos is called.
1448 // If this is not the case, place a warning
1449 Bool_t fixFlag = false;
1450 Bool_t releaseFlag = false;
1451 Bool_t minimizerFlag = false;
1452 for (it = fCmdLines.begin(); it != fCmdLines.end(); ++it) {
1453 if (line.Contains("FIX", TString::kIgnoreCase))
1454 fixFlag = true;
1455 else if (line.Contains("RELEASE", TString::kIgnoreCase) ||
1456 line.Contains("RESTORE", TString::kIgnoreCase))
1457 releaseFlag = true;
1458 else if (line.Contains("MINIMIZE", TString::kIgnoreCase) ||
1459 line.Contains("MIGRAD", TString::kIgnoreCase) ||
1460 line.Contains("SIMPLEX", TString::kIgnoreCase)) {
1461 if (releaseFlag)
1462 minimizerFlag = true;
1463 } else if (line.Contains("MINOS", TString::kIgnoreCase)) {
1464 if (fixFlag && releaseFlag && !minimizerFlag) {
1465 std::cerr << std::endl << ">> PFitter::CheckCommands(): **WARNING** RELEASE/RESTORE command present";
1466 std::cerr << std::endl << ">> without minimizer command (MINIMIZE/MIGRAD/SIMPLEX) between";
1467 std::cerr << std::endl << ">> RELEASE/RESTORE and MINOS. Behaviour might be different to the";
1468 std::cerr << std::endl << ">> expectation of the user ?!?" << std::endl;
1469 }
1470 fixFlag = false;
1471 releaseFlag = false;
1472 minimizerFlag = false;
1473 }
1474 }
1475
1476 return fIsValid;
1477}
1478
1479//--------------------------------------------------------------------------
1480// SetParameters
1481//--------------------------------------------------------------------------
1489{
1490 for (UInt_t i=0; i<fParams.size(); i++) {
1491 // check if parameter is fixed
1492 if (fParams[i].fStep == 0.0) { // add fixed parameter
1493 fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue);
1494 } else { // add free parameter
1495 // check if boundaries are given
1496 if (fParams[i].fNoOfParams > 5) { // boundaries given
1497 if (fParams[i].fLowerBoundaryPresent &&
1498 fParams[i].fUpperBoundaryPresent) { // upper and lower boundaries given
1499 fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue, fParams[i].fStep,
1500 fParams[i].fLowerBoundary, fParams[i].fUpperBoundary);
1501 } else if (fParams[i].fLowerBoundaryPresent &&
1502 !fParams[i].fUpperBoundaryPresent) { // lower boundary limited
1503 fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue, fParams[i].fStep);
1504 fMnUserParams.SetLowerLimit(fParams[i].fName.Data(), fParams[i].fLowerBoundary);
1505 } else { // upper boundary limited
1506 fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue, fParams[i].fStep);
1507 fMnUserParams.SetUpperLimit(fParams[i].fName.Data(), fParams[i].fUpperBoundary);
1508 }
1509 } else { // no boundaries given
1510 fMnUserParams.Add(fParams[i].fName.Data(), fParams[i].fValue, fParams[i].fStep);
1511 }
1512 }
1513 }
1514
1515 // check if there is an unused parameter, if so, fix it
1516 for (UInt_t i=0; i<fParams.size(); i++) {
1517 // parameter not used in the whole theory and not already fixed!!
1518 if ((fRunInfo->ParameterInUse(i) == 0) && (fParams[i].fStep != 0.0)) {
1519 fMnUserParams.Fix(i); // fix the unused parameter so that minuit will not vary it
1520 std::cerr << std::endl << "**WARNING** : Parameter No " << i+1 << " is not used at all, will fix it";
1521 std::cerr << std::endl;
1522 }
1523 }
1524
1525 return true;
1526}
1527
1528//--------------------------------------------------------------------------
1529// ExecuteContours
1530//--------------------------------------------------------------------------
1537{
1538 std::cout << ">> PFitter::ExecuteContours() ..." << std::endl;
1539
1540 // if already some minimization is done use the minuit2 output as input
1541 if (!fFcnMin) {
1542 std::cerr << std::endl << "**WARNING**: CONTOURS musn't be called before any minimization (MINIMIZE/MIGRAD/SIMPLEX) is done!!";
1543 std::cerr << std::endl;
1544 return false;
1545 }
1546
1547 // check if minimum was valid
1548 if (!fFcnMin->IsValid()) {
1549 std::cerr << std::endl << "**ERROR**: CONTOURS cannot started since the previous minimization failed :-(";
1550 std::cerr << std::endl;
1551 return false;
1552 }
1553
1554 ROOT::Minuit2::MnContours contours((*fFitterFcn), *fFcnMin);
1555
1557
1558 return true;
1559}
1560
1561//--------------------------------------------------------------------------
1562// ExecuteFitRange
1563//--------------------------------------------------------------------------
1571Bool_t PFitter::ExecuteFitRange(UInt_t lineNo)
1572{
1573 std::cout << ">> PFitter::ExecuteFitRange(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
1574
1575 if (fCmdLines[lineNo].fLine.Contains("fgb", TString::kIgnoreCase)) { // fit range given in bins
1576 fRunListCollection->SetFitRange(fCmdLines[lineNo].fLine);
1577 return true;
1578 }
1579
1580 std::vector<std::string> tokens;
1581 TString str;
1582
1583 tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t");
1584
1585 PMsrRunList *runList = fRunInfo->GetMsrRunList();
1586
1587 // execute command, no error checking needed since this has been already carried out in CheckCommands()
1588 if (static_cast<int>(tokens.size()) == 2) { // reset command
1590 } else if (static_cast<int>(tokens.size()) == 3) { // single fit range for all runs
1591 Double_t start = 0.0, end = 0.0;
1592 PDoublePair fitRange;
1593 PDoublePairVector fitRangeVector;
1594
1595 str = tokens[1].c_str();
1596 start = str.Atof();
1597 str = tokens[2].c_str();
1598 end = str.Atof();
1599
1600 fitRange.first = start;
1601 fitRange.second = end;
1602 fitRangeVector.push_back(fitRange);
1603 fRunListCollection->SetFitRange(fitRangeVector);
1604
1605 } else { // individual fit ranges for each run
1606 Double_t start = 0.0, end = 0.0;
1607 PDoublePair fitRange;
1608 PDoublePairVector fitRangeVector;
1609
1610 for (UInt_t i=0; i<runList->size(); i++) {
1611 str = tokens[2*i+1].c_str();
1612 start = str.Atof();
1613 str = tokens[2*i+2].c_str();
1614 end = str.Atof();
1615
1616 fitRange.first = start;
1617 fitRange.second = end;
1618 fitRangeVector.push_back(fitRange);
1619 }
1620
1621 fRunListCollection->SetFitRange(fitRangeVector);
1622 }
1623
1624 return true;
1625}
1626
1627//--------------------------------------------------------------------------
1628// ExecuteFix
1629//--------------------------------------------------------------------------
1637Bool_t PFitter::ExecuteFix(UInt_t lineNo)
1638{
1639 std::cout << ">> PFitter::ExecuteFix(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
1640
1641 std::vector<std::string> tokens;
1642 TString str;
1643
1644 tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t");
1645
1646 for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
1647 str = tokens[i].c_str();
1648
1649 if (str.IsDigit()) { // token is a parameter number
1650 fMnUserParams.Fix(static_cast<UInt_t>(str.Atoi())-1);
1651 } else { // token is a parameter name
1652 fMnUserParams.Fix(str.Data());
1653 }
1654 }
1655
1656
1657 return true;
1658}
1659
1660//--------------------------------------------------------------------------
1661// ExecuteHesse
1662//--------------------------------------------------------------------------
1669{
1670 std::cout << ">> PFitter::ExecuteHesse(): will call hesse ..." << std::endl;
1671
1672 // create the hesse object
1673 ROOT::Minuit2::MnHesse hesse;
1674
1675 // specify maximal number of function calls
1676 UInt_t maxfcn = std::numeric_limits<UInt_t>::max();
1677
1678 // call hesse
1679 Double_t start=0.0, end=0.0;
1680 start=MilliTime();
1681 ROOT::Minuit2::MnUserParameterState mnState = hesse((*fFitterFcn), fMnUserParams, maxfcn);
1682 end=MilliTime();
1683 std::cout << ">> PFitter::ExecuteMinimize(): execution time for Hesse = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
1684 TString str = TString::Format("Hesse: %.3f sec", (end-start)/1.0e3);
1685 fElapsedTime.push_back(str);
1686 if (!mnState.IsValid()) {
1687 std::cerr << std::endl << ">> PFitter::ExecuteHesse(): **WARNING** Hesse encountered a problem! The state found is invalid.";
1688 std::cerr << std::endl;
1689 return false;
1690 }
1691 if (!mnState.HasCovariance()) {
1692 std::cerr << std::endl << ">> PFitter::ExecuteHesse(): **WARNING** Hesse encountered a problem! No covariance matrix available.";
1693 std::cerr << std::endl;
1694 return false;
1695 }
1696
1697 // fill parabolic errors
1698 for (UInt_t i=0; i<fParams.size(); i++) {
1699 fRunInfo->SetMsrParamStep(i, mnState.Error(i));
1700 fRunInfo->SetMsrParamPosErrorPresent(i, false);
1701 }
1702
1703 if (fPrintLevel >= 2)
1704 std::cout << mnState << std::endl;
1705
1706 return true;
1707}
1708
1709//--------------------------------------------------------------------------
1710// ExecuteMigrad
1711//--------------------------------------------------------------------------
1718{
1719 std::cout << ">> PFitter::ExecuteMigrad(): will call migrad ..." << std::endl;
1720
1721 // create migrad object
1722 // strategy is by default = 'default'
1723 ROOT::Minuit2::MnMigrad migrad((*fFitterFcn), fMnUserParams, ROOT::Minuit2::MnStrategy{fStrategy});
1724
1725 // minimize
1726 // maxfcn is MINUIT2 Default maxfcn
1727 UInt_t maxfcn = std::numeric_limits<UInt_t>::max();
1728 // tolerance = MINUIT2 Default tolerance
1729 Double_t tolerance = 0.1;
1730 // keep track of elapsed time
1731 Double_t start=0.0, end=0.0;
1732 start=MilliTime();
1733 ROOT::Minuit2::FunctionMinimum min = migrad(maxfcn, tolerance);
1734 end=MilliTime();
1735 std::cout << ">> PFitter::ExecuteMinimize(): execution time for Migrad = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
1736 TString str = TString::Format("Migrad: %.3f sec", (end-start)/1.0e3);
1737 fElapsedTime.push_back(str);
1738 if (!min.IsValid()) {
1739 std::cerr << std::endl << ">> PFitter::ExecuteMigrad(): **WARNING**: Fit did not converge, sorry ...";
1740 std::cerr << std::endl;
1741 fIsValid = false;
1742 return false;
1743 }
1744
1745 // keep FunctionMinimum object
1746 fFcnMin.reset(new ROOT::Minuit2::FunctionMinimum(min));
1747
1748 // keep user parameters
1749 if (fFcnMin)
1750 fMnUserParams = fFcnMin->UserParameters();
1751
1752 // fill run info
1753 for (UInt_t i=0; i<fParams.size(); i++) {
1754 Double_t dval = min.UserState().Value(i);
1755 if (fPhase[i]) {
1756 Int_t m = (Int_t)(dval/360.0);
1757 dval = dval - m*360.0;
1758 }
1759 fRunInfo->SetMsrParamValue(i, dval);
1760 fRunInfo->SetMsrParamStep(i, min.UserState().Error(i));
1761 fRunInfo->SetMsrParamPosErrorPresent(i, false);
1762 }
1763
1764 // handle statistics
1765 Double_t minVal = min.Fval();
1766 UInt_t ndf = fFitterFcn->GetTotalNoOfFittedBins();
1767 // subtract number of varied parameters from total no of fitted bins -> ndf
1768 for (UInt_t i=0; i<fParams.size(); i++) {
1769 if ((min.UserState().Error(i) != 0.0) && !fMnUserParams.Parameters().at(i).IsFixed())
1770 ndf -= 1;
1771 }
1772
1773 // feed run info with new statistics info
1774 fRunInfo->SetMsrStatisticMin(minVal);
1775 fRunInfo->SetMsrStatisticNdf(ndf);
1776
1777 fConverged = true;
1778
1779 if (fPrintLevel >= 2)
1780 std::cout << *fFcnMin << std::endl;
1781
1782 return true;
1783}
1784
1785//--------------------------------------------------------------------------
1786// ExecuteMinimize
1787//--------------------------------------------------------------------------
1794{
1795 std::cout << ">> PFitter::ExecuteMinimize(): will call minimize ..." << std::endl;
1796
1797 // create minimizer object
1798 // strategy is by default = 'default'
1799 ROOT::Minuit2::MnMinimize minimize((*fFitterFcn), fMnUserParams, ROOT::Minuit2::MnStrategy{fStrategy});
1800
1801 // minimize
1802 // maxfcn is MINUIT2 Default maxfcn
1803 UInt_t maxfcn = std::numeric_limits<UInt_t>::max();
1804
1805 // tolerance = MINUIT2 Default tolerance
1806 Double_t tolerance = 0.1;
1807 // keep track of elapsed time
1808 Double_t start=0.0, end=0.0;
1809 start = MilliTime();
1810 ROOT::Minuit2::FunctionMinimum min = minimize(maxfcn, tolerance);
1811 end = MilliTime();
1812 std::cout << ">> PFitter::ExecuteMinimize(): execution time for Minimize = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
1813 TString str = TString::Format("Minimize: %.3f sec", (end-start)/1.0e3);
1814 fElapsedTime.push_back(str);
1815 if (!min.IsValid()) {
1816 std::cerr << std::endl << ">> PFitter::ExecuteMinimize(): **WARNING**: Fit did not converge, sorry ...";
1817 std::cerr << std::endl;
1818 fIsValid = false;
1819 return false;
1820 }
1821
1822 // keep FunctionMinimum object
1823 fFcnMin.reset(new ROOT::Minuit2::FunctionMinimum(min));
1824
1825 // keep user parameters
1826 if (fFcnMin)
1827 fMnUserParams = fFcnMin->UserParameters();
1828
1829 // fill run info
1830 for (UInt_t i=0; i<fParams.size(); i++) {
1831 Double_t dval = min.UserState().Value(i);
1832 if (fPhase[i]) {
1833 Int_t m = (Int_t)(dval/360.0);
1834 dval = dval - m*360.0;
1835 }
1836 fRunInfo->SetMsrParamValue(i, dval);
1837 fRunInfo->SetMsrParamStep(i, min.UserState().Error(i));
1838 fRunInfo->SetMsrParamPosErrorPresent(i, false);
1839 }
1840
1841 // handle statistics
1842 Double_t minVal = min.Fval();
1843 UInt_t ndf = fFitterFcn->GetTotalNoOfFittedBins();
1844 // subtract number of varied parameters from total no of fitted bins -> ndf
1845 for (UInt_t i=0; i<fParams.size(); i++) {
1846 if ((min.UserState().Error(i) != 0.0) && !fMnUserParams.Parameters().at(i).IsFixed())
1847 ndf -= 1;
1848 }
1849
1850 // feed run info with new statistics info
1851 fRunInfo->SetMsrStatisticMin(minVal);
1852 fRunInfo->SetMsrStatisticNdf(ndf);
1853
1854 fConverged = true;
1855
1856 if (fPrintLevel >= 2)
1857 std::cout << *fFcnMin << std::endl;
1858
1859 return true;
1860}
1861
1862//--------------------------------------------------------------------------
1863// ExecuteMinos
1864//--------------------------------------------------------------------------
1871{
1872 std::cout << ">> PFitter::ExecuteMinos(): will call minos ..." << std::endl;
1873
1874 // if already some minimization is done use the minuit2 output as input
1875 if (!fFcnMin) {
1876 std::cerr << std::endl << "**ERROR**: MINOS musn't be called before any minimization (MINIMIZE/MIGRAD/SIMPLEX) is done!!";
1877 std::cerr << std::endl;
1878 return false;
1879 }
1880
1881 // check if minimum was valid
1882 if (!fFcnMin->IsValid()) {
1883 std::cerr << std::endl << "**ERROR**: MINOS cannot started since the previous minimization failed :-(";
1884 std::cerr << std::endl;
1885 return false;
1886 }
1887
1888 // make minos analysis
1889 Double_t start=0.0, end=0.0;
1890 start=MilliTime();
1891 ROOT::Minuit2::MnMinos minos((*fFitterFcn), (*fFcnMin));
1892
1893 for (UInt_t i=0; i<fParams.size(); i++) {
1894 // only try to call minos if the parameter is not fixed!!
1895 // the 1st condition is from an user fixed variable,
1896 // the 2nd condition is from an all together unused variable
1897 // the 3rd condition is a variable fixed via the FIX command
1898 if ((fMnUserParams.Error(i) != 0.0) && (fRunInfo->ParameterInUse(i) != 0) && (!fMnUserParams.Parameters().at(i).IsFixed())) {
1899 std::cout << ">> PFitter::ExecuteMinos(): calculate errors for " << fParams[i].fName << std::endl;
1900
1901 // 1-sigma MINOS errors
1902 ROOT::Minuit2::MinosError err = minos.Minos(i);
1903
1904 if (err.IsValid()) {
1905 // fill msr-file structure
1906 fRunInfo->SetMsrParamStep(i, err.Lower());
1907 fRunInfo->SetMsrParamPosError(i, err.Upper());
1908 fRunInfo->SetMsrParamPosErrorPresent(i, true);
1909 } else {
1910 fRunInfo->SetMsrParamPosErrorPresent(i, false);
1911 }
1912 }
1913
1914 if (fMnUserParams.Parameters().at(i).IsFixed()) {
1915 std::cerr << std::endl << ">> PFitter::ExecuteMinos(): **WARNING** Parameter " << fMnUserParams.Name(i) << " (ParamNo " << i+1 << ") is fixed!";
1916 std::cerr << std::endl << ">> Will set STEP to zero, i.e. making it a constant parameter";
1917 std::cerr << std::endl;
1918 fRunInfo->SetMsrParamStep(i, 0.0);
1919 fRunInfo->SetMsrParamPosErrorPresent(i, false);
1920 }
1921 }
1922
1923 end=MilliTime();
1924 std::cout << ">> PFitter::ExecuteMinimize(): execution time for Minos = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
1925 TString str = TString::Format("Minos: %.3f sec", (end-start)/1.0e3);
1926 fElapsedTime.push_back(str);
1927
1928 return true;
1929}
1930
1931//--------------------------------------------------------------------------
1932// ExecutePlot
1933//--------------------------------------------------------------------------
1940{
1941 std::cout << ">> PFitter::ExecutePlot() ..." << std::endl;
1942
1943 ROOT::Minuit2::MnPlot plot;
1944 plot(fScanData);
1945
1946 return true;
1947}
1948
1949//--------------------------------------------------------------------------
1950// ExecutePrintLevel
1951//--------------------------------------------------------------------------
1959Bool_t PFitter::ExecutePrintLevel(UInt_t lineNo)
1960{
1961 std::cout << ">> PFitter::ExecutePrintLevel(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
1962
1963 std::vector<std::string> tokens;
1964 TString str;
1965
1966 tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t");
1967
1968 if (static_cast<int>(tokens.size()) < 2) {
1969 std::cerr << std::endl << "**ERROR** from PFitter::ExecutePrintLevel(): SYNTAX: PRINT_LEVEL <N>, where <N>=0-3" << std::endl << std::endl;
1970 return false;
1971 }
1972
1973 str = tokens[1].c_str();
1974
1975 Int_t ival;
1976 if (str.IsDigit()) {
1977 ival = str.Atoi();
1978 if ((ival >=0) && (ival <= 3)) {
1979 fPrintLevel = (UInt_t) ival;
1980 } else {
1981 std::cerr << std::endl << "**ERROR** from PFitter::ExecutePrintLevel(): SYNTAX: PRINT_LEVEL <N>, where <N>=0-3";
1982 std::cerr << std::endl << " found <N>=" << ival << std::endl << std::endl;
1983 return false;
1984 }
1985 } else {
1986 std::cerr << std::endl << "**ERROR** from PFitter::ExecutePrintLevel(): SYNTAX: PRINT_LEVEL <N>, where <N>=0-3" << std::endl << std::endl;
1987 return false;
1988 }
1989
1990#ifdef ROOT_GRTEQ_24
1991 ROOT::Minuit2::MnPrint::SetGlobalLevel(fPrintLevel);
1992#else
1993 ROOT::Minuit2::MnPrint::SetLevel(fPrintLevel);
1994#endif
1995
1996
1997 return true;
1998}
1999
2000//--------------------------------------------------------------------------
2001// ExecuteRelease
2002//--------------------------------------------------------------------------
2010Bool_t PFitter::ExecuteRelease(UInt_t lineNo)
2011{
2012 std::vector<std::string> tokens;
2013 TString str;
2014
2015 tokens = PStringUtils::Split(fCmdLines[lineNo].fLine.Data(), ", \t");
2016
2017 std::cout << ">> PFitter::ExecuteRelease(): " << fCmdLines[lineNo].fLine.Data() << std::endl;
2018
2019 for (Int_t i=1; i<static_cast<int>(tokens.size()); i++) {
2020 str = tokens[i].c_str();
2021
2022 if (str.IsDigit()) { // token is a parameter number
2023 fMnUserParams.Release(static_cast<UInt_t>(str.Atoi())-1);
2024 // set the error to 2% of the value when releasing
2025 fMnUserParams.SetError(static_cast<UInt_t>(str.Atoi())-1, 0.02*fMnUserParams.Value(static_cast<UInt_t>(str.Atoi())-1));
2026 } else { // token is a parameter name
2027 fMnUserParams.Release(str.Data());
2028 // set the error to 2% of the value when releasing
2029 fMnUserParams.SetError(str.Data(), 0.02*fMnUserParams.Value(str.Data()));
2030 }
2031 }
2032
2033
2034 return true;
2035}
2036
2037//--------------------------------------------------------------------------
2038// ExecuteRestore
2039//--------------------------------------------------------------------------
2046{
2047 std::cout << "PFitter::ExecuteRestore(): release all fixed parameters (RESTORE) ..." << std::endl;
2048
2049 for (UInt_t i=0; i<fMnUserParams.Parameters().size(); i++) {
2050 if (fMnUserParams.Parameters().at(i).IsFixed()) {
2051 fMnUserParams.Release(i);
2052 fMnUserParams.SetError(i, 0.02*fMnUserParams.Value(i));
2053 }
2054 }
2055
2056 return true;
2057}
2058
2059//--------------------------------------------------------------------------
2060// ExecuteScan
2061//--------------------------------------------------------------------------
2068{
2069 std::cout << ">> PFitter::ExecuteScan(): will call scan ..." << std::endl;
2070
2071 ROOT::Minuit2::MnScan scan((*fFitterFcn), fMnUserParams);
2072
2073 if (fScanAll) { // not clear at the moment what to be done here
2074 // TO BE IMPLEMENTED
2075 } else { // single parameter scan
2077 }
2078
2079 fConverged = true;
2080
2081 return true;
2082}
2083
2084//--------------------------------------------------------------------------
2085// ExecuteSave
2086//--------------------------------------------------------------------------
2094Bool_t PFitter::ExecuteSave(Bool_t firstSave)
2095{
2096 // if any minimization was done, otherwise get out immediately
2097 if (!fFcnMin) {
2098 std::cout << std::endl << ">> PFitter::ExecuteSave(): nothing to be saved ...";
2099 return false;
2100 }
2101
2102 ROOT::Minuit2::MnUserParameterState mnState = fFcnMin->UserState();
2103
2104 // check if the user parameter state is valid
2105 if (!mnState.IsValid()) {
2106 std::cerr << std::endl << ">> PFitter::ExecuteSave: **WARNING** Minuit2 User Parameter State is not valid, i.e. nothing to be saved";
2107 std::cerr << std::endl;
2108 return false;
2109 }
2110
2111 // handle expected chisq if applicable
2112 fParams = *(fRunInfo->GetMsrParamList()); // get the update parameters back
2113
2114 // calculate expected chisq
2115 std::vector<Double_t> param;
2116 std::vector<Double_t> err;
2117 Double_t totalExpectedChisq = 0.0;
2118 std::vector<Double_t> expectedchisqPerRun;
2119 std::vector<UInt_t> ndfPerHisto;
2120
2121 for (UInt_t i=0; i<fParams.size(); i++) {
2122 param.push_back(fParams[i].fValue);
2123 err.push_back(fParams[i].fStep);
2124 }
2125
2126 // CalcExpectedChiSquare handles both, chisq and mlh
2127 Bool_t ok;
2128 PDoubleVector par_r = ParamRound(param, err, ok);
2129 if (!ok)
2130 par_r = param;
2131 fFitterFcn->CalcExpectedChiSquare(par_r, totalExpectedChisq, expectedchisqPerRun);
2132
2133 // calculate chisq per run
2134 std::vector<Double_t> chisqPerRun;
2135 for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
2136 if (fUseChi2)
2137 chisqPerRun.push_back(fRunListCollection->GetSingleRunChisq(par_r, i));
2138 else
2139 chisqPerRun.push_back(fRunListCollection->GetSingleRunMaximumLikelihood(par_r, i));
2140 }
2141
2142 if (totalExpectedChisq != 0.0) { // i.e. applicable for single histogram fits only
2143 // get the ndf's of the histos
2144 UInt_t ndf_run;
2145 for (UInt_t i=0; i<expectedchisqPerRun.size(); i++) {
2146 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2147 ndfPerHisto.push_back(ndf_run);
2148 }
2149
2150 // feed the msr-file handler
2151 PMsrStatisticStructure *statistics = fRunInfo->GetMsrStatistic();
2152 if (statistics) {
2153 statistics->fMinPerHisto = chisqPerRun;
2154 statistics->fMinExpected = totalExpectedChisq;
2155 statistics->fMinExpectedPerHisto = expectedchisqPerRun;
2156 statistics->fNdfPerHisto = ndfPerHisto;
2157 }
2158 } else if (chisqPerRun.size() > 1) { // in case expected chisq is not applicable like for asymmetry fits
2159 UInt_t ndf_run = 0;
2160 for (UInt_t i=0; i<chisqPerRun.size(); i++) {
2161 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2162 ndfPerHisto.push_back(ndf_run);
2163 }
2164
2165 // feed the msr-file handler
2166 PMsrStatisticStructure *statistics = fRunInfo->GetMsrStatistic();
2167 if (statistics) {
2168 statistics->fMinPerHisto = chisqPerRun;
2169 statistics->fNdfPerHisto = ndfPerHisto;
2170 }
2171 }
2172
2173 // check if sector command has been requested
2174 if (fSectorFlag) {
2175 PDoubleVector error;
2176 for (UInt_t i=0; i<fParams.size(); i++)
2177 error.push_back(fParams[i].fStep);
2178
2179 PrepareSector(param, error);
2180 }
2181
2182 // clean up
2183 param.clear();
2184 expectedchisqPerRun.clear();
2185 ndfPerHisto.clear();
2186 chisqPerRun.clear();
2187
2188 std::cout << ">> PFitter::ExecuteSave(): will write minuit2 output file ..." << std::endl;
2189
2190 std::ofstream fout;
2191
2192 // open minuit2 output file
2193 if (firstSave)
2194 fout.open("MINUIT2.OUTPUT", std::iostream::out);
2195 else
2196 fout.open("MINUIT2.OUTPUT", std::iostream::out | std::iostream::app);
2197
2198 if (!fout.is_open()) {
2199 std::cerr << std::endl << "**ERROR** PFitter::ExecuteSave() couldn't open MINUIT2.OUTPUT file";
2200 std::cerr << std::endl;
2201 return false;
2202 }
2203
2204 // write header
2205 TDatime dt;
2206 fout << std::endl << "*************************************************************************";
2207 fout << std::endl << " musrfit MINUIT2 output file from " << fRunInfo->GetFileName().Data() << " - " << dt.AsSQLString();
2208 fout << std::endl << "*************************************************************************";
2209 fout << std::endl;
2210
2211 // write elapsed times
2212 fout << std::endl << " elapsed times:";
2213 for (UInt_t i=0; i<fElapsedTime.size(); i++) {
2214 fout << std::endl << " " << fElapsedTime[i];
2215 }
2216 fout << std::endl;
2217 fout << std::endl << "*************************************************************************";
2218 fout << std::endl;
2219 fElapsedTime.clear();
2220
2221 // write global information
2222 fout << std::endl << " Fval() = " << mnState.Fval() << ", Edm() = " << mnState.Edm() << ", NFcn() = " << mnState.NFcn();
2223 fout << std::endl;
2224 fout << std::endl << "*************************************************************************";
2225 fout << std::endl;
2226
2227 // identifiy the longest variable name for proper formating reasons
2228 Int_t maxLength = 10;
2229 for (UInt_t i=0; i<fParams.size(); i++) {
2230 if (fParams[i].fName.Length() > maxLength)
2231 maxLength = fParams[i].fName.Length() + 1;
2232 }
2233
2234 // write parameters
2235 fParams = *(fRunInfo->GetMsrParamList()); // get the update parameters back
2236 fout << std::endl << " PARAMETERS";
2237 fout << std::endl << "-------------------------------------------------------------------------";
2238 fout << std::endl << " ";
2239 for (Int_t j=0; j<=maxLength-4; j++)
2240 fout << " ";
2241 fout << "Parabolic Minos";
2242 fout << std::endl << " No Name";
2243 for (Int_t j=0; j<=maxLength-4; j++)
2244 fout << " ";
2245 fout << "Value Error Negative Positive Limits";
2246 for (UInt_t i=0; i<fParams.size(); i++) {
2247 // write no
2248 fout.setf(std::ios::right, std::ios::adjustfield);
2249 fout.width(3);
2250 fout << std::endl << i+1 << " ";
2251 // write name
2252 fout << fParams[i].fName.Data();
2253 for (Int_t j=0; j<=maxLength-fParams[i].fName.Length(); j++)
2254 fout << " ";
2255 // write value
2256 fout.setf(std::ios::left, std::ios::adjustfield);
2257 fout.precision(6);
2258 fout.width(10);
2259 fout << fParams[i].fValue << " ";
2260 // write parabolic error
2261 fout.setf(std::ios::left, std::ios::adjustfield);
2262 fout.precision(6);
2263 fout.width(10);
2264 if (fParams[i].fStep != 0.0)
2265 fout << fMnUserParams.Error(i) << " ";
2266 else
2267 fout << "---";
2268 // write minos errors
2269 if (fParams[i].fPosErrorPresent) {
2270 fout.setf(std::ios::left, std::ios::adjustfield);
2271 fout.precision(6);
2272 fout.width(12);
2273 fout << fParams[i].fStep;
2274 fout.setf(std::ios::left, std::ios::adjustfield);
2275 fout.precision(6);
2276 fout.width(11);
2277 fout << fParams[i].fPosError << " ";
2278 } else {
2279 fout.setf(std::ios::left, std::ios::adjustfield);
2280 fout.width(12);
2281 fout << "---";
2282 fout.setf(std::ios::left, std::ios::adjustfield);
2283 fout.width(12);
2284 fout << "---";
2285 }
2286 // write limits
2287 if (fParams[i].fNoOfParams > 5) {
2288 fout.setf(std::ios::left, std::ios::adjustfield);
2289 fout.width(7);
2290 if (fParams[i].fLowerBoundaryPresent)
2291 fout << fParams[i].fLowerBoundary;
2292 else
2293 fout << "---";
2294 fout.setf(std::ios::left, std::ios::adjustfield);
2295 fout.width(7);
2296 if (fParams[i].fUpperBoundaryPresent)
2297 fout << fParams[i].fUpperBoundary;
2298 else
2299 fout << "---";
2300 } else {
2301 fout.setf(std::ios::left, std::ios::adjustfield);
2302 fout.width(7);
2303 fout << "---";
2304 fout.setf(std::ios::left, std::ios::adjustfield);
2305 fout.width(7);
2306 fout << "---";
2307 }
2308 }
2309 fout << std::endl;
2310 fout << std::endl << "*************************************************************************";
2311
2312 // write covariance matrix
2313 fout << std::endl << " COVARIANCE MATRIX";
2314 fout << std::endl << "-------------------------------------------------------------------------";
2315 if (mnState.HasCovariance()) {
2316 ROOT::Minuit2::MnUserCovariance cov = mnState.Covariance();
2317 fout << std::endl << "from " << cov.Nrow() << " free parameters";
2318 for (UInt_t i=0; i<cov.Nrow(); i++) {
2319 fout << std::endl;
2320 for (UInt_t j=0; j<i; j++) {
2321 fout.setf(std::ios::left, std::ios::adjustfield);
2322 fout.precision(6);
2323 if (cov(i,j) > 0.0) {
2324 fout << " ";
2325 fout.width(13);
2326 } else {
2327 fout.width(14);
2328 }
2329 fout << cov(i,j);
2330 }
2331 }
2332 } else {
2333 fout << std::endl << " no covariance matrix available";
2334 }
2335 fout << std::endl;
2336 fout << std::endl << "*************************************************************************";
2337
2338 // write correlation matrix
2339 fout << std::endl << " CORRELATION COEFFICIENTS";
2340 fout << std::endl << "-------------------------------------------------------------------------";
2341 if (mnState.IsValid() && mnState.HasCovariance()) {
2342 ROOT::Minuit2::MnGlobalCorrelationCoeff corr = mnState.GlobalCC();
2343 ROOT::Minuit2::MnUserCovariance cov = mnState.Covariance();
2344 PIntVector parNo;
2345 fout << std::endl << " No Global ";
2346 for (UInt_t i=0; i<fParams.size(); i++) {
2347 // only free parameters, i.e. not fixed, and not unsed ones!
2348 if ((fParams[i].fStep != 0) && (fRunInfo->ParameterInUse(i) > 0) && (!fMnUserParams.Parameters().at(i).IsFixed())) {
2349 fout.setf(std::ios::left, std::ios::adjustfield);
2350 fout.width(9);
2351 fout << i+1;
2352 parNo.push_back(i);
2353 }
2354 }
2355 // check that there is a correspondens between minuit2 and musrfit book keeping
2356 if (parNo.size() != cov.Nrow()) {
2357 std::cerr << std::endl << "**SEVERE ERROR** in PFitter::ExecuteSave(): minuit2 and musrfit book keeping to not correspond! Unable to write correlation matrix.";
2358 std::cerr << std::endl;
2359 } else { // book keeping is OK
2360 TString title("Minuit2 Output Correlation Matrix for ");
2361 title += fRunInfo->GetFileName();
2362 title += " - ";
2363 title += dt.AsSQLString();
2364 std::unique_ptr<TCanvas> ccorr = std::make_unique<TCanvas>("ccorr", "title", 500, 500);
2365 std::unique_ptr<TH2D> hcorr = std::make_unique<TH2D>("hcorr", title, cov.Nrow(), 0.0, cov.Nrow(), cov.Nrow(), 0.0, cov.Nrow());
2366 Double_t dval;
2367 for (UInt_t i=0; i<cov.Nrow(); i++) {
2368 // parameter number
2369 fout << std::endl << " ";
2370 fout.setf(std::ios::left, std::ios::adjustfield);
2371 fout.width(5);
2372 fout << parNo[i]+1;
2373 // global correlation coefficient
2374 fout.setf(std::ios::left, std::ios::adjustfield);
2375 fout.precision(6);
2376 fout.width(12);
2377 fout << corr.GlobalCC()[i];
2378 // correlations matrix
2379 for (UInt_t j=0; j<cov.Nrow(); j++) {
2380 fout.setf(std::ios::left, std::ios::adjustfield);
2381// fout.precision(4);
2382 if (i==j) {
2383 fout.width(9);
2384 fout << " 1.0 ";
2385 hcorr->Fill((Double_t)i,(Double_t)i,1.0);
2386 } else {
2387 // check that errors are none zero
2388 if (fMnUserParams.Error(parNo[i]) == 0.0) {
2389 std::cerr << std::endl << "**SEVERE ERROR** in PFitter::ExecuteSave(): parameter no " << parNo[i]+1 << " has an error == 0. Cannot correctly handle the correlation matrix.";
2390 std::cerr << std::endl;
2391 dval = 0.0;
2392 } else if (fMnUserParams.Error(parNo[j]) == 0.0) {
2393 std::cerr << std::endl << "**SEVERE ERROR** in PFitter::ExecuteSave(): parameter no " << parNo[j]+1 << " has an error == 0. Cannot correctly handle the correlation matrix.";
2394 std::cerr << std::endl;
2395 dval = 0.0;
2396 } else {
2397 dval = cov(i,j)/(fMnUserParams.Error(parNo[i])*fMnUserParams.Error(parNo[j]));
2398 }
2399 hcorr->Fill((Double_t)i,(Double_t)j,dval);
2400 // handle precision, ugly but ...
2401 if (dval < 1.0e-2) {
2402 fout.precision(2);
2403 } else {
2404 fout.precision(4);
2405 }
2406 // handle sign
2407 if (dval > 0.0) {
2408 fout << " ";
2409 fout.width(7);
2410 } else {
2411 fout.width(8);
2412 }
2413 fout << dval << " ";
2414 }
2415 }
2416 }
2417 // write correlation matrix into a root file
2418 TFile ff("MINUIT2.root", "recreate");
2419 ccorr->Draw();
2420 if (cov.Nrow() <= 6)
2421 hcorr->Draw("COLZTEXT");
2422 else
2423 hcorr->Draw("COLZ");
2424 ccorr->Write("ccorr", TObject::kOverwrite, sizeof(ccorr));
2425 hcorr->Write("hcorr", TObject::kOverwrite, sizeof(hcorr));
2426 ff.Close();
2427
2428 if (fYamlOut) {
2429 // write the fit results to an easy-to-read/parse yaml file
2430 // note: the block names follow those used by Python library iminuit
2431 // https://github.com/scikit-hep/iminuit
2432
2433 // dynamically name the yaml output file
2434 // https://stackoverflow.com/a/25389052
2435 std::string yaml_filename(fRunInfo->GetFileName().Data());
2436 const std::string msr_ext(".msr");
2437 yaml_filename.replace(yaml_filename.find(msr_ext), msr_ext.length(),
2438 ".yaml");
2439
2440 // define yaml's 2-space indentation
2441 const std::string yaml_indent(" ");
2442
2443 // open the yaml file for writing
2444 std::ofstream yaml_file(yaml_filename);
2445
2446 // number formatting of the output
2447 yaml_file << std::scientific << std::setprecision(16);
2448
2449 // write the parameter values
2450 yaml_file << "values:\n";
2451 for (unsigned int i = 0; i < fParams.size(); ++i) {
2452 yaml_file << yaml_indent << fParams[i].fName.Data() << ": "
2453 << fParams[i].fValue << "\n";
2454 }
2455
2456 // write the parabolic errors
2457 yaml_file << "errors:\n";
2458 for (unsigned int i = 0; i < fParams.size(); ++i) {
2459 yaml_file << yaml_indent << fParams[i].fName.Data() << ": "
2460 << fMnUserParams.Error(i) << "\n";
2461 }
2462
2463 // write the minos errors
2464 yaml_file << "mnerrors:\n";
2465 for (unsigned int i = 0; i < fParams.size(); ++i) {
2466 // use boost's implementation of a variant, which can be streamed by
2467 // default - see: https://stackoverflow.com/q/47168477
2468 boost::variant<double, std::string> positive_error, negative_error;
2469 if (fParams[i].fPosErrorPresent) {
2470 positive_error = fParams[i].fPosError;
2471 negative_error = fParams[i].fStep;
2472 } else {
2473 positive_error = "null";
2474 negative_error = "null";
2475 }
2476
2477 yaml_file << yaml_indent << fParams[i].fName.Data() << ":\n";
2478 yaml_file << yaml_indent << yaml_indent
2479 << "positive: " << positive_error << "\n";
2480 yaml_file << yaml_indent << yaml_indent
2481 << "negative: " << negative_error << "\n";
2482 }
2483
2484 // write the parameter limits
2485 yaml_file << "limits:\n";
2486 for (unsigned int i = 0; i < fParams.size(); ++i) {
2487 // use boost's implementation of a variant, which can be streamed by
2488 // default - see: https://stackoverflow.com/q/47168477
2489 boost::variant<double, std::string> upper_limit, lower_limit;
2490 if (fParams[i].fLowerBoundaryPresent) {
2491 lower_limit = fParams[i].fLowerBoundary;
2492 } else {
2493 lower_limit = "null";
2494 }
2495 if (fParams[i].fUpperBoundaryPresent) {
2496 upper_limit = fParams[i].fUpperBoundary;
2497 } else {
2498 upper_limit = "null";
2499 }
2500
2501 yaml_file << yaml_indent << fParams[i].fName.Data() << ":\n";
2502 yaml_file << yaml_indent << yaml_indent << "lower: " << lower_limit
2503 << "\n";
2504 yaml_file << yaml_indent << yaml_indent << "upper: " << upper_limit
2505 << "\n";
2506 }
2507
2508 // write if the parameter is fixed
2509 yaml_file << "fixed:\n";
2510 for (unsigned int i = 0; i < fParams.size(); ++i) {
2511 std::string is_fixed = fParams[i].fStep == 0.0 ? "true" : "false";
2512 yaml_file << yaml_indent << fParams[i].fName.Data() << ": " << is_fixed
2513 << "\n";
2514 }
2515
2516 // write the covariance matrix (omitting fixed parameters)
2517 yaml_file << "covariance:\n";
2518 for (unsigned int i = 0; i < cov.Nrow(); ++i) {
2519 yaml_file << yaml_indent << mnState.Name(parNo[i]) << ":\n";
2520 for (unsigned int j = 0; j < cov.Nrow(); ++j) {
2521 yaml_file << yaml_indent << yaml_indent << mnState.Name(parNo[j])
2522 << ": " << cov(i, j) << "\n";
2523 }
2524 }
2525
2526 // write the correlation matrix (omitting fixed parameters)
2527 yaml_file << "correlation:\n";
2528 for (unsigned int i = 0; i < cov.Nrow(); ++i) {
2529 yaml_file << yaml_indent << mnState.Name(parNo[i]) << ":\n";
2530 for (unsigned int j = 0; j < cov.Nrow(); ++j) {
2531 double correlation =
2532 i == j ? 1.0
2533 : cov(i, j) / (fMnUserParams.Error(parNo[i]) *
2534 fMnUserParams.Error(parNo[j]));
2535 yaml_file << yaml_indent << yaml_indent << mnState.Name(parNo[j])
2536 << ": " << correlation << "\n";
2537 }
2538 }
2539
2540 // close the yaml file
2541 yaml_file.close();
2542 }
2543 }
2544 parNo.clear(); // clean up
2545 } else {
2546 fout << std::endl << " no correlation coefficients available";
2547 }
2548
2549 fout << std::endl;
2550 fout << std::endl << "*************************************************************************";
2551 fout << std::endl << " chisq/maxLH RESULT ";
2552 fout << std::endl << "*************************************************************************";
2553 PMsrStatisticStructure *statistics = fRunInfo->GetMsrStatistic();
2554
2555 // get time range and write it
2556 Double_t fitStartTime = PMUSR_UNDEFINED, fitEndTime = PMUSR_UNDEFINED;
2557 // first check if there is a global block with a valid time range
2558 PMsrGlobalBlock *global = fRunInfo->GetMsrGlobal();
2559 fitStartTime = global->GetFitRange(0);
2560 fitEndTime = global->GetFitRange(1);
2561 if (fitStartTime == PMUSR_UNDEFINED) { // no global time range, hence take the one from the first run block
2562 PMsrRunList *run = fRunInfo->GetMsrRunList();
2563 fitStartTime = run->at(0).GetFitRange(0);
2564 fitEndTime = run->at(0).GetFitRange(1);
2565 }
2566 fout.setf(std::ios::fixed, std::ios::floatfield);
2567 fout << std::endl << " Time Range: " << fitStartTime << ", " << fitEndTime << std::endl;
2568 if (fUseChi2) {
2569 fout.setf(std::ios::fixed, std::ios::floatfield);
2570 fout << std::endl << " chisq = " << std::setprecision(4) << statistics->fMin << ", NDF = " << statistics->fNdf << ", chisq/NDF = " << std::setprecision(6) << statistics->fMin/statistics->fNdf;
2571 if (statistics->fMinExpected > 0)
2572 fout << std::endl << " chisq_e = " << std::setprecision(4) << statistics->fMinExpected << ", NDF = " << statistics->fNdf << ", chisq_e/NDF = " << std::setprecision(6) << statistics->fMinExpected/statistics->fNdf;
2573 } else { // maxLH
2574 fout.setf(std::ios::fixed, std::ios::floatfield);
2575 fout << std::endl << " maxLH = " << std::setprecision(4) << statistics->fMin << ", NDF = " << statistics->fNdf << ", maxLH/NDF = " << std::setprecision(6) << statistics->fMin/statistics->fNdf;
2576 if (statistics->fMinExpected > 0)
2577 fout << std::endl << " maxLH_e = " << std::setprecision(4) << statistics->fMinExpected << ", NDF = " << statistics->fNdf << ", maxLH_e/NDF = " << std::setprecision(6) << statistics->fMinExpected/statistics->fNdf;
2578 }
2579
2580 if (fSectorFlag)
2581 ExecuteSector(fout);
2582
2583 fout << std::endl;
2584 fout << std::endl << "*************************************************************************";
2585 fout << std::endl << " DONE ";
2586 fout << std::endl << "*************************************************************************";
2587 fout << std::endl << std::endl;
2588
2589 // close MINUIT2.OUTPUT file
2590 fout.close();
2591
2592 return true;
2593}
2594
2595//--------------------------------------------------------------------------
2596// ExecuteSimplex
2597//--------------------------------------------------------------------------
2604{
2605 std::cout << ">> PFitter::ExecuteSimplex(): will call simplex ..." << std::endl;
2606
2607 // create minimizer object
2608 // strategy is by default = 'default'
2609 ROOT::Minuit2::MnSimplex simplex((*fFitterFcn), fMnUserParams, ROOT::Minuit2::MnStrategy{fStrategy});
2610
2611 // minimize
2612 // maxfcn is 10*MINUIT2 Default maxfcn
2613 UInt_t maxfcn = std::numeric_limits<UInt_t>::max();
2614 // tolerance = MINUIT2 Default tolerance
2615 Double_t tolerance = 0.1;
2616 // keep track of elapsed time
2617 Double_t start=0.0, end=0.0;
2618 start=MilliTime();
2619 ROOT::Minuit2::FunctionMinimum min = simplex(maxfcn, tolerance);
2620 end=MilliTime();
2621 std::cout << ">> PFitter::ExecuteMinimize(): execution time for Simplex = " << std::setprecision(3) << (end-start)/1.0e3 << " sec." << std::endl;
2622 TString str = TString::Format("Simplex: %.3f sec", (end-start)/1.0e3);
2623 fElapsedTime.push_back(str);
2624 if (!min.IsValid()) {
2625 std::cerr << std::endl << ">> PFitter::ExecuteSimplex(): **WARNING**: Fit did not converge, sorry ...";
2626 std::cerr << std::endl;
2627 fIsValid = false;
2628 return false;
2629 }
2630
2631 // keep FunctionMinimum object
2632 fFcnMin.reset(new ROOT::Minuit2::FunctionMinimum(min));
2633
2634 // keep user parameters
2635 if (fFcnMin)
2636 fMnUserParams = fFcnMin->UserParameters();
2637
2638 // fill run info
2639 for (UInt_t i=0; i<fParams.size(); i++) {
2640 Double_t dval = min.UserState().Value(i);
2641 if (fPhase[i]) {
2642 Int_t m = (Int_t)(dval/360.0);
2643 dval = dval - m*360.0;
2644 }
2645 fRunInfo->SetMsrParamValue(i, dval);
2646 fRunInfo->SetMsrParamStep(i, min.UserState().Error(i));
2647 fRunInfo->SetMsrParamPosErrorPresent(i, false);
2648 }
2649
2650 // handle statistics
2651 Double_t minVal = min.Fval();
2652 UInt_t ndf = fFitterFcn->GetTotalNoOfFittedBins();
2653 // subtract number of varied parameters from total no of fitted bins -> ndf
2654 for (UInt_t i=0; i<fParams.size(); i++) {
2655 if ((min.UserState().Error(i) != 0.0) && !fMnUserParams.Parameters().at(i).IsFixed())
2656 ndf -= 1;
2657 }
2658
2659 // feed run info with new statistics info
2660 fRunInfo->SetMsrStatisticMin(minVal);
2661 fRunInfo->SetMsrStatisticNdf(ndf);
2662
2663 fConverged = true;
2664
2665 if (fPrintLevel >= 2)
2666 std::cout << *fFcnMin << std::endl;
2667
2668 return true;
2669}
2670
2671//--------------------------------------------------------------------------
2672// PrepareSector
2673//--------------------------------------------------------------------------
2681{
2682 Double_t val;
2683 UInt_t ndf;
2684
2685 Int_t usedParams = 0;
2686 for (UInt_t i=0; i<error.size(); i++) {
2687 if (error[i] != 0.0)
2688 usedParams++;
2689 }
2690
2691 PDoublePairVector secFitRange;
2692 secFitRange.resize(1);
2693
2694 if (fUseChi2) {
2695 Double_t totalExpectedChisq = 0.0;
2696 PDoubleVector expectedChisqPerRun;
2697 PDoubleVector chisqPerRun;
2698 for (UInt_t k=0; k<fSector.size(); k++) {
2699 // set sector fit range
2700 secFitRange[0].first = fSector[k].GetTimeRangeFirst(0);
2701 secFitRange[0].second = fSector[k].GetTimeRangeLast();
2702 fRunListCollection->SetFitRange(secFitRange);
2703 // calculate chisq
2704 val = (*fFitterFcn)(param);
2705 fSector[k].SetChisq(val);
2706 // calculate NDF
2707 ndf = static_cast<UInt_t>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
2708 fSector[k].SetNDF(ndf);
2709 // calculate expected chisq
2710 totalExpectedChisq = 0.0;
2711 fFitterFcn->CalcExpectedChiSquare(param, totalExpectedChisq, expectedChisqPerRun);
2712 fSector[k].SetExpectedChisq(totalExpectedChisq);
2713 // calculate chisq per run
2714 for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
2715 chisqPerRun.push_back(fRunListCollection->GetSingleRunChisq(param, i));
2716 fSector[k].SetChisq(chisqPerRun[i], i);
2717 fSector[k].SetExpectedChisq(expectedChisqPerRun[i], i);
2718 }
2719
2720 if (totalExpectedChisq != 0.0) {
2721 UInt_t ndf_run = 0;
2722 for (UInt_t i=0; i<expectedChisqPerRun.size(); i++) {
2723 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2724 if (ndf_run > 0) {
2725 fSector[k].SetNDF(ndf_run, i);
2726 }
2727 }
2728 } else if (chisqPerRun.size() > 0) { // in case expected chisq is not applicable like for asymmetry fits
2729 UInt_t ndf_run = 0;
2730 for (UInt_t i=0; i<chisqPerRun.size(); i++) {
2731 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2732 if (ndf_run > 0) {
2733 fSector[k].SetNDF(ndf_run, i);
2734 }
2735 }
2736 }
2737 // clean up
2738 chisqPerRun.clear();
2739 expectedChisqPerRun.clear();
2740 }
2741 } else {
2742 Double_t totalExpectedMaxLH = 0.0;
2743 PDoubleVector expectedMaxLHPerRun;
2744 PDoubleVector maxLHPerRun;
2745 for (UInt_t k=0; k<fSector.size(); k++) {
2746 // set sector fit range
2747 secFitRange[0].first = fSector[k].GetTimeRangeFirst(0);
2748 secFitRange[0].second = fSector[k].GetTimeRangeLast();
2749 fRunListCollection->SetFitRange(secFitRange);
2750 // calculate maxLH
2751 val = (*fFitterFcn)(param);
2752 fSector[k].SetChisq(val);
2753 // calculate NDF
2754 ndf = static_cast<UInt_t>(fFitterFcn->GetTotalNoOfFittedBins()) - usedParams;
2755 fSector[k].SetNDF(ndf);
2756 // calculate expected maxLH
2757 totalExpectedMaxLH = 0.0;
2758 fFitterFcn->CalcExpectedChiSquare(param, totalExpectedMaxLH, expectedMaxLHPerRun);
2759 fSector[k].SetExpectedChisq(totalExpectedMaxLH);
2760 // calculate maxLH per run
2761 for (UInt_t i=0; i<fRunInfo->GetMsrRunList()->size(); i++) {
2762 maxLHPerRun.push_back(fRunListCollection->GetSingleRunMaximumLikelihood(param, i));
2763 fSector[k].SetChisq(maxLHPerRun[i], i);
2764 fSector[k].SetExpectedChisq(expectedMaxLHPerRun[i], i);
2765 }
2766
2767 if (totalExpectedMaxLH != 0.0) {
2768 UInt_t ndf_run = 0;
2769 for (UInt_t i=0; i<expectedMaxLHPerRun.size(); i++) {
2770 ndf_run = fFitterFcn->GetNoOfFittedBins(i) - fRunInfo->GetNoOfFitParameters(i);
2771 if (ndf_run > 0) {
2772 fSector[k].SetNDF(ndf_run, i);
2773 }
2774 }
2775 }
2776
2777 // clean up
2778 maxLHPerRun.clear();
2779 expectedMaxLHPerRun.clear();
2780 }
2781 }
2782}
2783
2784//--------------------------------------------------------------------------
2785// ExecuteSector
2786//--------------------------------------------------------------------------
2793Bool_t PFitter::ExecuteSector(std::ofstream &fout)
2794{
2795 fout << std::endl;
2796 fout << std::endl << "*************************************************************************";
2797 fout << std::endl << " SECTOR RESULTS";
2798 fout << std::endl << "*************************************************************************";
2799
2800 if (fUseChi2) {
2801 for (UInt_t i=0; i<fSector.size(); i++) {
2802 fout << std::endl;
2803 fout << " Sector " << i+1 << ": FitRange: " << fSector[i].GetTimeRangeFirst(0) << ", " << fSector[i].GetTimeRangeLast() << std::endl;
2804 fout << " chisq = " << fSector[i].GetChisq() << ", NDF = " << fSector[i].GetNDF() << ", chisq/NDF = " << fSector[i].GetChisq()/fSector[i].GetNDF();
2805
2806 if (fSector[i].GetExpectedChisq() > 0) {
2807 fout << std::endl << " expected chisq = " << fSector[i].GetExpectedChisq() << ", NDF = " << fSector[i].GetNDF() << ", expected chisq/NDF = " << fSector[i].GetExpectedChisq()/fSector[i].GetNDF();
2808 for (UInt_t j=0; j<fSector[i].GetNoRuns(); j++) {
2809 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) << ")";
2810 }
2811 } else if (fSector[i].GetNoRuns() > 0) { // in case expected chisq is not applicable like for asymmetry fits
2812 for (UInt_t j=0; j<fSector[i].GetNoRuns(); j++) {
2813 fout << std::endl << " run block " << j+1 << " (NDF/red.chisq) = (" << fSector[i].GetNDF(j) << "/" << fSector[i].GetChisq(j)/fSector[i].GetNDF(j) << ")";
2814 }
2815 }
2816 fout << std::endl << "++++";
2817 }
2818 } else { // max log likelihood
2819 for (UInt_t i=0; i<fSector.size(); i++) {
2820 fout << std::endl;
2821 fout << " Sector " << i+1 << ": FitRange: " << fSector[i].GetTimeRangeFirst(0) << ", " << fSector[i].GetTimeRangeLast() << std::endl;
2822 fout << " maxLH = " << fSector[i].GetChisq() << ", NDF = " << fSector[i].GetNDF() << ", maxLH/NDF = " << fSector[i].GetChisq()/fSector[i].GetNDF();
2823
2824 if (fSector[i].GetExpectedChisq() > 0) {
2825 fout << std::endl << " expected maxLH = " << fSector[i].GetExpectedChisq() << ", NDF = " << fSector[i].GetNDF() << ", expected maxLH/NDF = " << fSector[i].GetExpectedChisq()/fSector[i].GetNDF();
2826 for (UInt_t j=0; j<fSector[i].GetNoRuns(); j++) {
2827 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) << ")";
2828 }
2829 } else if (fSector[i].GetNoRuns() > 0) { // in case expected chisq is not applicable like for asymmetry fits
2830 for (UInt_t j=0; j<fSector[i].GetNoRuns(); j++) {
2831 fout << std::endl << " run block " << j+1 << " (NDF/red.maxLH) = (" << fSector[i].GetNDF(j) << "/" << fSector[i].GetChisq(j)/fSector[i].GetNDF(j) << ")";
2832 }
2833 }
2834 fout << std::endl << "++++";
2835 }
2836 }
2837
2838 return true;
2839}
2840
2841//--------------------------------------------------------------------------
2842// MilliTime
2843//--------------------------------------------------------------------------
2850{
2851 struct timeval now;
2852 gettimeofday(&now, nullptr);
2853
2854 return ((Double_t)now.tv_sec * 1.0e6 + (Double_t)now.tv_usec)/1.0e3;
2855}
2856
2857//--------------------------------------------------------------------------
2858// ParamRound (private)
2859//--------------------------------------------------------------------------
2873{
2874 PDoubleVector par_r;
2875
2876 par_r.resize(par.size());
2877 ok = true;
2878
2879 if (par.size() != err.size()) {
2880 // error msg
2881 ok = false;
2882 return par_r;
2883 }
2884
2885 int exp;
2886 double dval;
2887 for (unsigned int i=0; i<par.size(); i++) {
2888 if (err[i] != 0.0) {
2889 exp = floor(log10(fabs(err[i]))-1);
2890 dval = round(par[i]*pow(10.0, -exp))/pow(10.0, -exp);
2891 par_r[i] = dval;
2892 } else {
2893 par_r[i] = par[i];
2894 }
2895 }
2896
2897 return par_r;
2898}
2899
2900
2901//-------------------------------------------------------------------------------------------------
2902// end
2903//-------------------------------------------------------------------------------------------------
#define PMN_FIX
Fix parameters at current values.
Definition PFitter.h:70
#define PMN_SIMPLEX
SIMPLEX minimizer (robust but slow)
Definition PFitter.h:92
#define PMN_USER_PARAM_STATE
Set user parameter state (not implemented)
Definition PFitter.h:98
#define PMN_RESTORE
Restore parameters from previous SAVE.
Definition PFitter.h:86
#define PMN_RELEASE
Release previously fixed parameters.
Definition PFitter.h:84
#define PMN_PRINT
Set print level for fit output (0=quiet, 1=normal, 2=verbose)
Definition PFitter.h:100
#define PMN_PLOT
Plot command (for scan/contour results)
Definition PFitter.h:82
#define PMN_CONTOURS
Contour plot command (2D error ellipses)
Definition PFitter.h:64
#define PMN_HESSE
Calculate Hessian matrix for error estimation.
Definition PFitter.h:72
#define PMN_FIT_RANGE
Fit range scan to find optimal fitting window.
Definition PFitter.h:68
#define PMN_EIGEN
Eigenvalue analysis (not implemented)
Definition PFitter.h:66
#define PMN_MACHINE_PRECISION
Set machine precision for numerical derivatives.
Definition PFitter.h:74
#define PMN_SAVE
Save current parameter state.
Definition PFitter.h:88
#define PMN_USER_COVARIANCE
Set user covariance matrix (not implemented)
Definition PFitter.h:96
#define PMN_INTERACTIVE
Interactive mode (not implemented in musrfit)
Definition PFitter.h:62
#define PMN_MIGRAD
MIGRAD minimizer (gradient-based, recommended)
Definition PFitter.h:76
#define PMN_SECTOR
Calculate χ² vs. time in sectors (time-window analysis)
Definition PFitter.h:102
#define PMN_SCAN
Parameter scan (1D or 2D)
Definition PFitter.h:90
#define PMN_MINOS
MINOS error analysis (asymmetric confidence intervals)
Definition PFitter.h:80
#define PMN_MINIMIZE
MINIMIZE (automatic algorithm selection)
Definition PFitter.h:78
std::pair< Double_t, Double_t > PDoublePair
Definition PMusr.h:405
std::vector< PMsrRunBlock > PMsrRunList
Definition PMusr.h:1263
#define PMUSR_UNDEFINED
Definition PMusr.h:177
std::vector< PMsrLineStructure > PMsrLines
Definition PMusr.h:1007
std::vector< PDoublePair > PDoublePairVector
Definition PMusr.h:411
std::pair< Int_t, Int_t > PIntPair
Definition PMusr.h:387
std::vector< Int_t > PIntVector
Definition PMusr.h:381
std::vector< Double_t > PDoubleVector
Definition PMusr.h:399
return status
Bool_t ExecuteContours()
Executes CONTOURS command (2D error contours).
Definition PFitter.cpp:1536
Bool_t ExecutePlot()
Executes PLOT command (visualize scan/contour results).
Definition PFitter.cpp:1939
PDoublePairVector fOriginalFitRange
Original fit ranges per run (saved for FIT_RANGE command)
Definition PFitter.h:327
UInt_t fScanNoPoints
Number of scan/contour evaluation points (default=41)
Definition PFitter.h:322
Bool_t IsValid()
Definition PFitter.h:273
UInt_t fStrategy
Minuit2 strategy: 0=fast/low-accuracy, 1=default, 2=careful/high-accuracy.
Definition PFitter.h:303
Double_t fScanHigh
Scan upper bound: 0.0 = auto (2σ above current value)
Definition PFitter.h:324
Bool_t fIsValid
Overall validity flag: true if fitter initialized successfully.
Definition PFitter.h:295
Bool_t ExecutePrintLevel(UInt_t lineNo)
Executes PRINT command (set verbosity level).
Definition PFitter.cpp:1959
PStringVector fElapsedTime
Timing information for each fit command.
Definition PFitter.h:329
PIntPairVector fCmdList
Parsed commands: first=command ID, second=line number.
Definition PFitter.h:312
Double_t MilliTime()
Returns current time in milliseconds.
Definition PFitter.cpp:2849
UInt_t fScanParameter[2]
Parameter indices: [0]=primary scan/contour, [1]=secondary (contours only)
Definition PFitter.h:321
Bool_t DoFit()
Main entry point for executing the fit.
Definition PFitter.cpp:625
PIntVector GetParFromFun(const TString funStr)
Extracts parameter numbers from a FUNCTIONS block entry.
Definition PFitter.cpp:478
Bool_t fSectorFlag
SECTOR command present flag.
Definition PFitter.h:332
Bool_t fYamlOut
Output flag: true to generate YAML output file (MINUIT2.OUTPUT → yaml)
Definition PFitter.h:299
Bool_t ExecuteScan()
Executes SCAN command (1D parameter space scan).
Definition PFitter.cpp:2067
UInt_t fPrintLevel
Verbosity level: 0=quiet, 1=normal, 2=verbose (Minuit output)
Definition PFitter.h:301
Bool_t ExecuteSave(Bool_t first)
Executes SAVE command (store current parameters).
Definition PFitter.cpp:2094
PDoubleVector ParamRound(const PDoubleVector &par, const PDoubleVector &err, Bool_t &ok)
Rounds parameters for output with appropriate precision.
Definition PFitter.cpp:2872
Bool_t fScanAll
Multi-parameter scan flag: false=1D scan, true=2D scan (not fully implemented)
Definition PFitter.h:320
Bool_t fIsScanOnly
Scan mode flag: true if only parameter scans requested (no minimization)
Definition PFitter.h:296
virtual ~PFitter()
Destructor - Cleans up dynamically allocated resources.
Definition PFitter.cpp:351
PRunListCollection * fRunListCollection
Pointer to preprocessed run data collection.
Definition PFitter.h:307
Bool_t ExecuteSimplex()
Executes SIMPLEX command (non-gradient minimization).
Definition PFitter.cpp:2603
PMsrLines fCmdLines
Raw command lines from MSR COMMANDS block.
Definition PFitter.h:311
std::vector< PSectorChisq > fSector
Sector analysis results (χ² vs. time windows)
Definition PFitter.h:333
Bool_t SetParameters()
Transfers MSR parameters to Minuit2 parameter state.
Definition PFitter.cpp:1488
Bool_t ExecuteSector(std::ofstream &fout)
Executes SECTOR command (time-dependent χ² analysis).
Definition PFitter.cpp:2793
void GetPhaseParams()
Identifies which parameters represent phase angles.
Definition PFitter.cpp:389
Double_t fScanLow
Scan lower bound: 0.0 = auto (2σ below current value)
Definition PFitter.h:323
PFitter(PMsrHandler *runInfo, PRunListCollection *runListCollection, Bool_t chisq_only=false, Bool_t yaml_out=false)
Constructor for the fitting engine.
Definition PFitter.cpp:289
Bool_t ExecuteHesse()
Executes HESSE command (calculate error matrix).
Definition PFitter.cpp:1668
PMsrParamList fParams
Copy of parameter list from MSR file.
Definition PFitter.h:309
PMsrHandler * fRunInfo
Pointer to MSR file handler (parameters, theory, commands)
Definition PFitter.h:306
Bool_t ExecuteRelease(UInt_t lineNo)
Executes RELEASE command (unfreeze parameters).
Definition PFitter.cpp:2010
Bool_t ExecuteMinos()
Executes MINOS command (asymmetric error analysis).
Definition PFitter.cpp:1870
PIntVector GetParFromMap(const TString mapStr)
Extracts parameter numbers from a map reference.
Definition PFitter.cpp:548
PDoublePairVector fScanData
Scan results: (parameter_value, χ²) pairs.
Definition PFitter.h:325
Bool_t ExecuteMinimize()
Executes MINIMIZE command (automatic algorithm selection).
Definition PFitter.cpp:1793
ROOT::Minuit2::MnUserParameters fMnUserParams
Minuit2 parameter state (values, errors, limits)
Definition PFitter.h:316
Bool_t ExecuteMigrad()
Executes MIGRAD command (gradient descent minimization).
Definition PFitter.cpp:1717
std::unique_ptr< ROOT::Minuit2::FunctionMinimum > fFcnMin
Minuit2 function minimum result.
Definition PFitter.h:317
Bool_t ExecuteRestore()
Executes RESTORE command (reload saved parameters).
Definition PFitter.cpp:2045
Bool_t CheckCommands()
Validates COMMANDS block syntax and builds execution queue.
Definition PFitter.cpp:931
Bool_t fConverged
Convergence flag: true if fit converged to a valid minimum.
Definition PFitter.h:297
Bool_t fChisqOnly
Evaluation-only flag: true to calculate χ² without fitting.
Definition PFitter.h:298
Bool_t ExecuteFitRange(UInt_t lineNo)
Executes FIT_RANGE command (optimal time-window search).
Definition PFitter.cpp:1571
Bool_t ExecuteFix(UInt_t lineNo)
Executes FIX command (freeze parameters).
Definition PFitter.cpp:1637
std::vector< bool > fPhase
Phase parameter flags: true if parameter is a phase angle.
Definition PFitter.h:335
void PrepareSector(PDoubleVector &param, PDoubleVector &error)
Prepares sector χ² analysis data structures.
Definition PFitter.cpp:2680
std::unique_ptr< PFitterFcn > fFitterFcn
Objective function for Minuit2 minimization.
Definition PFitter.h:314
Bool_t fUseChi2
Fit mode: true = χ² minimization, false = log-max-likelihood.
Definition PFitter.h:300
virtual Double_t GetFitRange(UInt_t idx)
Definition PMusr.cpp:1154
MSR file parser and manager for the musrfit framework.
virtual PMsrLines * GetMsrCommands()
Returns pointer to COMMANDS block lines.
virtual PMsrParamList * GetMsrParamList()
Returns pointer to fit parameter list.
Manager class for all processed μSR run data during fitting.
void SetChisq(Double_t chisq)
Definition PFitter.h:144
Double_t GetExpectedChisq()
Definition PFitter.h:189
Double_t fLast
requested time stamp
Definition PFitter.h:211
UInt_t GetNDF()
Definition PFitter.h:198
PDoubleVector fFirst
time stamp for fgb for a given run
Definition PFitter.h:215
void SetNDF(UInt_t ndf)
Definition PFitter.h:162
void SetExpectedChisq(Double_t expChisq)
Definition PFitter.h:153
PUIntVector fNDFRun
NDF for the sector and run.
Definition PFitter.h:218
Double_t fChisq
chisq or maxLH for the sector
Definition PFitter.h:212
void SetSectorTime(Double_t last)
Definition PFitter.h:140
UInt_t fNDF
NDF for the sector.
Definition PFitter.h:214
Double_t GetTimeRangeFirst(UInt_t idx)
Definition PFitter.cpp:194
PSectorChisq(UInt_t noOfRuns)
Definition PFitter.cpp:80
Double_t GetChisq()
Definition PFitter.h:180
PDoubleVector fChisqRun
chisq or maxLH for the sector and run
Definition PFitter.h:216
Double_t fExpectedChisq
keep the expected chisq or maxLH for the sector
Definition PFitter.h:213
PDoubleVector fExpectedChisqRun
expected chisq or maxLH for the sector and run
Definition PFitter.h:217
void SetRunFirstTime(Double_t first, UInt_t idx)
Definition PFitter.cpp:108
UInt_t fNoOfRuns
number of runs presesent
Definition PFitter.h:210
UInt_t fNdf
number of degrees of freedom
Definition PMusr.h:1351
Double_t fMinExpected
expected total chi2 or max. likelihood
Definition PMusr.h:1352
Double_t fMin
chisq or max. likelihood
Definition PMusr.h:1349
PUIntVector fNdfPerHisto
number of degrees of freedom per histo
Definition PMusr.h:1354
PDoubleVector fMinExpectedPerHisto
expected pre histo chi2 or max. likelihood
Definition PMusr.h:1353
PDoubleVector fMinPerHisto
chisq or max. likelihood per histo
Definition PMusr.h:1350