Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

NuSystFitter.cxx

Go to the documentation of this file.
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 //____________________________________________________________________72
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 //____________________________________________________________________72
00053 NuSystFitter::~NuSystFitter()
00054 {
00055 }
00056 
00057 //____________________________________________________________________72
00058 void NuSystFitter::push_back(NuMMRun* run)
00059 {
00060   fRuns->push_back(run);
00061 }
00062 //____________________________________________________________________72
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> /*outFileList*/,
00068                          const std::string /*combinedOutputFilename*/,
00069                          Int_t /*model*/)
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 //____________________________________________________________________72
00083 void NuSystFitter::NoOscPrediction()
00084 {
00085 
00086 }
00087 
00088 //____________________________________________________________________72
00089 const NuMMParameters NuSystFitter::Minimise(const NuMMParameters& mmPars)
00090 { 
00091   
00092   //Set up Minuit parameters
00093   ROOT::Minuit2::MnUserParameters mnPars = mmPars.MinuitParameters();
00094   vector<double> param_vec = mnPars.Params();
00095   //cout << "Fitting with " << param_vec.size() << " parameters." << endl;
00096   //cout << "Fitting with " << mnPars.VariableParameters() << " variable parameters." << endl;
00097   if (!fQuietMode) mmPars.PrintStatus();
00098     
00099   //Run Minuit fit
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   //cout << "Diagonal covar elements:" << endl;
00124   //ROOT::Minuit2::MnUserCovariance covar = funcMin.UserCovariance();
00125   //for (unsigned int i = 0; i < covar.Nrow(); i++) {
00126   //  cout << "element " << i << " = " << covar(i,i) << endl;
00127   //}
00128   
00129   NuMMParameters bestFitPars(funcMin);
00130   bestFitPars.MinuitPass(didpass);
00131     //bestFitPars.PrintStatus();
00132     return bestFitPars;
00133   
00134 }
00135 
00136 //____________________________________________________________________72
00137 const NuMMParameters NuSystFitter::Minimise(const NuMMParameters& mmPars, bool &success)
00138 { 
00139 
00140   //Set up Minuit parameters
00141   ROOT::Minuit2::MnUserParameters mnPars = mmPars.MinuitParameters();
00142  
00143   //Run Minuit fit
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   //cout << "Diagonal covar elements:" << endl;
00165   //ROOT::Minuit2::MnUserCovariance covar = funcMin.UserCovariance();
00166   //for (unsigned int i = 0; i < covar.Nrow(); i++) {
00167   //  cout << "element " << i << " = " << covar(i,i) << endl;
00168   //}
00169 
00170   success = funcMin.IsValid();
00171   NuMMParameters bestFitPars(funcMin);
00172   return bestFitPars;
00173 
00174 }
00175 
00176 //____________________________________________________________________72
00177 const TGraph* NuSystFitter::PlotContours(const NuMMParameters& mmPars)
00178 { 
00179 
00180   
00181   //Set up Minuit parameters
00182   ROOT::Minuit2::MnUserParameters mnPars = mmPars.MinuitParameters();
00183   
00184   //Run Minuit fit
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   //std::vector<std::pair<Double_t,Double_t> > vContPoints(10);// = contErr();
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 //  cout << "drawing contour" << endl;
00223 //  gCont->SetName("gCont");
00224 //  gDirectory->Print();
00225 //  TFile* file=TFile::Open("contourplot.root","RECREATE");
00226 //  gDirectory->Print();
00227 //  gCont->Write("gCont");
00228 //  file->Close();
00229   return gCont;
00230 }
00231 
00232 //____________________________________________________________________72
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   //Put the contour points in a TGraph
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 //____________________________________________________________________72
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   //Make a single vector of points
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   //Put the contour points in a TGraph
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 //____________________________________________________________________72
00304 const std::vector<std::pair<Double_t,Double_t> > NuSystFitter
00305 ::NeutrinoContourFinder(const NuMMParameters& inputPars)
00306 { 
00307   //Find the target chi2 for the contour
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   //Fix sn2 ready for the dm2 scans:
00314   NuMMParameters mmPars = inputPars;
00315   mmPars.FixSn2();
00316   //Make somewhere to put the contour points
00317   std::vector<pair<Double_t,Double_t> > pointsUp;
00318   std::vector<pair<Double_t,Double_t> > pointsDown;
00319 
00320   //Run the contour in quiet mode
00321   this->QuietModeOn();
00322 
00323   //Get the points for the contour
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   //Make a single vector of points
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 //____________________________________________________________________72
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 //____________________________________________________________________72
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 //____________________________________________________________________72
00573 double NuSystFitter::operator()(const std::vector<double>& pars) const
00574 {
00575   NuMMParameters mmPars(pars);
00576   //cout << "Called operator()" << endl;
00577   //mmPars.PrintStatus();
00578   return Likelihood(mmPars);
00579 }
00580 
00581 //____________________________________________________________________72
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 //____________________________________________________________________72
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 //____________________________________________________________________72
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         // Set the parameters object
00631         NuMMParameters mmPars(mmParsC);
00632 
00633         Double_t sn2value = 0, like = 0, minimum = 0;
00634 
00635         // Make the TGraph to fill
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         // We want to scan over the sin2bar surface and generate a likelyhood plot
00641         for (Int_t i = 0; i < numpoints; i++)
00642         {
00643                 sn2value = minval + increment*i;
00644                 mmPars.Sn2Bar(sn2value);
00645 
00646                 // Generate the likelyhood....
00647                 like = (*this)(mmPars.VectorParameters());
00648         
00649                 // Fill the array
00650                 //sin2s[i] = sn2value;
00651                 //likelyhoods[i] = like;
00652                 chisurf->SetPoint(i, sn2value, like);
00653         
00654                 // Is this the lowest value?    
00655                 if (i == 0)
00656                         minimum = like;
00657                 else
00658                         minimum = like < minimum ? like : minimum;
00659         }       
00660 
00661         // Offset the data points
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         // Now
00670         if (!fQuietMode) cout << "Surface Generation Done." << endl;
00671 
00672         // Return the completed TGraph
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         // Set the parameters object
00686         NuMMParameters mmPars(mmParsC);
00687 
00688         // Make the TGraph to fill
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         // We want to scan over the sin2bar surface and generate a likelyhood plot
00696         for (Int_t i = 0; i < numpoints; i++)
00697         {
00698                 dm2value = minval + increment*i;
00699                 mmPars.Dm2Bar(dm2value);
00700 
00701                 // Generate the likelyhood....
00702                 like = (*this)(mmPars.VectorParameters());
00703         
00704                 // Fill the array
00705 //              dm2s[i] = dm2value;
00706 //              likelyhoods[i] = like;
00707                 
00708                 chisurf->SetPoint(i, dm2value, like);
00709         
00710                 // Is this the lowest value?    
00711                 if (i == 0)
00712                         minimum = like;
00713                 else
00714                         minimum = like < minimum ? like : minimum;
00715         }       
00716 
00717         // Offset the data points
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         // Now
00726         if (!fQuietMode) cout << "Surface Generation Done." << endl;
00727 
00728         // Return the completed TGraph
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         //  mmPars.Dm2Bar(2.5e-3);
00737          // mmPars.Sn2Bar(1.0);
00738           mmPars.FixNorm();
00739           mmPars.FixShwScale();
00740           mmPars.FixNCBackground();
00741           mmPars.FixDm2();
00742           mmPars.FixSn2();
00743           mmPars.FixDm2Bar(false);
00744           mmPars.FixSn2Bar();
00745 
00746 //      Double_t sin2[points], likelyhood[points], mass[points];
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 //        cout << endl << "Sin2 " << i+1 << " / " << points << endl;
00757           // Set up the parameter structure
00758           sinval = min + interval*i;
00759           mmPars.Sn2Bar(sinval);
00760 
00761           // Now, minimize the likelyhood for this value
00762           NuMMParameters mmFit = this->Minimise(mmPars);
00763           //NuMMParameters mmFit(mmPars);
00764 
00765     likeval = (*this)(mmFit.VectorParameters());
00766     sin2like->SetPoint(i, sinval, likeval);
00767         
00768           // Calculate Minimum
00769           if (i == 0)
00770             minimum = likeval;
00771           else
00772             minimum = likeval < minimum ? likeval : minimum;
00773 //              cout << "Minimum is now " << minimum << endl;
00774         }
00775 
00776         if (!fQuietMode) cout << endl << "Adjusting Graph Minimum" << endl;
00777         // Offset the data points
00778         for (Int_t i = 0; i < points; i++)
00779         {
00780                 Double_t x, y;
00781                 sin2like->GetPoint(i, x, y);
00782 //              cout << "From: " << x << ", " << y << " to ";
00783                 sin2like->SetPoint(i, x, y-minimum);
00784 //              cout << x << ", " << y-minimum << endl;
00785         }
00786 
00787         if (!fQuietMode) {
00788     cout << endl << "Valley trace plot generation completed" << endl;
00789         cout << "   Minimum found was " << minimum << endl;
00790   }
00791 
00792         // Make the graphs
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     //  Double_t sin2[points], likelyhood[points], mass[points];
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         // Set up the parameter structure
00829         dmval = min + interval*i;
00830         mmPars.Dm2Bar(dmval);
00831 
00832         // Now, minimize the likelyhood for this value
00833         NuMMParameters mmFit = this->Minimise(mmPars);
00834         //NuMMParameters mmFit(mmPars);
00835 
00836         likeval = (*this)(mmFit.VectorParameters());
00837         dm2like->SetPoint(i, dmval, likeval);
00838 
00839         // Calculate Minimum
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     // Offset the data points
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     //  Double_t sin2[points], likelyhood[points], mass[points];
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         // Print a progress bar
00895         NuUtilities::ProgressBar(i, points-1,5);
00896       
00897         // Set up the parameter structure
00898         dmval = min + interval*i;
00899         mmPars.Dm2(dmval);
00900 
00901         // Now, minimize the likelyhood for this value
00902         NuMMParameters mmFit = this->Minimise(mmPars);
00903         //NuMMParameters mmFit(mmPars);
00904 
00905         likeval = (*this)(mmFit.VectorParameters());
00906         dm2like->SetPoint(i, dmval, likeval);
00907 
00908         // Calculate Minimum
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     // Offset the data points
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     //  Double_t sin2[points], likelyhood[points], mass[points];
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         // Print a progress bar
00964         NuUtilities::ProgressBar(i, points-1,5);
00965 
00966         // Set up the parameter structure
00967         snval = min + interval*i;
00968         mmPars.Sn2(snval);
00969 
00970         // Now, minimize the likelyhood for this value
00971         NuMMParameters mmFit = this->Minimise(mmPars);
00972         //NuMMParameters mmFit(mmPars);
00973 
00974         likeval = (*this)(mmFit.VectorParameters());
00975         sn2like->SetPoint(i, snval, likeval);
00976 
00977         // Calculate Minimum
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     // Offset the data points
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     // Calculate the bin spacing. This is -1 because we want to 'add'
01014     // one bin outside of the specified range, so that the bin contents
01015     // are representative of the center of the bin.
01016     Double_t sininterval =  (sn2BarMax - sn2BarMin) / (sinPoints -1);
01017     Double_t massinterval = (dm2BarMax - dm2BarMin) / (massPoints - 1);
01018 
01019     // Offsets. This is how much to shift the bins min and max by
01020     Double_t sinoffset = sininterval / 2.0;
01021     Double_t massoffset = massinterval / 2.0;
01022     // Create the destination histogram
01023     TH2D *surface = new TH2D(   "chisurf", "#chi^{2} Likelihood Surface",
01024                                 sinPoints, sn2BarMin-sinoffset, sn2BarMax+sinoffset,
01025                                 massPoints, dm2BarMin-massoffset, dm2BarMax+massoffset );
01026     // Set it up
01027     surface->GetXaxis()->SetTitle("sin^{2}2#bar#theta");
01028     surface->GetYaxis()->SetTitle("#Delta#barm^{2}");
01029     
01030     // A variable to store the minimum likelihood encountered
01031     // Double_t minimum = -1;
01032    
01033     // Make a copy of the parameters
01034     NuMMParameters mmPars(mmParsIn);
01035     
01036     // Variables to store the current value. These are declared here
01037     // so that we can verify we have counted them correctly after the
01038     // looping ends.
01039     // Double_t sinVal = 0., dmVal = 0.;
01040     
01041     if (!fQuietMode) cout << "Generating Likelihood Surface..." << endl;
01042     
01043     Double_t minimum = this->FillLikelihoodSurfaceBar(*surface, mmPars);
01044     
01045     // // Now, start looping over the surface
01046     // for (Int_t sinBin = 1; sinBin <= sinPoints; sinBin++) 
01047     // {
01048     //     // Calculate and set this sin (bin 0 starts at -sinoffset but
01049     //     // we want it to contain the value at 0)
01050     //     sinVal = sn2BarMin + sininterval*(sinBin-1);
01051     //     mmPars.Sn2Bar(sinVal);
01052     //     
01053     //     for (Int_t massBin = 1; massBin <= massPoints; massBin++)
01054     //     {
01055     //         // Calculate and set the dmass value
01056     //         dmVal = dm2BarMin + massinterval*(massBin-1);
01057     //         mmPars.Dm2Bar(dmVal);
01058     //         
01059     //         // Now, calculate the likelihood using this fitter
01060     //         Double_t likelihood = (*this)(mmPars.VectorParameters());
01061     //         
01062     //         // Minimim calculations
01063     //         if (minimum < 0 || likelihood < minimum)
01064     //             minimum = likelihood;
01065     //         
01066     //         // Set the bin content!
01067     //         surface->SetBinContent(sinBin, massBin, likelihood);
01068     //     }
01069     // }
01070     // Print a message to say we have finished
01071     if (!fQuietMode) {
01072         cout << "Surface Generation Done. Minimum Likelihood = "
01073              << minimum << endl;
01074     }
01075              
01076     
01077     // Get the minimum bin on this histogram
01078     Int_t minbinX, minbinY, minbinZ;
01079     surface->GetMinimumBin(minbinX, minbinY, minbinZ);
01080     // Set the fit parameters to this point as a start point
01081     mmPars.Sn2Bar(surface->GetXaxis()->GetBinCenter(minbinX));
01082     mmPars.Dm2Bar(surface->GetYaxis()->GetBinCenter(minbinY));
01083 
01084   if (True_Minimum) {
01085     // Now minimise at this point, and grab the likelihood
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     // Check if the fit failed, if it did, then don't use it
01092     if (mmFit.MinuitPass())
01093     {
01094         // If this is smaller than this minimum we have found (it should be)
01095         if (minlike <= minimum)
01096           minimum = minlike;
01097         else
01098           cout << "WARNING: Fit Minimisation found minimum higher than grid search" << endl;
01099     }
01100   }
01101     // Now, we have generated likelihoods for all grid points.
01102     // Offset each one by the minimum, so that it is a delta chi
01103     // squared surface.
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     // Now we have generated and offset the histogram. Return it!
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           // Draw a progress bar, but only if we have quiet mode on
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           // Work out if this is the minimum
01136           if (minimum < 0 || minimum > likelihood) minimum = likelihood;
01137       }
01138   }
01139   // Now, return the minimum!
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           // Work out if this is the minimum
01163           if (minimum < 0 || minimum > likelihood) minimum = likelihood;
01164       }
01165   }
01166   // Now, return the minimum!
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           // Work out if this is the minimum
01186           if (minimum < 0 || minimum > likelihood) minimum = likelihood;
01187       }
01188   }
01189   // Now, return the minimum!
01190   return minimum;
01191 }
01192 
01194 
01195 const NuMMParameters NuSystFitter::FCMinimise(const NuMMParameters& mmPars)
01196 {
01197   // Start with a coarse grid search, to seed minuit
01198   const NuMMParameters mmStart = CoarseGridSearch(mmPars);    
01199   
01200   // Now run the normal minuit procedure with this as the starting point
01201   NuMMParameters mmFit = Minimise(mmStart);
01202   
01203   // If minuit failed, do a finer grid search around the coarse starting point
01204   // Did minuit succeed?
01205   // if (mmFit.MinuitPass())
01206   // {
01207 
01208   // } else {
01209   if (!mmFit.MinuitPass())
01210   {
01211       // Minuit failed to fit. Use a more intensive grid search,
01212       // starting on the minuit starting point (that we get from
01213       // a grid search)
01214       MSG("NuSystFitter", Msg::kInfo) << "Minuit fit failed. Doing Finer Grid search" << endl;
01215       mmFit = FineGridSearch(mmStart);
01216   } else {
01217       // Tell them what minuit found
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   // The width and height of the grid
01231   const Int_t gridWidth = 5;
01232   const Int_t gridHeight = 15;
01233 
01234   // Generate the surface
01235   TH2D likesurf("likesurf", "likesurf", gridWidth, 0.2, 1, gridHeight, 2e-3, 30e-3);
01236   // TH2D likesurf("likesurf", "likesurf", gridWidth, 0.2, 1, 998*10, 2e-3, 1000e-3);
01237   mmGrid = GridSearch(likesurf, mmGrid);
01238   // cout << "Found dm2: " << mmGrid.Dm2Bar() << ", sn2: " << mmGrid.Sn2Bar() << endl;
01239 
01240   // Now do a log search
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   // This was code to do a much sparser grid search instead of the log search
01250   // TH2D sparser("sparser", "sparser", gridWidth, 0.2, 1, 400, 30e-3, 1000e-3);
01251   //  mmGrid = GridSearch(sparser, mmGrid, &mmGrid);
01252 
01253   // Output the minimum
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   // Calculate the location of the fine grid search
01263   Double_t gridL, gridR, gridT, gridB;
01264   gridL = gridR = gridT = gridB = -1.0;
01265   
01266   // Go +- 0.2 in sin space
01267   gridL = mmStart.Sn2Bar() - 0.2;
01268   gridR = gridL + 0.4;
01269   // Now limit it to the physical realm
01270   if (gridL <= mmStart.LowerSn2BarLimit()) gridL = mmStart.LowerSn2BarLimit();
01271   if (gridR > 1.0) gridR = 1.0;
01272 
01273   // And go +-2e-3 in mass space
01274   gridB = mmStart.Dm2Bar() - 2e-3;
01275   gridT = gridB + 4e-3;
01276   // We only really need to worry about lower limit here
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   // Ensure that we haven't done anything stupid like set low above high
01287   if (gridL >= gridR || gridT <= gridB) {
01288 //      cout << "Error: Negative range in fine grid search" << endl;
01289       throw runtime_error("Negative range in fine grid search");
01290   }
01291   
01292   // Make the surface
01293   
01294   // The width and height of the grid
01295   const Int_t gridWidth = 19;
01296   const Int_t gridHeight = 19;
01297   
01298   // Generate the surface
01299   TH2D likesurf("likesurf", "likesurf", gridWidth, gridL, gridR,
01300     gridHeight, gridB, gridT);
01301     
01302   // And now do a grid search on this
01303   NuMMParameters mmGrid = GridSearch(likesurf, mmStart);
01304   
01305   // Output the minimum
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     // Find the point on this surface that is minimum
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     // Check the zero point, to see if it is lower than anything else on the grid
01323     mmGrid.Sn2Bar(0);
01324     mmGrid.Dm2Bar(0);
01325     Double_t zeropoint = (*this)(mmGrid.VectorParameters());
01326     if (zeropoint < likelihood) {
01327         // Then the no-oscillation case is the minimum
01328         minsin = 0.0;
01329         minmass = 0.0;
01330     }
01331     
01332     // If we have been given a reference point, check to see if this is lower
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     // Set mmPars to the newly found point, then return it
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         // Set the parameters object
01359         NuMMParameters mmPars(mmParsC);
01360 
01361         // Make the TGraph to fill
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         // We want to scan over the sin2bar surface and generate a likelyhood plot
01369         for (Int_t i = 0; i < numpoints; i++)
01370         {
01371                 dm2value = minval + increment*i;
01372                 mmPars.Dm2(dm2value);
01373 
01374                 // Generate the likelyhood....
01375                 like = (*this)(mmPars.VectorParameters());
01376         
01377                 // Fill the array
01378 //              dm2s[i] = dm2value;
01379 //              likelyhoods[i] = like;
01380                 
01381                 chisurf->SetPoint(i, dm2value, like);
01382         
01383                 // Is this the lowest value?    
01384                 if (i == 0)
01385                         minimum = like;
01386                 else
01387                         minimum = like < minimum ? like : minimum;
01388         }       
01389 
01390         // Offset the data points
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         // Now
01399         if (!fQuietMode) cout << "Surface Generation Done." << endl;
01400 
01401         // Return the completed TGraph
01402         return chisurf;
01403 }

Generated on Mon Feb 15 11:07:16 2010 for loon by  doxygen 1.3.9.1