00001 #include "TCanvas.h"
00002 #include "TFile.h"
00003 #include "TGraph.h"
00004 #include "TAxis.h"
00005 #include "TH2.h"
00006
00007 #include "Minuit2/ContoursError.h"
00008 #include "Minuit2/MnContours.h"
00009 #include "Minuit2/MnMigrad.h"
00010 #include "Minuit2/MnUserParameters.h"
00011 #include "Minuit2/FunctionMinimum.h"
00012
00013 #include "MessageService/MsgService.h"
00014 #include "NtupleUtils/NuMMRunPRL.h"
00015 #include "NtupleUtils/NuMMHelperPRL.h"
00016 #include "NtupleUtils/NuMMParameters.h"
00017 #include "NtupleUtils/NuSystFitter.h"
00018 #include "NtupleUtils/NuFCFitter.h"
00019 #include "NtupleUtils/NuUtilities.h"
00020
00021 ClassImp(NuSystFitter)
00022
00023 CVSID("$Id: NuSystFitter.cxx,v 1.47 2010/01/11 10:55:38 nickd Exp $");
00024
00025
00026 NuSystFitter::NuSystFitter()
00027 : fQuietMode(false),
00028 fUp(1.0),
00029 fNumContourPoints(80),
00030 fsn2PointsForNeutrinoContour(),
00031 fsn2PointsForNeutrinoContourPhysical(),
00032 fsn2PointsForNeutrinoContourUnphysical()
00033 {
00034 fRuns = new vector<NuMMRun*>();
00035
00036 for (Double_t sn2 = 1.0; sn2 > 0.871; sn2 -= 0.02){
00037 fsn2PointsForNeutrinoContourPhysical.push_back(sn2);
00038 }
00039 fsn2PointsForNeutrinoContourPhysical.push_back(0.87);
00040 fsn2PointsForNeutrinoContourPhysical.push_back(0.86);
00041 for (Double_t sn2 = 0.8595; sn2 > 0.7999; sn2 -= 0.0005){
00042 fsn2PointsForNeutrinoContourPhysical.push_back(sn2);
00043 }
00044
00045 for (Double_t sn2 = 1.0; sn2 < 3; sn2 += 0.02){
00046 fsn2PointsForNeutrinoContourUnphysical.push_back(sn2);
00047 }
00048
00049 fsn2PointsForNeutrinoContour = fsn2PointsForNeutrinoContourPhysical;
00050 }
00051
00052
00053 NuSystFitter::~NuSystFitter()
00054 {
00055 }
00056
00057
00058 void NuSystFitter::push_back(NuMMRun* run)
00059 {
00060 fRuns->push_back(run);
00061 }
00062
00063 void NuSystFitter::Setup(const std::vector<string> helperInputs,
00064 const std::vector<NuHistInterpolator*> fdDataInput,
00065 const std::vector<NuHistInterpolator*> ndDataInput,
00066 const std::string xsecFile,
00067 const std::vector<string> ,
00068 const std::string ,
00069 Int_t )
00070 {
00071 vector<NuHistInterpolator*>::const_iterator fdDataIt = fdDataInput.begin();
00072 vector<NuHistInterpolator*>::const_iterator ndDataIt = ndDataInput.begin();
00073 for (vector<string>::const_iterator helperIt = helperInputs.begin();
00074 helperIt != helperInputs.end();
00075 ++helperIt,++ndDataIt,++fdDataIt){
00076 NuMMHelperPRL* mmHelper = new NuMMHelperPRL(*helperIt,xsecFile);
00077 NuMMRun* mmRun = new NuMMRunPRL(mmHelper,*ndDataIt,*fdDataIt);
00078 this->push_back(mmRun);
00079 }
00080 }
00081
00082
00083 void NuSystFitter::NoOscPrediction()
00084 {
00085
00086 }
00087
00088
00089 const NuMMParameters NuSystFitter::Minimise(const NuMMParameters& mmPars)
00090 {
00091
00092
00093 ROOT::Minuit2::MnUserParameters mnPars = mmPars.MinuitParameters();
00094 vector<double> param_vec = mnPars.Params();
00095
00096
00097 if (!fQuietMode) mmPars.PrintStatus();
00098
00099
00100 ROOT::Minuit2::MnMigrad mnMigrad(*this,mnPars);
00101 ROOT::Minuit2::FunctionMinimum funcMin = mnMigrad();
00102
00103 Bool_t didpass = false;
00104
00105 if (!funcMin.IsValid()){
00106 cout << "Function minimum is not valid!" << endl;
00107 }
00108 else{
00109 didpass = true;
00110 if (!fQuietMode){
00111 cout << "Function minimum is: " << endl
00112 << "Sn2: " << funcMin.UserParameters().Parameter(1).Value()
00113 << ", dm2: " << funcMin.UserParameters().Parameter(0).Value()
00114 << "; norm: " << funcMin.UserParameters().Parameter(2).Value()
00115 << "; shwEn: " << funcMin.UserParameters().Parameter(3).Value()
00116 << "; NCBack: " << funcMin.UserParameters().Parameter(4).Value()
00117 << "; Sn2bar: " << funcMin.UserParameters().Parameter(6).Value()
00118 << "; dm2bar: " << funcMin.UserParameters().Parameter(5).Value()
00119 << endl;
00120 }
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 NuMMParameters bestFitPars(funcMin);
00130 bestFitPars.MinuitPass(didpass);
00131
00132 return bestFitPars;
00133
00134 }
00135
00136
00137 const NuMMParameters NuSystFitter::Minimise(const NuMMParameters& mmPars, bool &success)
00138 {
00139
00140
00141 ROOT::Minuit2::MnUserParameters mnPars = mmPars.MinuitParameters();
00142
00143
00144 ROOT::Minuit2::MnMigrad mnMigrad(*this,mnPars);
00145 ROOT::Minuit2::FunctionMinimum funcMin = mnMigrad();
00146
00147 if (!funcMin.IsValid()){
00148 cout << "Function minimum is not valid!" << endl;
00149 }
00150 else{
00151 if (!fQuietMode){
00152 cout << "Function minimum is: " << endl
00153 << "Sn2: " << funcMin.UserParameters().Parameter(1).Value()
00154 << ", dm2: " << funcMin.UserParameters().Parameter(0).Value()
00155 << "; norm: " << funcMin.UserParameters().Parameter(2).Value()
00156 << "; shwEn: " << funcMin.UserParameters().Parameter(3).Value()
00157 << "; NCBack: " << funcMin.UserParameters().Parameter(4).Value()
00158 << "; Sn2bar: " << funcMin.UserParameters().Parameter(6).Value()
00159 << "; dm2bar: " << funcMin.UserParameters().Parameter(5).Value()
00160 << endl;
00161 }
00162 }
00163
00164
00165
00166
00167
00168
00169
00170 success = funcMin.IsValid();
00171 NuMMParameters bestFitPars(funcMin);
00172 return bestFitPars;
00173
00174 }
00175
00176
00177 const TGraph* NuSystFitter::PlotContours(const NuMMParameters& mmPars)
00178 {
00179
00180
00181
00182 ROOT::Minuit2::MnUserParameters mnPars = mmPars.MinuitParameters();
00183
00184
00185 ROOT::Minuit2::MnMigrad mnMigrad(*this,mnPars);
00186 ROOT::Minuit2::FunctionMinimum funcMin = mnMigrad();
00187
00188 if (!funcMin.IsValid()){
00189 cout << "Function minimum is not valid!" << endl;
00190 }
00191 else{
00192 cout << "Contour Minimization: " << endl;
00193 cout << "Function minimum is: " << endl
00194 << "Sn2: " << funcMin.UserParameters().Parameter(1).Value()
00195 << ", dm2: " << funcMin.UserParameters().Parameter(0).Value()
00196 << "; norm: " << funcMin.UserParameters().Parameter(2).Value()
00197 << "; shwEn: " << funcMin.UserParameters().Parameter(3).Value()
00198 << "; NCBack: " << funcMin.UserParameters().Parameter(4).Value()
00199 << "; Sn2bar: " << funcMin.UserParameters().Parameter(6).Value()
00200 << "; dm2bar: " << funcMin.UserParameters().Parameter(5).Value()
00201 << endl;
00202 }
00203
00204 ROOT::Minuit2::MnContours contours(*this,funcMin);
00205 ROOT::Minuit2::ContoursError contErr = contours.Contour(mmPars.ContourPars().first,
00206 mmPars.ContourPars().second,
00207 fNumContourPoints);
00208
00209 std::vector<std::pair<Double_t,Double_t> > vContPoints = contErr();
00210
00211
00212 Double_t* x = new Double_t[vContPoints.size()];
00213 for (UInt_t pointCount = 0; pointCount<vContPoints.size(); ++pointCount){
00214 x[pointCount] = vContPoints[pointCount].first;
00215 }
00216
00217 Double_t* y = new Double_t[vContPoints.size()];
00218 for (UInt_t pointCount = 0; pointCount<vContPoints.size(); ++pointCount){
00219 y[pointCount] = vContPoints[pointCount].second;
00220 }
00221 TGraph* gCont = new TGraph(vContPoints.size(),y,x);
00222
00223
00224
00225
00226
00227
00228
00229 return gCont;
00230 }
00231
00232
00233 const TGraph* NuSystFitter
00234 ::OneSidedNeutrinoContourFinder(const NuMMParameters& inputPars)
00235 {
00236 std::vector<std::pair<Double_t,Double_t> > contPoints =
00237 this->NeutrinoContourFinder(inputPars);
00238
00239
00240 TGraph* contour = new TGraph(contPoints.size());
00241 Int_t point=0;
00242 for (vector<pair<Double_t, Double_t> >::const_iterator it =
00243 contPoints.begin();
00244 it != contPoints.end();
00245 ++it){
00246 contour->SetPoint(point,(*it).first,(*it).second);
00247 cout << "Set contour point " << point
00248 << ", " << (*it).first
00249 << ", " << (*it).second
00250 << endl;
00251 ++point;
00252 }
00253 return contour;
00254 }
00255
00256
00257 const TGraph* NuSystFitter
00258 ::TwoSidedNeutrinoContourFinder(const NuMMParameters& inputPars)
00259 {
00260 fsn2PointsForNeutrinoContour = fsn2PointsForNeutrinoContourPhysical;
00261 std::vector<std::pair<Double_t,Double_t> > contPointsPhys =
00262 this->NeutrinoContourFinder(inputPars);
00263
00264 fsn2PointsForNeutrinoContour = fsn2PointsForNeutrinoContourUnphysical;
00265 std::vector<std::pair<Double_t,Double_t> > contPointsUnphys =
00266 this->NeutrinoContourFinder(inputPars);
00267
00268
00269 std::vector<pair<Double_t,Double_t> > contourPoints;
00270 for (vector<pair<Double_t, Double_t> >::const_iterator it =
00271 contPointsPhys.begin();
00272 it != contPointsPhys.end();
00273 ++it){
00274 pair<Double_t,Double_t> currentPoint((*it).first,(*it).second);
00275 contourPoints.push_back(currentPoint);
00276 }
00277 for (vector<pair<Double_t, Double_t> >::reverse_iterator
00278 itr = contPointsUnphys.rbegin();
00279 itr != contPointsUnphys.rend();
00280 ++itr){
00281 pair<Double_t,Double_t> currentPoint((*itr).first,(*itr).second);
00282 contourPoints.push_back(currentPoint);
00283 }
00284
00285
00286
00287 TGraph* contour = new TGraph(contourPoints.size());
00288 Int_t point=0;
00289 for (vector<pair<Double_t, Double_t> >::const_iterator it =
00290 contourPoints.begin();
00291 it != contourPoints.end();
00292 ++it){
00293 contour->SetPoint(point,(*it).first,(*it).second);
00294 cout << "Set contour point " << point
00295 << ", " << (*it).first
00296 << ", " << (*it).second
00297 << endl;
00298 ++point;
00299 }
00300 return contour;
00301 }
00302
00303
00304 const std::vector<std::pair<Double_t,Double_t> > NuSystFitter
00305 ::NeutrinoContourFinder(const NuMMParameters& inputPars)
00306 {
00307
00308 NuMMParameters bestFitPars = this->Minimise(inputPars);
00309 Double_t bestFitChi2 = (*this)(bestFitPars.VectorParameters());
00310 Double_t targetChi2 = bestFitChi2 + this->Up();
00311 cout << "Target chi2 = " << targetChi2 << endl;
00312
00313
00314 NuMMParameters mmPars = inputPars;
00315 mmPars.FixSn2();
00316
00317 std::vector<pair<Double_t,Double_t> > pointsUp;
00318 std::vector<pair<Double_t,Double_t> > pointsDown;
00319
00320
00321 this->QuietModeOn();
00322
00323
00324 for (vector<Double_t>::iterator snIt = fsn2PointsForNeutrinoContour.begin();
00325 snIt != fsn2PointsForNeutrinoContour.end();
00326 ++snIt){
00327 Double_t sn2 = *snIt;
00328 mmPars.Sn2(sn2);
00329 const std::pair<Double_t, Double_t> values =
00330 this->DmScanForContour(mmPars,targetChi2);
00331 cout << "Contour points: sn2 = " << sn2
00332 << "; dm2 = " << values.first << " and " << values.second
00333 << endl;
00334 if ((values.first < 0.0) || (values.second < 0.0)){
00335 cout << "End of contour at sn2 = " << mmPars.Sn2() << endl;
00336 break;
00337 }
00338 else{
00339 pair<Double_t, Double_t> pointDown(sn2,values.first);
00340 pair<Double_t, Double_t> pointUp(sn2,values.second);
00341 pointsDown.push_back(pointDown);
00342 pointsUp.push_back(pointUp);
00343 }
00344 }
00345
00346
00347 std::vector<pair<Double_t,Double_t> > contour;
00348 for (vector<pair<Double_t, Double_t> >::const_iterator it = pointsUp.begin();
00349 it != pointsUp.end();
00350 ++it){
00351 pair<Double_t,Double_t> currentPoint((*it).first,(*it).second);
00352 contour.push_back(currentPoint);
00353 }
00354 for (vector<pair<Double_t, Double_t> >::reverse_iterator
00355 itr = pointsDown.rbegin();
00356 itr != pointsDown.rend();
00357 ++itr){
00358 pair<Double_t,Double_t> currentPoint((*itr).first,(*itr).second);
00359 contour.push_back(currentPoint);
00360 }
00361 return contour;
00362 }
00363
00364
00365 const std::pair<Double_t,Double_t> NuSystFitter
00366 ::DmScanForContour(const NuMMParameters& mmPars,
00367 Double_t targetChi2)
00368 {
00369 std::pair<Double_t,Double_t> errors;
00370
00371 NuMMParameters bestFitPoint = this->Minimise(mmPars);
00372 Double_t bestFitChi2 = (*this)(bestFitPoint.VectorParameters());
00373 Double_t bestFitDm2 = bestFitPoint.Dm2();
00374
00375 if (bestFitChi2 > targetChi2){
00376 errors.first = -1.0;
00377 errors.second = -1.0;
00378 return errors;
00379 }
00380
00381 cout << "Best chi2: " << bestFitChi2
00382 << " at dm2 = " << bestFitDm2
00383 << ", sn2 = " << bestFitPoint.Sn2()
00384 << ", norm = " << bestFitPoint.Normalisation()
00385 << ", NC = " << bestFitPoint.NCBackgroundScale()
00386 << ", shwEn = " << bestFitPoint.ShwEnScale()
00387 << endl
00388 << ". Target chi2: " << targetChi2
00389 << endl;
00390
00391 for (Int_t direction = -1; direction < 2; direction += 2){
00392
00393 cout << "Direction = " << direction << endl;
00394
00395 NuMMParameters scanMMPars = mmPars;
00396 scanMMPars.Dm2(bestFitDm2);
00397 scanMMPars.FixDm2();
00398
00399 Double_t incrementArray[9] = {0.1e-3,
00400 0.03e-3,
00401 0.01e-3,
00402 0.003e-3,
00403 0.001e-3,
00404 0.0003e-3,
00405 0.0001e-3,
00406 0.00003e-3,
00407 0.00001e-3};
00408 Double_t firstChi2 = bestFitChi2;
00409 Double_t firstDm2 = bestFitDm2;
00410 Double_t currentChi2 = -1.0;
00411 Double_t lastChi2 = -1.0;
00412 Double_t lastDm2 = -1.0;
00413 for (Int_t incCount = 0; incCount<9; ++incCount){
00414 Double_t increment = incrementArray[incCount];
00415
00416 currentChi2 = firstChi2;
00417 scanMMPars.Dm2(firstDm2);
00418
00419 cout << "Starting while with firstChi2 = " << firstChi2
00420 << ", firstDm2 = " << firstDm2
00421 << ", increment = " << increment
00422 << endl;
00423
00424 while (currentChi2 < targetChi2){
00425 lastChi2 = currentChi2;
00426 lastDm2 = scanMMPars.Dm2();
00427
00428 scanMMPars.Dm2(scanMMPars.Dm2() + direction*increment);
00429 cout << "Trying dm2 = " << scanMMPars.Dm2() << "... ";
00430 flush(cout);
00431 if (scanMMPars.AreAllParametersFixed()){
00432 currentChi2 = (*this)(scanMMPars.VectorParameters());
00433 }
00434 else{
00435 currentChi2 = (*this)(this->Minimise(scanMMPars).VectorParameters());
00436 }
00437 cout << "chi2 = " << currentChi2 << endl;
00438 }
00439
00440 firstDm2 = lastDm2;
00441 firstChi2 = lastChi2;
00442
00443 }
00444
00445 Double_t chi2Difference = lastChi2 - currentChi2;
00446 Double_t dm2Difference = lastDm2 - scanMMPars.Dm2();
00447 Double_t value = -1.0;
00448 cout << "chi2Difference = " << chi2Difference << endl;
00449 cout << "dm2Difference = " << dm2Difference << endl;
00450 if ((fabs(chi2Difference)<1e-12) || (fabs(dm2Difference)<1e-12)){
00451 cout << "Chi2 or Dm2 difference is zero. Supplying currentChi2."
00452 << endl;
00453 value = scanMMPars.Dm2();
00454 }
00455 else{
00456 Double_t fractionBetween = (targetChi2 - currentChi2)/chi2Difference;
00457 value = fractionBetween*dm2Difference + scanMMPars.Dm2();
00458 }
00459 cout << "Error is between " << lastDm2
00460 << " and " << scanMMPars.Dm2()
00461 << ", with chi2 between " << lastChi2
00462 << " and " << currentChi2
00463 << endl;
00464 cout << "Value is " << value << endl;
00465 if (-1 == direction){errors.first = value;}
00466 if (1 == direction){errors.second = value;}
00467 }
00468
00469 cout << "Final answer is dm2 = " << bestFitDm2
00470 << " + " << errors.second - bestFitDm2
00471 << " - " << errors.first - bestFitDm2
00472 << endl;
00473 return errors;
00474 }
00475
00476
00477 const std::pair<Double_t,Double_t> NuSystFitter
00478 ::SingleParDm2Errors(const NuMMParameters& mmPars)
00479 {
00480 std::pair<Double_t,Double_t> errors;
00481
00482 NuMMParameters bestFitPoint = this->Minimise(mmPars);
00483 Double_t bestFitChi2 = (*this)(bestFitPoint.VectorParameters());
00484 Double_t targetChi2 = bestFitChi2 + this->Up();
00485 Double_t bestFitDm2 = bestFitPoint.Dm2();
00486
00487 cout << "Best chi2: " << bestFitChi2
00488 << " at dm2 = " << bestFitDm2
00489 << ". Target chi2: " << targetChi2
00490 << endl;
00491
00492 for (Int_t direction = -1; direction < 2; direction += 2){
00493
00494 cout << "Direction = " << direction << endl;
00495
00496 NuMMParameters scanMMPars = mmPars;
00497 scanMMPars.Dm2(bestFitDm2);
00498 scanMMPars.FixDm2();
00499
00500 Double_t incrementArray[5] = {0.1e-3,
00501 0.01e-3,
00502 0.001e-3,
00503 0.0001e-3,
00504 0.00001e-3};
00505 Double_t firstChi2 = bestFitChi2;
00506 Double_t firstDm2 = bestFitDm2;
00507 Double_t currentChi2 = -1.0;
00508 Double_t lastChi2 = -1.0;
00509 Double_t lastDm2 = -1.0;
00510 for (Int_t incCount = 0; incCount<5; ++incCount){
00511 Double_t increment = incrementArray[incCount];
00512
00513 currentChi2 = firstChi2;
00514 scanMMPars.Dm2(firstDm2);
00515
00516 cout << "Starting while with firstChi2 = " << firstChi2
00517 << ", firstDm2 = " << firstDm2
00518 << ", increment = " << increment
00519 << endl;
00520
00521 while (currentChi2 < targetChi2){
00522 lastChi2 = currentChi2;
00523 lastDm2 = scanMMPars.Dm2();
00524
00525 scanMMPars.Dm2(scanMMPars.Dm2() + direction*increment);
00526 cout << "Trying dm2 = " << scanMMPars.Dm2() << "... ";
00527 if (scanMMPars.AreAllParametersFixed()){
00528 currentChi2 = (*this)(scanMMPars.VectorParameters());
00529 }
00530 else{
00531 currentChi2 = (*this)(this->Minimise(scanMMPars).VectorParameters());
00532 }
00533 cout << "chi2 = " << currentChi2 << endl;
00534 }
00535
00536 firstDm2 = lastDm2;
00537 firstChi2 = lastChi2;
00538
00539 }
00540
00541 Double_t chi2Difference = lastChi2 - currentChi2;
00542 Double_t dm2Difference = lastDm2 - scanMMPars.Dm2();
00543 Double_t value = -1.0;
00544 cout << "chi2Difference = " << chi2Difference << endl;
00545 cout << "dm2Difference = " << dm2Difference << endl;
00546 if ((fabs(chi2Difference)<1e-12) || (fabs(dm2Difference)<1e-12)){
00547 cout << "Chi2 or Dm2 difference is zero. Supplying currentChi2."
00548 << endl;
00549 value = scanMMPars.Dm2();
00550 }
00551 else{
00552 Double_t fractionBetween = (targetChi2 - currentChi2)/chi2Difference;
00553 value = fractionBetween*dm2Difference + scanMMPars.Dm2();
00554 }
00555 cout << "Error is between " << lastDm2
00556 << " and " << scanMMPars.Dm2()
00557 << ", with chi2 between " << lastChi2
00558 << " and " << currentChi2
00559 << endl;
00560 cout << "Value is " << value << endl;
00561 if (-1 == direction){errors.first = value;}
00562 if (1 == direction){errors.second = value;}
00563 }
00564
00565 cout << "Final answer is dm2 = " << bestFitDm2
00566 << " + " << errors.second - bestFitDm2
00567 << " - " << errors.first - bestFitDm2
00568 << endl;
00569 return errors;
00570 }
00571
00572
00573 double NuSystFitter::operator()(const std::vector<double>& pars) const
00574 {
00575 NuMMParameters mmPars(pars);
00576
00577
00578 return Likelihood(mmPars);
00579 }
00580
00581
00582 double NuSystFitter::Likelihood(const NuMMParameters& mmPars) const
00583 {
00584 Double_t likelihood = 0.0;
00585 for (std::vector<NuMMRun*>::iterator runIt = fRuns->begin();
00586 fRuns->end() != runIt;
00587 ++runIt){
00588 likelihood += (*runIt)->ComparePredWithData(mmPars);
00589 }
00590 if (!fQuietMode){
00591 cout << "Stats likelihood: " << likelihood;
00592 }
00593 likelihood += mmPars.PenaltyTerm();
00594 if (!fQuietMode){
00595 cout << " + penalty = " << likelihood << endl;
00596 }
00597
00598 return likelihood;
00599 }
00600
00601
00602 void NuSystFitter::QuietModeOn()
00603 {
00604 fQuietMode = true;
00605 for (std::vector<NuMMRun*>::iterator runIt = fRuns->begin();
00606 fRuns->end() != runIt;
00607 ++runIt){
00608 (*runIt)->QuietModeOn();
00609 }
00610 }
00611
00612
00613 void NuSystFitter::QuietModeOff()
00614 {
00615 fQuietMode = true;
00616 for (std::vector<NuMMRun*>::iterator runIt = fRuns->begin();
00617 fRuns->end() != runIt;
00618 ++runIt){
00619 (*runIt)->QuietModeOff();
00620 }
00621 }
00622
00623
00624 const TGraph *NuSystFitter::Chi2SliceSin2bar(const NuMMParameters & mmParsC, Int_t numpoints, const Double_t minval, const Double_t maxval)
00625 {
00626 Double_t increment = (maxval - minval) / (Double_t)numpoints;
00627
00628 if (!fQuietMode) cout << "Generating Likelyhood surface for sin2bar" << endl;
00629
00630
00631 NuMMParameters mmPars(mmParsC);
00632
00633 Double_t sn2value = 0, like = 0, minimum = 0;
00634
00635
00636 TGraph *chisurf = new TGraph(numpoints);
00637 chisurf->SetNameTitle("Chi2Sin2Bar", "#Delta#chi^{2} Surface for Sin^{2}2#bar#theta");
00638 chisurf->GetXaxis()->SetTitle("Sin^{2}2#bar#theta");
00639
00640
00641 for (Int_t i = 0; i < numpoints; i++)
00642 {
00643 sn2value = minval + increment*i;
00644 mmPars.Sn2Bar(sn2value);
00645
00646
00647 like = (*this)(mmPars.VectorParameters());
00648
00649
00650
00651
00652 chisurf->SetPoint(i, sn2value, like);
00653
00654
00655 if (i == 0)
00656 minimum = like;
00657 else
00658 minimum = like < minimum ? like : minimum;
00659 }
00660
00661
00662 for (Int_t i = 0; i < numpoints; i++)
00663 {
00664 Double_t x, y;
00665 chisurf->GetPoint(i, x, y);
00666 chisurf->SetPoint(i, x, y-minimum);
00667 }
00668
00669
00670 if (!fQuietMode) cout << "Surface Generation Done." << endl;
00671
00672
00673 return chisurf;
00674 }
00675
00676
00677
00678 const TGraph *NuSystFitter::Chi2SliceDm2bar(const NuMMParameters & mmParsC, const Int_t numpoints, const Double_t minval, const Double_t maxval)
00679 {
00680 Double_t increment = (maxval - minval) / (Double_t)numpoints;
00681
00682
00683 if (!fQuietMode) cout << "Generating Likelyhood surface for dm2bar" << endl;
00684
00685
00686 NuMMParameters mmPars(mmParsC);
00687
00688
00689 TGraph *chisurf = new TGraph(numpoints);
00690 chisurf->SetNameTitle("Chi2Dm2Bar", "#Delta#chi^{2} Surface for #Delta#barm^{2}");
00691 chisurf->GetXaxis()->SetTitle("#Delta#barm^{2}");
00692
00693 Double_t dm2value = 0, like = 0, minimum = 0;
00694
00695
00696 for (Int_t i = 0; i < numpoints; i++)
00697 {
00698 dm2value = minval + increment*i;
00699 mmPars.Dm2Bar(dm2value);
00700
00701
00702 like = (*this)(mmPars.VectorParameters());
00703
00704
00705
00706
00707
00708 chisurf->SetPoint(i, dm2value, like);
00709
00710
00711 if (i == 0)
00712 minimum = like;
00713 else
00714 minimum = like < minimum ? like : minimum;
00715 }
00716
00717
00718 for (Int_t i = 0; i < numpoints; i++)
00719 {
00720 Double_t x, y;
00721 chisurf->GetPoint(i, x, y);
00722 chisurf->SetPoint(i, x, y-minimum);
00723 }
00724
00725
00726 if (!fQuietMode) cout << "Surface Generation Done." << endl;
00727
00728
00729 return chisurf;
00730 }
00731
00732 const TGraph *NuSystFitter::Chi2ValleyBar(const NuMMParameters &mmParsC, const Int_t points, const Double_t min, const Double_t max )
00733 {
00734 NuMMParameters mmPars(mmParsC);
00735
00736
00737
00738 mmPars.FixNorm();
00739 mmPars.FixShwScale();
00740 mmPars.FixNCBackground();
00741 mmPars.FixDm2();
00742 mmPars.FixSn2();
00743 mmPars.FixDm2Bar(false);
00744 mmPars.FixSn2Bar();
00745
00746
00747 Double_t sinval=0, likeval=0, minimum=0;
00748 Double_t interval = (max - min) / (points -1);;
00749
00750 if(!fQuietMode) cout << "Generating Valley trace plot..." << endl;
00751
00752 TGraph *sin2like = new TGraph(points);
00753
00754 for (Int_t i = 0; i < points; i++)
00755 {
00756
00757
00758 sinval = min + interval*i;
00759 mmPars.Sn2Bar(sinval);
00760
00761
00762 NuMMParameters mmFit = this->Minimise(mmPars);
00763
00764
00765 likeval = (*this)(mmFit.VectorParameters());
00766 sin2like->SetPoint(i, sinval, likeval);
00767
00768
00769 if (i == 0)
00770 minimum = likeval;
00771 else
00772 minimum = likeval < minimum ? likeval : minimum;
00773
00774 }
00775
00776 if (!fQuietMode) cout << endl << "Adjusting Graph Minimum" << endl;
00777
00778 for (Int_t i = 0; i < points; i++)
00779 {
00780 Double_t x, y;
00781 sin2like->GetPoint(i, x, y);
00782
00783 sin2like->SetPoint(i, x, y-minimum);
00784
00785 }
00786
00787 if (!fQuietMode) {
00788 cout << endl << "Valley trace plot generation completed" << endl;
00789 cout << " Minimum found was " << minimum << endl;
00790 }
00791
00792
00793 return sin2like;
00794 }
00796
00797 const TGraph *NuSystFitter::Chi2ValleyBarDm2Bar( const NuMMParameters &mmParsC,
00798 const Int_t points,
00799 const Double_t min,
00800 const Double_t max )
00801 {
00802 NuMMParameters mmPars(mmParsC);
00803
00804 mmPars.FixNorm();
00805 mmPars.FixShwScale();
00806 mmPars.FixNCBackground();
00807 mmPars.FixDm2();
00808 mmPars.FixSn2();
00809 mmPars.FixDm2Bar();
00810 mmPars.FixSn2Bar(false);
00811 mmPars.ConstrainPhysical();
00812
00813
00814
00815 Double_t dmval=0, likeval=0, minimum=0;
00816 Double_t interval = (max - min) / (points -1);;
00817
00818 if(!fQuietMode) cout << "Generating Valley trace plot for dm2..." << endl;
00819
00820 TGraph *dm2like = new TGraph(points);
00821 dm2like->SetName("valleyplot_mass");
00822
00823 for (Int_t i = 0; i < points; i++)
00824 {
00825 if (i % 10 == 0) {
00826 cout << i << "/" << points << endl;
00827 }
00828
00829 dmval = min + interval*i;
00830 mmPars.Dm2Bar(dmval);
00831
00832
00833 NuMMParameters mmFit = this->Minimise(mmPars);
00834
00835
00836 likeval = (*this)(mmFit.VectorParameters());
00837 dm2like->SetPoint(i, dmval, likeval);
00838
00839
00840 if (i == 0)
00841 minimum = likeval;
00842 else
00843 minimum = likeval < minimum ? likeval : minimum;
00844 }
00845
00846 if (!fQuietMode) cout << endl << "Adjusting Graph Minimum" << endl;
00847
00848
00849 for (Int_t i = 0; i < points; i++)
00850 {
00851 Double_t x, y;
00852 dm2like->GetPoint(i, x, y);
00853 dm2like->SetPoint(i, x, y-minimum);
00854 }
00855
00856 if (!fQuietMode) {
00857 cout << endl << "Valley trace plot generation completed" << endl;
00858 cout << " Minimum found was " << minimum << endl;
00859 }
00860
00861 return dm2like;
00862 }
00863
00865
00866 const TGraph *NuSystFitter::Chi2ValleyDm2( const NuMMParameters &mmParsC,
00867 const Int_t points,
00868 const Double_t min,
00869 const Double_t max)
00870 {
00871 NuMMParameters mmPars(mmParsC);
00872
00873 mmPars.FixNorm();
00874 mmPars.FixShwScale();
00875 mmPars.FixNCBackground();
00876 mmPars.FixDm2();
00877 mmPars.ReleaseSn2();
00878 mmPars.FixDm2Bar();
00879 mmPars.FixSn2Bar();
00880 mmPars.ConstrainPhysical();
00881
00882
00883
00884 Double_t dmval=0, likeval=0, minimum=0;
00885 Double_t interval = (max - min) / (points -1);;
00886
00887 if(!fQuietMode) cout << "Generating Valley trace plot for dm2..." << endl;
00888
00889 TGraph *dm2like = new TGraph(points);
00890 dm2like->SetName("valleyplot_mass");
00891
00892 for (Int_t i = 0; i < points; i++)
00893 {
00894
00895 NuUtilities::ProgressBar(i, points-1,5);
00896
00897
00898 dmval = min + interval*i;
00899 mmPars.Dm2(dmval);
00900
00901
00902 NuMMParameters mmFit = this->Minimise(mmPars);
00903
00904
00905 likeval = (*this)(mmFit.VectorParameters());
00906 dm2like->SetPoint(i, dmval, likeval);
00907
00908
00909 if (i == 0)
00910 minimum = likeval;
00911 else
00912 minimum = likeval < minimum ? likeval : minimum;
00913 }
00914
00915 if (!fQuietMode) cout << endl << "Adjusting Graph Minimum" << endl;
00916
00917
00918 for (Int_t i = 0; i < points; i++)
00919 {
00920 Double_t x, y;
00921 dm2like->GetPoint(i, x, y);
00922 dm2like->SetPoint(i, x, y-minimum);
00923 }
00924
00925 if (!fQuietMode) {
00926 cout << endl << "Valley trace plot generation completed" << endl;
00927 cout << " Minimum found was " << minimum << endl;
00928 }
00929
00930 return dm2like;
00931 }
00932
00934
00935 const TGraph *NuSystFitter::Chi2ValleySn2( const NuMMParameters &mmParsC,
00936 const Int_t points,
00937 const Double_t min,
00938 const Double_t max)
00939 {
00940 NuMMParameters mmPars(mmParsC);
00941
00942 mmPars.FixNorm();
00943 mmPars.FixShwScale();
00944 mmPars.FixNCBackground();
00945 mmPars.ReleaseDm2();
00946 mmPars.FixSn2();
00947 mmPars.FixDm2Bar();
00948 mmPars.FixSn2Bar();
00949 mmPars.ConstrainPhysical();
00950
00951
00952
00953 Double_t snval=0, likeval=0, minimum=0;
00954 Double_t interval = (max - min) / (points -1);;
00955
00956 if(!fQuietMode) cout << "Generating Valley trace plot for sn2..." << endl;
00957
00958 TGraph *sn2like = new TGraph(points);
00959 sn2like->SetName("valleyplot_sin");
00960
00961 for (Int_t i = 0; i < points; i++)
00962 {
00963
00964 NuUtilities::ProgressBar(i, points-1,5);
00965
00966
00967 snval = min + interval*i;
00968 mmPars.Sn2(snval);
00969
00970
00971 NuMMParameters mmFit = this->Minimise(mmPars);
00972
00973
00974 likeval = (*this)(mmFit.VectorParameters());
00975 sn2like->SetPoint(i, snval, likeval);
00976
00977
00978 if (i == 0)
00979 minimum = likeval;
00980 else
00981 minimum = likeval < minimum ? likeval : minimum;
00982 }
00983
00984 if (!fQuietMode) cout << endl << "Adjusting Graph Minimum" << endl;
00985
00986
00987 for (Int_t i = 0; i < points; i++)
00988 {
00989 Double_t x, y;
00990 sn2like->GetPoint(i, x, y);
00991 sn2like->SetPoint(i, x, y-minimum);
00992 }
00993
00994 if (!fQuietMode) {
00995 cout << endl << "Valley trace plot generation completed" << endl;
00996 cout << " Minimum found was " << minimum << endl;
00997 }
00998
00999 return sn2like;
01000 }
01001
01003
01004 TH2D *NuSystFitter::LikelihoodSurfaceBar (const NuMMParameters &mmParsIn,
01005 Int_t sinPoints,
01006 Int_t massPoints,
01007 Double_t sn2BarMin,
01008 Double_t sn2BarMax,
01009 Double_t dm2BarMin,
01010 Double_t dm2BarMax,
01011 Bool_t True_Minimum )
01012 {
01013
01014
01015
01016 Double_t sininterval = (sn2BarMax - sn2BarMin) / (sinPoints -1);
01017 Double_t massinterval = (dm2BarMax - dm2BarMin) / (massPoints - 1);
01018
01019
01020 Double_t sinoffset = sininterval / 2.0;
01021 Double_t massoffset = massinterval / 2.0;
01022
01023 TH2D *surface = new TH2D( "chisurf", "#chi^{2} Likelihood Surface",
01024 sinPoints, sn2BarMin-sinoffset, sn2BarMax+sinoffset,
01025 massPoints, dm2BarMin-massoffset, dm2BarMax+massoffset );
01026
01027 surface->GetXaxis()->SetTitle("sin^{2}2#bar#theta");
01028 surface->GetYaxis()->SetTitle("#Delta#barm^{2}");
01029
01030
01031
01032
01033
01034 NuMMParameters mmPars(mmParsIn);
01035
01036
01037
01038
01039
01040
01041 if (!fQuietMode) cout << "Generating Likelihood Surface..." << endl;
01042
01043 Double_t minimum = this->FillLikelihoodSurfaceBar(*surface, mmPars);
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071 if (!fQuietMode) {
01072 cout << "Surface Generation Done. Minimum Likelihood = "
01073 << minimum << endl;
01074 }
01075
01076
01077
01078 Int_t minbinX, minbinY, minbinZ;
01079 surface->GetMinimumBin(minbinX, minbinY, minbinZ);
01080
01081 mmPars.Sn2Bar(surface->GetXaxis()->GetBinCenter(minbinX));
01082 mmPars.Dm2Bar(surface->GetYaxis()->GetBinCenter(minbinY));
01083
01084 if (True_Minimum) {
01085
01086 if (!fQuietMode) cout << "Searching for true minimum" << endl;
01087
01088 NuMMParameters mmFit = this->Minimise(mmPars);
01089 Double_t minlike = (*this)(mmFit.VectorParameters());
01090
01091
01092 if (mmFit.MinuitPass())
01093 {
01094
01095 if (minlike <= minimum)
01096 minimum = minlike;
01097 else
01098 cout << "WARNING: Fit Minimisation found minimum higher than grid search" << endl;
01099 }
01100 }
01101
01102
01103
01104 for (Int_t sinBin = 1; sinBin <= sinPoints; sinBin++) {
01105 for (Int_t massBin = 1; massBin <= massPoints; massBin++) {
01106 Double_t content = surface->GetBinContent(sinBin, massBin);
01107 surface->SetBinContent(sinBin, massBin, content - minimum);
01108 }
01109 }
01110
01111
01112 return surface;
01113 }
01114
01116
01117 Double_t NuSystFitter::FillLikelihoodSurface (TH2D &surface, NuMMParameters mmPars)
01118 {
01119 Double_t minimum = -1;
01120 Int_t bincount = surface.GetNbinsX() * surface.GetNbinsY();
01121
01122 for (Int_t x = 1; x <= surface.GetNbinsX(); x++)
01123 {
01124 for (Int_t y = 1; y <= surface.GetNbinsY(); y++)
01125 {
01126
01127 if (fQuietMode) NuUtilities::ProgressBar(x*y, bincount, 5);
01128
01129 mmPars.Sn2(surface.GetXaxis()->GetBinCenter(x));
01130 mmPars.Dm2(surface.GetYaxis()->GetBinCenter(y));
01131 Double_t likelihood = (*this)(mmPars.VectorParameters());
01132
01133 surface.SetBinContent(x, y, likelihood);
01134
01135
01136 if (minimum < 0 || minimum > likelihood) minimum = likelihood;
01137 }
01138 }
01139
01140 return minimum;
01141 }
01142
01144
01145 Double_t NuSystFitter::FillLikelihoodSurfaceBar (TH2D &surface, NuMMParameters mmPars)
01146 {
01147 Double_t minimum = -1;
01148 Int_t bincount = surface.GetNbinsX() * surface.GetNbinsY();
01149
01150 for (Int_t x = 1; x <= surface.GetNbinsX(); x++)
01151 {
01152 for (Int_t y = 1; y <= surface.GetNbinsY(); y++)
01153 {
01154 if (fQuietMode) NuUtilities::ProgressBar(x*y, bincount, 5);
01155
01156 mmPars.Sn2Bar(surface.GetXaxis()->GetBinCenter(x));
01157 mmPars.Dm2Bar(surface.GetYaxis()->GetBinCenter(y));
01158 Double_t likelihood = (*this)(mmPars.VectorParameters());
01159
01160 surface.SetBinContent(x, y, likelihood);
01161
01162
01163 if (minimum < 0 || minimum > likelihood) minimum = likelihood;
01164 }
01165 }
01166
01167 return minimum;
01168 }
01169
01170 Double_t NuSystFitter::FillLikelihoodSurfaceCPT (TH2D &surface, NuMMParameters mmPars)
01171 {
01172 Double_t minimum = -1;
01173 for (Int_t x = 1; x <= surface.GetNbinsX(); x++)
01174 {
01175 for (Int_t y = 1; y <= surface.GetNbinsY(); y++)
01176 {
01177 mmPars.Sn2(surface.GetXaxis()->GetBinCenter(x));
01178 mmPars.Dm2(surface.GetYaxis()->GetBinCenter(y));
01179 mmPars.Sn2Bar(surface.GetXaxis()->GetBinCenter(x));
01180 mmPars.Dm2Bar(surface.GetYaxis()->GetBinCenter(y));
01181 Double_t likelihood = (*this)(mmPars.VectorParameters());
01182
01183 surface.SetBinContent(x, y, likelihood);
01184
01185
01186 if (minimum < 0 || minimum > likelihood) minimum = likelihood;
01187 }
01188 }
01189
01190 return minimum;
01191 }
01192
01194
01195 const NuMMParameters NuSystFitter::FCMinimise(const NuMMParameters& mmPars)
01196 {
01197
01198 const NuMMParameters mmStart = CoarseGridSearch(mmPars);
01199
01200
01201 NuMMParameters mmFit = Minimise(mmStart);
01202
01203
01204
01205
01206
01207
01208
01209 if (!mmFit.MinuitPass())
01210 {
01211
01212
01213
01214 MSG("NuSystFitter", Msg::kInfo) << "Minuit fit failed. Doing Finer Grid search" << endl;
01215 mmFit = FineGridSearch(mmStart);
01216 } else {
01217
01218 MSG("NuSystFitter", Msg::kInfo)
01219 << "Minuit found: dm2: " << mmFit.Dm2()
01220 << " sn2: " << mmFit.Sn2()
01221 << " dm2bar: " << mmFit.Dm2Bar()
01222 << " sn2bar: " << mmFit.Sn2Bar()
01223 << '\n';
01224 }
01225 return mmFit;
01226 }
01227
01228 NuMMParameters NuSystFitter::CoarseGridSearch(NuMMParameters mmGrid)
01229 {
01230
01231 const Int_t gridWidth = 5;
01232 const Int_t gridHeight = 15;
01233
01234
01235 TH2D likesurf("likesurf", "likesurf", gridWidth, 0.2, 1, gridHeight, 2e-3, 30e-3);
01236
01237 mmGrid = GridSearch(likesurf, mmGrid);
01238
01239
01240
01241 vector<Double_t> bins;
01242 for (Double_t i = -1.5; i <= -0.; i += 0.1) {
01243 bins.push_back(pow(10, i));
01244 }
01245 Int_t bincount = bins.size()-1;
01246 TH2D logsurf("logsurf", "logsurf", gridWidth, 0.2, 1, bincount, &(bins.front()));
01247 mmGrid = GridSearch(logsurf, mmGrid, &mmGrid);
01248
01249
01250
01251
01252
01253
01254 MSG("NuSystFitter", Msg::kInfo) << "Coarse grid search found sn2: "
01255 << mmGrid.Sn2Bar() << ", dm: " << mmGrid.Dm2Bar() << '\n';
01256
01257 return mmGrid;
01258 }
01259
01260 NuMMParameters NuSystFitter::FineGridSearch(NuMMParameters mmStart)
01261 {
01262
01263 Double_t gridL, gridR, gridT, gridB;
01264 gridL = gridR = gridT = gridB = -1.0;
01265
01266
01267 gridL = mmStart.Sn2Bar() - 0.2;
01268 gridR = gridL + 0.4;
01269
01270 if (gridL <= mmStart.LowerSn2BarLimit()) gridL = mmStart.LowerSn2BarLimit();
01271 if (gridR > 1.0) gridR = 1.0;
01272
01273
01274 gridB = mmStart.Dm2Bar() - 2e-3;
01275 gridT = gridB + 4e-3;
01276
01277 if (gridB <= mmStart.LowerDm2BarLimit()) gridB = mmStart.LowerSn2BarLimit();
01278
01279
01280 MSG("NuSystFitter", Msg::kInfo)
01281 << "Doing fine grid search on sin = [ "
01282 << gridL << ", " << gridR << " ]\n"
01283 << " dm = [ "
01284 << gridB << ", " << gridT << " ]\n";
01285
01286
01287 if (gridL >= gridR || gridT <= gridB) {
01288
01289 throw runtime_error("Negative range in fine grid search");
01290 }
01291
01292
01293
01294
01295 const Int_t gridWidth = 19;
01296 const Int_t gridHeight = 19;
01297
01298
01299 TH2D likesurf("likesurf", "likesurf", gridWidth, gridL, gridR,
01300 gridHeight, gridB, gridT);
01301
01302
01303 NuMMParameters mmGrid = GridSearch(likesurf, mmStart);
01304
01305
01306 MSG("NusystFitter", Msg::kInfo) << "Fine grid search found sn2bar: "
01307 << mmGrid.Sn2Bar() << ", dm2bar: " << mmGrid.Dm2Bar() << '\n';
01308
01309 return mmGrid;
01310 }
01311
01312 NuMMParameters NuSystFitter::GridSearch(TH2D &likesurf, NuMMParameters mmGrid, NuMMParameters *Ref)
01313 {
01314 Double_t likelihood = FillLikelihoodSurfaceBar(likesurf, mmGrid);
01315
01316
01317 Int_t minbinX = 0, minbinY = 0, minbinZ = 0;
01318 likesurf.GetMinimumBin(minbinX, minbinY, minbinZ);
01319 Double_t minsin = likesurf.GetXaxis()->GetBinCenter(minbinX);
01320 Double_t minmass = likesurf.GetYaxis()->GetBinCenter(minbinY);
01321
01322
01323 mmGrid.Sn2Bar(0);
01324 mmGrid.Dm2Bar(0);
01325 Double_t zeropoint = (*this)(mmGrid.VectorParameters());
01326 if (zeropoint < likelihood) {
01327
01328 minsin = 0.0;
01329 minmass = 0.0;
01330 }
01331
01332
01333 if (Ref) {
01334 Double_t refpoint = (*this)(Ref->VectorParameters());
01335 if (refpoint < likelihood) {
01336 MAXMSG("NuSystFitter", 5, Msg::kDebug) << "Reference point is lower than grid search" << endl;
01337 minsin = Ref->Sn2Bar();
01338 minmass = Ref->Dm2Bar();
01339 }
01340 }
01341
01342
01343 mmGrid.Sn2Bar(minsin);
01344 mmGrid.Dm2Bar(minmass);
01345
01346 return mmGrid;
01347 }
01348
01349
01350
01351 const TGraph *NuSystFitter::Chi2SliceDm2(const NuMMParameters & mmParsC, const Int_t numpoints, const Double_t minval, const Double_t maxval)
01352 {
01353 Double_t increment = (maxval - minval) / (Double_t)numpoints;
01354
01355
01356 if (!fQuietMode) cout << "Generating Likelyhood surface for dm2" << endl;
01357
01358
01359 NuMMParameters mmPars(mmParsC);
01360
01361
01362 TGraph *chisurf = new TGraph(numpoints);
01363 chisurf->SetNameTitle("Chi2Dm2", "#Delta#chi^{2} Surface for #Deltam^{2}");
01364 chisurf->GetXaxis()->SetTitle("#Deltam^{2}");
01365
01366 Double_t dm2value = 0, like = 0, minimum = 0;
01367
01368
01369 for (Int_t i = 0; i < numpoints; i++)
01370 {
01371 dm2value = minval + increment*i;
01372 mmPars.Dm2(dm2value);
01373
01374
01375 like = (*this)(mmPars.VectorParameters());
01376
01377
01378
01379
01380
01381 chisurf->SetPoint(i, dm2value, like);
01382
01383
01384 if (i == 0)
01385 minimum = like;
01386 else
01387 minimum = like < minimum ? like : minimum;
01388 }
01389
01390
01391 for (Int_t i = 0; i < numpoints; i++)
01392 {
01393 Double_t x, y;
01394 chisurf->GetPoint(i, x, y);
01395 chisurf->SetPoint(i, x, y-minimum);
01396 }
01397
01398
01399 if (!fQuietMode) cout << "Surface Generation Done." << endl;
01400
01401
01402 return chisurf;
01403 }