34 #include "Math/Minimizer.h"
35 #include "Math/Factory.h"
37 #include "reportingUtils.hpp"
43 using namespace ROOT::Math;
51 void usage(
const char* progName,
52 const int errCode = 0)
54 cerr <<
"usage:" << endl
55 << progName <<
" -l # -u # [-i -h -q -N] [-n normfile -s start values -r rank] -w wavelist [-o outfile] " << endl
57 <<
" -l # lower edge of mass bin [MeV/c^2]" << endl
58 <<
" -u # upper edge of mass bin [MeV/c^2]" << endl
59 <<
" -w file path to wavelist file" << endl
60 <<
" -c file path to constraint config file" << endl
61 <<
" -o file path to output file (default: 'fitresult.root')" << endl
62 <<
" -a file path to acceptance file" << endl
63 <<
" -n file path to normalization file" << endl
64 <<
" -N use normalization of decay amplitudes (default: false)" << endl
65 <<
" -S file path to file with start values" <<endl
66 <<
" -r # rank of spin density matrix (default: 1)" <<endl
67 <<
" -q run quietly" << endl
68 <<
" -h print help" << endl
74 int main(
int argc,
char** argv)
78 const TString valTreeName =
"pwa";
79 const TString valBranchName =
"fitbin";
80 const double defaultStartValue = 0.01;
81 double defaultMinStep = 0.0005;
82 const unsigned int maxNmbOfIterations = 20000;
83 const bool runHesse =
false;
84 const bool runMinos =
false;
85 const string minimizerType[2] = {
"Minuit2",
"Migrad"};
100 char* progName = argv[0];
101 double binLowMass = 0;
102 double binHighMass = 0;
103 TString waveListFileName =
"";
104 TString waveConstraintConfigFileName =
"";
105 TString outFileName =
"fitresult.root";
106 TString startValFileName =
"";
107 TString normFileName;
111 bool useNorm =
false;
112 unsigned int rank = 1;
116 while ((c = getopt(argc, argv,
"l:u:iw:o:c:a:S:n:Nr:qh")) != -1)
122 binLowMass = atof(optarg);
125 binHighMass = atof(optarg);
128 outFileName = optarg;
131 waveConstraintConfigFileName = optarg;
134 startValFileName = optarg;
138 normFileName = optarg;
141 accFileName = optarg;
144 waveListFileName = optarg;
156 if (normFileName.Length() <= 1) {
157 normFileName=
"norm.int";
158 printWarn <<
"Using default normalization integral file '" << normFileName <<
"'." << endl;
160 if (accFileName.Length() <= 1) {
161 accFileName=
"norm.int";
162 printWarn <<
"Using default acceptance normalization integral file '" << accFileName <<
"'." << endl;
164 if (waveListFileName.Length() <= 1) {
165 printErr <<
"No wavelist file specified! Aborting!" << endl;
171 printInfo <<
"Creating and setting up likelihood function" << endl;
176 L.
Init(waveListFileName,
181 waveConstraintConfigFileName);
184 const unsigned int nmbPar = L.
NDim();
195 printInfo <<
"Creating and setting up minimizer " << minimizerType[0] <<
" " << minimizerType[1] << endl;
196 Minimizer* minimizer = Factory::CreateMinimizer(minimizerType[0], minimizerType[1]);
198 printErr <<
"Error creating minimizer. Exiting." << endl;
201 minimizer->SetFunction(L);
202 minimizer->SetPrintLevel((quiet) ? 0 : 3);
206 printInfo <<
"Reading start values from '" << startValFileName <<
"'." << endl;
207 double binCenter = 0.5 * (binLowMass + binHighMass);
208 bool hasStartVal =
false;
209 TFile* startValFile = NULL;
211 if (startValFileName.Length() > 2) {
213 startValFile = TFile::Open(startValFileName,
"READ");
214 if (!startValFile || startValFile->IsZombie())
215 printWarn <<
"Cannot open start value file '" << startValFileName <<
"'. Using default start values." << endl;
219 startValFile->GetObject(valTreeName, tree);
221 printWarn <<
"Cannot find start value tree '"<< valTreeName <<
"' in file '" << startValFileName <<
"'." << endl;
224 tree->SetBranchAddress(valBranchName, &startBin);
226 unsigned int iBest = 0;
228 for (
unsigned int i = 0;
i < tree->GetEntriesFast(); ++
i) {
230 if (fabs(binCenter - startBin->
mass()) <= fabs(binCenter - mBest)) {
232 mBest = startBin->
mass();
235 tree->GetEntry(iBest);
243 printInfo <<
"Setting start values for " << nmbPar <<
" parameters." << endl
244 <<
" Parameter naming scheme is: V[rank index]_[IGJPCME][isobar spec]" << endl;
245 unsigned int maxParNameLength = 0;
246 for (
unsigned int i = 0;
i < nmbPar; ++
i){
247 if (L.
parname(
i).length() > maxParNameLength)
248 maxParNameLength = L.
parname(
i).length();
252 vector<bool> parIsFixed(nmbPar,
false);
253 for (
unsigned int i = 0;
i < nmbPar; ++
i) {
256 double startVal = defaultStartValue;
258 cout<<parName<< endl;
266 if (!minimizer->SetVariable(i, parName, startVal, defaultMinStep))
269 cout <<
" Read start value 0 for parameter " << parName <<
". Setting default start value." << endl;
270 startVal = defaultStartValue;
272 cout <<
" Setting parameter [" << setw(3) << i <<
"] "
273 << setw(maxParNameLength) << parName <<
" = " << maxPrecisionAlign(startVal) << endl;
275 if (!minimizer->SetFixedVariable(i, parName, 0.))
277 cout <<
" Fixing parameter [" << setw(3) << i <<
"] "
278 << setw(maxParNameLength) << parName <<
" = 0" << endl;
279 parIsFixed[
i] =
true;
282 printErr <<
"Something went wrong when setting minimizer parameters. Exiting." << endl;
288 startValFile->Close();
295 printInfo <<
"Performing minimization." << endl;
302 minimizer->SetMaxIterations(maxNmbOfIterations);
303 success = minimizer->Minimize();
305 printWarn <<
"Minimization failed for mass bin " << binCenter << endl;
307 printInfo <<
"Calculating Hessian matrix." << endl;
310 printWarn <<
"Calculation of Hessian matrix failed." << endl;
312 cout <<
"Minimization stopped after " << minimizer->NCalls() <<
" function calls." << endl
313 <<
" Total number of mimimzer parameters ................. " << minimizer->NDim() << endl
314 <<
" Number of free minimzer parameters .................. " << minimizer->NFree() << endl
315 <<
" Maximum allowed number of iterations ................ " << minimizer->MaxIterations() << endl
316 <<
" Maximum allowed number of function calls ............ " << minimizer->MaxFunctionCalls() << endl
317 <<
" Minimizer status .................................... " << minimizer->Status() << endl
318 <<
" Minimizer provides error and error matrix ........... " << minimizer->ProvidesError() << endl
319 <<
" Minimizer has performed detailed error validation ... " << minimizer->IsValidError() << endl
320 <<
" Estimated Distance to Minimum ....................... " << minimizer->Edm() << endl
321 <<
" Statistical scale used for error calculation ........ " << minimizer->ErrorDef() << endl
322 <<
" Minimizer strategy .................................. " << minimizer->Strategy() << endl
323 <<
" Absolute tolerance .................................. " << minimizer->Tolerance() << endl;
327 printInfo <<
"Minimization result:" << endl;
329 for (
unsigned int i = 0;
i< nmbPar; ++
i) {
331 cout <<
" Parameter [" << setw(3) <<
i <<
"] "
332 << setw(maxParNameLength) << L.
parname(
i) <<
" = ";
334 cout << minimizer->X()[
i] <<
" (fixed)" << endl;
336 cout << setw(12) << maxPrecisionAlign(minimizer->X()[
i]) <<
" +- "
337 << setw(12) << maxPrecisionAlign(minimizer->Errors()[
i]);
338 if (runMinos && (i == 156)) {
339 double minosErrLow = 0;
340 double minosErrUp = 0;
341 success = minimizer->GetMinosError(i, minosErrLow, minosErrUp);
343 cout <<
" Minos: " <<
"[" << minosErrLow <<
", +" << minosErrUp <<
"]" << endl;
348 cout <<
"Number of calls to likelihood function FdF() ... " << L.
ncalls() << endl
349 <<
"Total time spent for likelihood calculation .... " << L.
Ltime() << endl
350 <<
"Total time spent for normalization ............. " << L.
Ntime() << endl;
376 printInfo <<
"Writing result to '" << outFileName <<
"'." << endl;
379 TFile* outFile =
new TFile(outFileName,
"UPDATE");
380 if (!outFile || outFile->IsZombie())
381 printWarn <<
"Cannot open output file '" << outFileName <<
"'. No results will be written." << endl;
386 outFile->GetObject(valTreeName, tree);
388 printInfo <<
"File '" << outFileName <<
"' is empty. Creating new tree for PWA result." << endl;
389 tree =
new TTree(valTreeName, valTreeName);
390 tree->Branch(valBranchName, &result);
392 tree->SetBranchAddress(valBranchName, &result);
395 vector<TComplex> prodAmplitudes;
396 vector<pair<int,int> > indices;
397 vector<TString> waveNames;
398 vector<complex<double> > V;
399 vector<string> names;
402 TMatrixD errMatrix(nmbPar, nmbPar);
403 for(
unsigned int i = 0;
i < nmbPar; ++
i){
404 for(
unsigned int j = 0; j < nmbPar; ++j) {
405 errMatrix[
i][j] = minimizer->CovMatrix(
i,j);
409 TMatrixD covMatrix(2,2);
414 L.
buildCAmps(minimizer->X(), V, indices, names, errMatrix,covMatrix,
true);
417 for (
unsigned int i = 0;
i < V.size(); ++
i)
418 prodAmplitudes.push_back(TComplex(V[
i].real(), V[
i].imag()));
419 assert(indices.size() == prodAmplitudes.size());
420 for(
unsigned int i = 0;
i < names.size(); ++
i)
421 waveNames.push_back(TString(names[
i].c_str()));
423 vector<TString> waveTitles;
425 const vector<string>& titles = L.
wavetitles();
426 for(
unsigned int i = 0;
i < titles.size(); ++
i)
427 waveTitles.push_back(TString(titles[
i].c_str()));
428 waveTitles.push_back(
"flat");
434 cout <<
" Setup integrals" << endl;
435 unsigned int n = waveTitles.size();
443 int nmbEvt = useNorm ? 1 : L.
nevents();
445 cout <<
"Filling TFitBin:" << endl;
446 cout <<
" Number of fit parameters ........... " << nmbPar << endl;
447 cout <<
" Number of production amplitudes .... " << prodAmplitudes.size() << endl;
448 cout <<
" Number of indices .................. " << indices.size() << endl;
449 cout <<
" Number of wave names (with rank) ... " << waveNames.size() << endl;
450 cout <<
" Number of wave titles (w/o rank) ... " << waveTitles.size() << endl;
451 cout <<
" Dimension of error matrix .......... " << errMatrix.GetNrows() << endl;
452 cout <<
" Dimension of integral matrix ....... " << integralMatrix.
nrows() << endl;
453 cout <<
" Dimension of acceptance matrix ..... " << accMatrix.
nrows() << endl;
454 result->
fill(prodAmplitudes,
462 minimizer->MinValue(),
467 TString binName = valBranchName;
468 binName += binLowMass;
470 binName += binHighMass;
471 binName.ReplaceAll(
" ",
"");
473 tree->Write(
"", TObject::kOverwrite);
485 int mnparm(
int,
string,
double,
double,
double,
double)
487 printErr <<
"this is impossible" << endl;