| 1 | /* ======================================================================== *\ | 
|---|
| 2 | ! | 
|---|
| 3 | ! * | 
|---|
| 4 | ! * This file is part of MARS, the MAGIC Analysis and Reconstruction | 
|---|
| 5 | ! * Software. It is distributed to you in the hope that it can be a useful | 
|---|
| 6 | ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. | 
|---|
| 7 | ! * It is distributed WITHOUT ANY WARRANTY. | 
|---|
| 8 | ! * | 
|---|
| 9 | ! * Permission to use, copy, modify and distribute this software and its | 
|---|
| 10 | ! * documentation for any purpose is hereby granted without fee, | 
|---|
| 11 | ! * provided that the above copyright notice appear in all copies and | 
|---|
| 12 | ! * that both that copyright notice and this permission notice appear | 
|---|
| 13 | ! * in supporting documentation. It is provided "as is" without express | 
|---|
| 14 | ! * or implied warranty. | 
|---|
| 15 | ! * | 
|---|
| 16 | ! | 
|---|
| 17 | ! | 
|---|
| 18 | !   Author(s): Wolfgang Wittek 7/2003 <mailto:wittek@mppmu.mpg.de> | 
|---|
| 19 | ! | 
|---|
| 20 | !   Copyright: MAGIC Software Development, 2000-2003 | 
|---|
| 21 | ! | 
|---|
| 22 | ! | 
|---|
| 23 | \* ======================================================================== */ | 
|---|
| 24 |  | 
|---|
| 25 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
| 26 | //                                                                         // | 
|---|
| 27 | // MMinuitInterface                                                        // | 
|---|
| 28 | //                                                                         // | 
|---|
| 29 | // Class for interfacing with Minuit                                       // | 
|---|
| 30 | //                                                                         // | 
|---|
| 31 | //                                                                         // | 
|---|
| 32 | //                                                                         // | 
|---|
| 33 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
| 34 | #include "MMinuitInterface.h" | 
|---|
| 35 |  | 
|---|
| 36 | #include <math.h>            // fabs | 
|---|
| 37 |  | 
|---|
| 38 | #include <TMinuit.h> | 
|---|
| 39 | #include <TStopwatch.h> | 
|---|
| 40 |  | 
|---|
| 41 | #include "MLog.h" | 
|---|
| 42 | #include "MLogManip.h" | 
|---|
| 43 | #include "MParContainer.h" | 
|---|
| 44 |  | 
|---|
| 45 |  | 
|---|
| 46 | ClassImp(MMinuitInterface); | 
|---|
| 47 |  | 
|---|
| 48 | using namespace std; | 
|---|
| 49 |  | 
|---|
| 50 |  | 
|---|
| 51 | // -------------------------------------------------------------------------- | 
|---|
| 52 | // | 
|---|
| 53 | // Default constructor. | 
|---|
| 54 | // | 
|---|
| 55 | MMinuitInterface::MMinuitInterface(const char *name, const char *title) | 
|---|
| 56 | { | 
|---|
| 57 | fName  = name  ? name  : "MMinuitInterface"; | 
|---|
| 58 | fTitle = title ? title : "Interface for Minuit"; | 
|---|
| 59 |  | 
|---|
| 60 | } | 
|---|
| 61 |  | 
|---|
| 62 | // -------------------------------------------------------------------------- | 
|---|
| 63 | // | 
|---|
| 64 | // Default destructor. | 
|---|
| 65 | // | 
|---|
| 66 | MMinuitInterface::~MMinuitInterface() | 
|---|
| 67 | { | 
|---|
| 68 | } | 
|---|
| 69 |  | 
|---|
| 70 |  | 
|---|
| 71 | // ----------------------------------------------------------------------- | 
|---|
| 72 | // | 
|---|
| 73 | // Interface to MINUIT | 
|---|
| 74 | // | 
|---|
| 75 | // | 
|---|
| 76 | Bool_t MMinuitInterface::CallMinuit( | 
|---|
| 77 | void (*fcn)(Int_t &, Double_t *, Double_t &, Double_t *, Int_t), | 
|---|
| 78 | UInt_t npar, char name[80][100], | 
|---|
| 79 | Double_t vinit[80], Double_t step[80], | 
|---|
| 80 | Double_t limlo[80], Double_t limup[80], Int_t fix[80], | 
|---|
| 81 | TObject *objectfit , TString method, Bool_t nulloutput) | 
|---|
| 82 | { | 
|---|
| 83 | TString str(method); | 
|---|
| 84 |  | 
|---|
| 85 | // | 
|---|
| 86 | // Be carefull: This is not thread safe | 
|---|
| 87 | // | 
|---|
| 88 | UInt_t maxpar = 100; | 
|---|
| 89 |  | 
|---|
| 90 | if (npar > maxpar) | 
|---|
| 91 | { | 
|---|
| 92 | *fLog << "CallMinuit : too many parameters,  npar = " << npar | 
|---|
| 93 | << ",   maxpar = " << maxpar << endl; | 
|---|
| 94 | return kFALSE; | 
|---|
| 95 | } | 
|---|
| 96 |  | 
|---|
| 97 |  | 
|---|
| 98 |  | 
|---|
| 99 | //.............................................. | 
|---|
| 100 | // Set the maximum number of parameters | 
|---|
| 101 | TMinuit &minuit = *(new TMinuit(maxpar)); | 
|---|
| 102 | minuit.SetName("MinuitSupercuts"); | 
|---|
| 103 | //TMinuit minuit(maxpar); | 
|---|
| 104 | //gMinuit = new TMinuit(maxpar); | 
|---|
| 105 | //TMinuit &minuit = *gMinuit; | 
|---|
| 106 |  | 
|---|
| 107 |  | 
|---|
| 108 | //.............................................. | 
|---|
| 109 | // Set the print level | 
|---|
| 110 | // -1   no output except SHOW comands | 
|---|
| 111 | //  0   minimum output | 
|---|
| 112 | //  1   normal output (default) | 
|---|
| 113 | //  2   additional ouput giving intermediate results | 
|---|
| 114 | //  3   maximum output, showing progress of minimizations | 
|---|
| 115 | // | 
|---|
| 116 | //Int_t printLevel = -1; | 
|---|
| 117 | Int_t printLevel = 1; | 
|---|
| 118 | minuit.SetPrintLevel(printLevel); | 
|---|
| 119 |  | 
|---|
| 120 | //.............................................. | 
|---|
| 121 | // Printout for warnings | 
|---|
| 122 | //    SET WAR      print warnings | 
|---|
| 123 | //    SET NOW      suppress warnings | 
|---|
| 124 | Int_t errWarn; | 
|---|
| 125 | Double_t tmpwar = 0; | 
|---|
| 126 | minuit.mnexcm("SET NOW", &tmpwar, 0, errWarn); | 
|---|
| 127 | //minuit.mnexcm("SET WAR", &tmpwar, 0, errWarn); | 
|---|
| 128 |  | 
|---|
| 129 | //.............................................. | 
|---|
| 130 | // Set the address of the minimization function | 
|---|
| 131 | minuit.SetFCN(fcn); | 
|---|
| 132 |  | 
|---|
| 133 |  | 
|---|
| 134 | //.............................................. | 
|---|
| 135 | // Store address of object to be used in fcn | 
|---|
| 136 | minuit.SetObjectFit(objectfit ); | 
|---|
| 137 |  | 
|---|
| 138 |  | 
|---|
| 139 | //.............................................. | 
|---|
| 140 | // Set starting values and step sizes for parameters | 
|---|
| 141 | for (UInt_t i=0; i<npar; i++) | 
|---|
| 142 | { | 
|---|
| 143 | if (minuit.DefineParameter(i, &name[i][0], vinit[i], step[i], | 
|---|
| 144 | limlo[i], limup[i])) | 
|---|
| 145 | { | 
|---|
| 146 | *fLog << "CallMinuit: Error in defining parameter " | 
|---|
| 147 | << name[i][0] << endl; | 
|---|
| 148 | return kFALSE; | 
|---|
| 149 | } | 
|---|
| 150 | } | 
|---|
| 151 |  | 
|---|
| 152 | //.............................................. | 
|---|
| 153 | //Int_t NumPars; | 
|---|
| 154 | //NumPars = minuit.GetNumPars(); | 
|---|
| 155 | //*fLog << "CallMinuit :  number of free parameters = " | 
|---|
| 156 | //     << NumPars << endl; | 
|---|
| 157 |  | 
|---|
| 158 |  | 
|---|
| 159 | //.............................................. | 
|---|
| 160 | // Error definition : | 
|---|
| 161 | // | 
|---|
| 162 | //    for chisquare function : | 
|---|
| 163 | //      up = 1.0   means calculate 1-standard deviation error | 
|---|
| 164 | //         = 4.0   means calculate 2-standard deviation error | 
|---|
| 165 | // | 
|---|
| 166 | //    for log(likelihood) function : | 
|---|
| 167 | //      up = 0.5   means calculate 1-standard deviation error | 
|---|
| 168 | //         = 2.0   means calculate 2-standard deviation error | 
|---|
| 169 | Double_t up = 1.0; | 
|---|
| 170 | minuit.SetErrorDef(up); | 
|---|
| 171 |  | 
|---|
| 172 |  | 
|---|
| 173 |  | 
|---|
| 174 | // Int_t errMigrad; | 
|---|
| 175 | // Double_t tmp = 0; | 
|---|
| 176 | // minuit.mnexcm("MIGRAD", &tmp, 0, errMigrad); | 
|---|
| 177 |  | 
|---|
| 178 |  | 
|---|
| 179 | //.............................................. | 
|---|
| 180 | // fix a parameter | 
|---|
| 181 | for (UInt_t i=0; i<npar; i++) | 
|---|
| 182 | { | 
|---|
| 183 | if (fix[i] > 0) | 
|---|
| 184 | { | 
|---|
| 185 | Int_t parNo = i; | 
|---|
| 186 | minuit.FixParameter(parNo); | 
|---|
| 187 | step[parNo] = 0.0; | 
|---|
| 188 | } | 
|---|
| 189 | } | 
|---|
| 190 |  | 
|---|
| 191 | //.............................................. | 
|---|
| 192 | //NumPars = minuit.GetNumPars(); | 
|---|
| 193 | //*fLog << "CallMinuit :  number of free parameters = " | 
|---|
| 194 | //     << NumPars << endl; | 
|---|
| 195 |  | 
|---|
| 196 | //.............................................. | 
|---|
| 197 | // Set maximum number of iterations (default = 500) | 
|---|
| 198 | //Int_t maxiter = 100000; | 
|---|
| 199 | Int_t maxiter = 10; | 
|---|
| 200 | minuit.SetMaxIterations(maxiter); | 
|---|
| 201 |  | 
|---|
| 202 | //.............................................. | 
|---|
| 203 | // minimization by the method of Migrad | 
|---|
| 204 | if (str.Contains("Migrad", TString::kIgnoreCase)) | 
|---|
| 205 | { | 
|---|
| 206 | //*fLog << "call MIGRAD" << endl; | 
|---|
| 207 | if (nulloutput) | 
|---|
| 208 | fLog->SetNullOutput(kTRUE); | 
|---|
| 209 | Double_t tmp = 0; | 
|---|
| 210 | minuit.mnexcm("MIGRAD", &tmp, 0, fErrMinimize); | 
|---|
| 211 | if (nulloutput) | 
|---|
| 212 | fLog->SetNullOutput(kFALSE); | 
|---|
| 213 | //*fLog << "return from MIGRAD" << endl; | 
|---|
| 214 | } | 
|---|
| 215 |  | 
|---|
| 216 | //.............................................. | 
|---|
| 217 | // same minimization as by Migrad | 
|---|
| 218 | // but switches to the SIMPLEX method if MIGRAD fails to converge | 
|---|
| 219 | if (str.Contains("Minimize", TString::kIgnoreCase)) | 
|---|
| 220 | { | 
|---|
| 221 | *fLog << "call MINIMIZE" << endl; | 
|---|
| 222 | Double_t tmp = 0; | 
|---|
| 223 | minuit.mnexcm("MINIMIZE", &tmp, 0, fErrMinimize); | 
|---|
| 224 | *fLog << "return from MINIMIZE" << endl; | 
|---|
| 225 | } | 
|---|
| 226 |  | 
|---|
| 227 | //.............................................. | 
|---|
| 228 | // minimization by the SIMPLEX method | 
|---|
| 229 | if (str.Contains("Simplex", TString::kIgnoreCase)) | 
|---|
| 230 | { | 
|---|
| 231 | *fLog << "call SIMPLEX" << endl; | 
|---|
| 232 | if (nulloutput) | 
|---|
| 233 | fLog->SetNullOutput(kTRUE); | 
|---|
| 234 | Double_t tmp = 0; | 
|---|
| 235 | minuit.mnexcm("SIMPLEX", &tmp, 0, fErrMinimize); | 
|---|
| 236 | if (nulloutput) | 
|---|
| 237 | fLog->SetNullOutput(kFALSE); | 
|---|
| 238 | //*fLog << "return from SIMPLEX" << endl; | 
|---|
| 239 | } | 
|---|
| 240 |  | 
|---|
| 241 | //.............................................. | 
|---|
| 242 | // check quality of minimization | 
|---|
| 243 | // istat = 0   covariance matrix not calculated | 
|---|
| 244 | //         1   diagonal approximation only (not accurate) | 
|---|
| 245 | //         2   full matrix, but forced positive-definite | 
|---|
| 246 | //         3   full accurate covariance matrix | 
|---|
| 247 | //             (indication of normal convergence) | 
|---|
| 248 | minuit.mnstat(fMin, fEdm, fErrdef, fNpari, fNparx, fIstat); | 
|---|
| 249 |  | 
|---|
| 250 | //if (fErrMinimize != 0  ||  fIstat < 3) | 
|---|
| 251 | if (fErrMinimize != 0) | 
|---|
| 252 | { | 
|---|
| 253 | *fLog << "CallMinuit : Minimization failed" << endl; | 
|---|
| 254 | *fLog << "       fMin = " << fMin   << ",   fEdm = "  << fEdm | 
|---|
| 255 | << ",   fErrdef = "  << fErrdef << ",   fIstat = " << fIstat | 
|---|
| 256 | << ",   fErrMinimize = " << fErrMinimize << endl; | 
|---|
| 257 | return kFALSE; | 
|---|
| 258 | } | 
|---|
| 259 |  | 
|---|
| 260 | //*fLog << "CallMinuit : Minimization was successful" << endl; | 
|---|
| 261 | //*fLog << "       fMin = " << fMin   << ",   fEdm = "  << fEdm | 
|---|
| 262 | //     << ",   fErrdef = "  << fErrdef << ",   fIstat = " << fIstat | 
|---|
| 263 | //     << ",   fErrMinimize = " << fErrMinimize << endl; | 
|---|
| 264 |  | 
|---|
| 265 |  | 
|---|
| 266 | //.............................................. | 
|---|
| 267 | // minimization by the method of Migrad | 
|---|
| 268 | if (str.Contains("Hesse", TString::kIgnoreCase)) | 
|---|
| 269 | { | 
|---|
| 270 | //*fLog << "call HESSE" << endl; | 
|---|
| 271 | Double_t tmp = 0; | 
|---|
| 272 | minuit.mnexcm("HESSE", &tmp, 0, fErrMinimize); | 
|---|
| 273 | //*fLog << "return from HESSE" << endl; | 
|---|
| 274 | } | 
|---|
| 275 |  | 
|---|
| 276 | //.............................................. | 
|---|
| 277 | // Minos error analysis | 
|---|
| 278 | if (str.Contains("Minos", TString::kIgnoreCase)) | 
|---|
| 279 | { | 
|---|
| 280 | //*fLog << "call MINOS" << endl; | 
|---|
| 281 | Double_t tmp = 0; | 
|---|
| 282 | minuit.mnexcm("MINOS", &tmp, 0, fErrMinimize); | 
|---|
| 283 | //*fLog << "return from MINOS" << endl; | 
|---|
| 284 | } | 
|---|
| 285 |  | 
|---|
| 286 | //.............................................. | 
|---|
| 287 | // Print current status of minimization | 
|---|
| 288 | // if nkode = 0    only function value | 
|---|
| 289 | //            1    parameter values, errors, limits | 
|---|
| 290 | //            2    values, errors, step sizes, internal values | 
|---|
| 291 | //            3    values, errors, step sizes, 1st derivatives | 
|---|
| 292 | //            4    values, paraboloc errors, MINOS errors | 
|---|
| 293 |  | 
|---|
| 294 | //Int_t nkode = 4; | 
|---|
| 295 | //minuit.mnprin(nkode, fmin); | 
|---|
| 296 |  | 
|---|
| 297 | //.............................................. | 
|---|
| 298 | // call fcn with IFLAG = 3 (final calculation : calculate p(chi2)) | 
|---|
| 299 | // iflag = 1   initial calculations only | 
|---|
| 300 | //         2   calculate 1st derivatives and function | 
|---|
| 301 | //         3   calculate function only | 
|---|
| 302 | //         4   calculate function + final calculations | 
|---|
| 303 | const char *command = "CALL"; | 
|---|
| 304 | Double_t iflag = 3; | 
|---|
| 305 | Int_t errfcn3; | 
|---|
| 306 | minuit.mnexcm(command, &iflag, 1, errfcn3); | 
|---|
| 307 |  | 
|---|
| 308 | //*fLog << "Exit CallMinuit" << endl; | 
|---|
| 309 |  | 
|---|
| 310 | return kTRUE; | 
|---|
| 311 | } | 
|---|
| 312 |  | 
|---|
| 313 |  | 
|---|
| 314 | //=========================================================================== | 
|---|
| 315 |  | 
|---|
| 316 |  | 
|---|
| 317 |  | 
|---|
| 318 |  | 
|---|
| 319 |  | 
|---|
| 320 |  | 
|---|
| 321 |  | 
|---|
| 322 |  | 
|---|
| 323 |  | 
|---|
| 324 |  | 
|---|
| 325 |  | 
|---|