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

NCFitMaster.cxx

Go to the documentation of this file.
00001 
00002 //$Id: NCFitMaster.cxx,v 1.21 2009/06/18 18:12:22 bckhouse Exp $
00003 //
00004 //C. Backhouse 11/2008
00005 //
00007 
00008 #include "NCFitMaster.h"
00009 
00010 #include "NCUtils/Extrapolation/NCExtrapolation.h"
00011 
00012 #include "MessageService/MsgService.h"
00013 
00014 #include "TCanvas.h"
00015 #include "TDirectory.h"
00016 #include "TLegend.h"
00017 #include "TMarker.h"
00018 #include "TStopwatch.h"
00019 
00020 CVSID("$Id: NCFitMaster.cxx,v 1.21 2009/06/18 18:12:22 bckhouse Exp $");
00021 
00022 
00023 using namespace std;
00024 using namespace NC::Fitter;
00025 
00026 
00027 namespace NC{
00033   class GetChiSqrFromDerived: public ICallableND
00034   {
00035   public:
00036     GetChiSqrFromDerived(){}
00037     GetChiSqrFromDerived(NCExtrapolation* P,
00038                          std::vector<NCParameter> pars,
00039                          bool penalty,
00040                          bool analyticNorm)
00041       :p(P), params(pars), usePenalty(penalty),
00042        fAnalyticNormalization(analyticNorm){}
00043     virtual ~GetChiSqrFromDerived(){} // shut gcc up
00044     double EvalAtEx(const CoordNDim& r, CoordNDim* ret) const;
00045     void UsePenalty(bool p){usePenalty = p;}
00046     void DrawAndWriteGraph() const;
00047   private:
00048     NCExtrapolation* p;
00049     // Cache must be static, otherwise each instance will have a seperate copy.
00050     static std::map<CoordNDim, double> cache;
00051     std::vector<NCParameter> params;
00052     bool usePenalty;
00053     bool fAnalyticNormalization;
00054     static std::vector<CoordNDim> evaledAt;
00055     static std::vector<double> chisqRets;
00056   };
00057 } // end namespace
00058 
00059 
00060 map<CoordNDim, double> NC::GetChiSqrFromDerived::cache;
00061 vector<CoordNDim> NC::GetChiSqrFromDerived::evaledAt;
00062 vector<double> NC::GetChiSqrFromDerived::chisqRets;
00063 
00064 //----------------------------------------------------------------------
00065 double NC::GetChiSqrFromDerived::EvalAtEx(const CoordNDim& r,
00066                                           CoordNDim* retCoord) const
00067 {
00068   if(retCoord) *retCoord = r;
00069 
00070   evaledAt.push_back(r);
00071 
00072   const map<CoordNDim, double>::const_iterator it = cache.find(r);
00073   if(it != cache.end()){
00074 //    cout << "chisq from cache " << r << endl;
00075     chisqRets.push_back(it->second);
00076     return it->second;
00077   }
00078   // Maximum cache size is arbitrary, tune for performance.
00079   const unsigned int maxCacheSize = int(1e7); // on the order of 10meg
00080   if(cache.size() > maxCacheSize) cache.clear();
00081   //cout << "UNCACHED CHISQ REQUESTED " << r << endl;
00082 
00083   CoordNDim evalAt = r;
00084 
00085   if(usePenalty){
00086     // If the point is outside the physical region - move it to the boundary
00087     for(unsigned int n = 0; n < params.size(); ++n){
00088       if(params[n].UseLimits()){
00089         if(r[n] < params[n].Min()) evalAt[n] = params[n].Min();
00090         if(r[n] > params[n].Max()) evalAt[n] = params[n].Max();
00091       }
00092     }
00093   }
00094 
00095   const CoordinateConverter* cc = p->GetCoordConv();
00096   NC::OscProb::OscPars* oscPars = cc->OscParsFromCoordNDim(evalAt);
00097 
00098   double norm = 1;
00099   double ret = p->FindChiSqrForPars(oscPars,
00100                                     cc->SystParsFromCoordNDim(evalAt),
00101                                     fAnalyticNormalization ? &norm : 0);
00102 
00103   // TODO WE NEED TO STORE NORM INTO RETCOORD, BUT DON'T KNOW WHICH ONE!
00104 
00105   delete oscPars;
00106 
00107   if(usePenalty){
00108     // If we had to move the point then apply a quadratic penalty term.
00109     // The factor of 1000 was arrived at through trial and error.
00110     const double amplitude = 1e3;
00111     for(unsigned int n = 0; n < params.size(); ++n){
00112       if(params[n].UseLimits()){
00113         const double wsqr = (params[n].Min()-params[n].Max())*(params[n].Min()-params[n].Max());
00114         assert(wsqr);
00115         if(r[n] < params[n].Min())
00116           ret += amplitude*(params[n].Min()-r[n])*(params[n].Min()-r[n])/wsqr;
00117         if(r[n] > params[n].Max())
00118           ret += amplitude*(r[n]-params[n].Max())*(r[n]-params[n].Max())/wsqr;
00119       }
00120     }
00121   }
00122 
00123   //  for(unsigned int n = 0; n < evalAt.size(); ++n)
00124   //    cout << names[n] << " = " << evalAt[n] << "  ";
00125   //  cout << "-> " << ret << endl;
00126 
00127   // TODO - this cache is broken when using more than one extrapolation
00128   // disable it for now
00129   //  cache[r] = ret;
00130   chisqRets.push_back(ret);
00131 
00132   return ret;
00133 }
00134 
00135 //----------------------------------------------------------------------
00136 void NC::GetChiSqrFromDerived::DrawAndWriteGraph() const
00137 {
00138   TCanvas c("minimizer_eval_positions");
00139   TH2D axes("", "Evaluation Positions;time;", 100, 0, evaledAt.size(), 100, -1, 5);
00140   axes.Draw();
00141   for(unsigned int m = 0; m < evaledAt[0].size(); ++m){
00142     TGraph* g = new TGraph;
00143     g->Set(evaledAt.size());
00144     g->SetMarkerColor(m+1);
00145     for(unsigned int n = 0; n < evaledAt.size(); ++n){
00146       g->SetPoint(n, n, evaledAt[n][m]);
00147       g->Draw("p same");
00148     }
00149   }
00150 
00151   c.Write();
00152 }
00153 
00154 
00155 //----------------------------------------------------------------------
00156 NC::FitMaster::FitMaster(NCExtrapolation* child)
00157   : fExtrap(child), fBestFitOscPars(0), fFixedValsForMarg(0)
00158 {
00159   // We need to teach MinFinderSimple about where our variables are degenerate
00160   vector<string> names;
00161   names.push_back("theta23");
00162   names.push_back("theta");
00163   names.push_back("umu3");
00164   vector<double> poss;
00165   poss.push_back(TMath::Pi()/4);
00166   poss.push_back(TMath::Pi()/4);
00167   poss.push_back(0.5);
00168   NC::Fitter::MinFinderSimple::SetSpacePartitions(names, poss);
00169 }
00170 
00171 
00172 //----------------------------------------------------------------------
00173 const Registry& NC::FitMaster::DefaultConfig()
00174 {
00175   static Registry r;
00176 
00177   r.UnLockValues();
00178 
00179   // Whether the contour finder should use Minuit and if so how much (0 to 2).
00180   r.Set("LazyContoursUseMinuit", 0);
00181 
00182   r.Set("LazyContoursWant68",        true);
00183   r.Set("LazyContoursWant90",        true);
00184   r.Set("LazyContoursWant99",        true);
00185   r.Set("AllowBestFitOutsideRange",  false);
00186   r.Set("AllowContoursOutsideRange", false);
00187   r.Set("WantMinimum",               true);
00188   r.Set("Want2DProjections",         false);
00189   r.Set("WantGridSearch",            false);
00190   r.Set("WantSlices",                false);
00191   r.Set("Want2DSlices",              false);
00192   r.Set("WantCovarianceMatrix",      false);
00193   r.Set("TryPreviousMinimum",        false);
00194   r.Set("ForceBestFitToTruth",       false);
00195   r.Set("PrecScale",                 1.0);
00196   r.Set("AnalyticNormalization",     false);
00197   r.Set("ContoursList",              "");
00198   r.Set("ProjectionsList",           "");
00199 
00200   r.Merge(NC::CoordinateConverter::DefaultConfig());
00201 
00202   r.LockValues();
00203 
00204   return r;
00205 }
00206 
00207 
00208 //----------------------------------------------------------------------
00209 void NC::FitMaster::Prepare(const Registry& r)
00210 {
00211   MSG("NCFitMaster", Msg::kInfo) << "NC::FitMaster::Prepare(const Registry& r)" << endl;
00212 
00213   int         tmpb;  // a temp bool.
00214   int         tmpi;  // a temp int.
00215   double      tmpd;  // a temp double.
00216   const char* tmps;  // a temp string
00217 
00218   //?  if(r.Get("OscillationModel",    tmpi)) fOscillationModel    = NCType::EOscModel(tmpi);
00219 
00220   /*?
00221   //set the defaults for the systematic parameters
00222   //set them all off by default
00223   TString adjust = "Adjust";
00224   for(int i = 0; i < NCType::kNumSystematicParameters; ++i){
00225     if(r.Get(NCType::kParams[i].name, tmpb)) fSystematicsToUse[i] = tmpb;
00226     if(r.Get(adjust + NCType::kParams[i].name, tmpd)) fSystematicsAdjust[i] = tmpd;
00227   }
00228   */
00229 
00230   /*?
00231   MSG("NCExtrapolation", Msg::kInfo) << "PARAMETERS WE ARE USING:" << endl;
00232   for(int i = 0; i < NCType::kNumSystematicParameters; ++i){
00233     MSG("NCExtrapolation", Msg::kInfo) << i << ") "
00234                                        << NCType::kParams[i].name
00235                                        << " = " << fSystematicsToUse[i]
00236                                        << " with default = "
00237                                        << NCType::kParams[i].defaultVal
00238                                        << " adjust = "
00239                                        << fSystematicsAdjust[i] << endl;
00240   }
00241   */
00242 
00243   if(r.Get("LazyContoursUseMinuit",     tmpi)) fContourMethod = tmpi;
00244   if(r.Get("LazyContoursWant68",        tmpb)) fWant68 = tmpb;
00245   if(r.Get("LazyContoursWant90",        tmpb)) fWant90 = tmpb;
00246   if(r.Get("LazyContoursWant99",        tmpb)) fWant99 = tmpb;
00247   if(r.Get("WantMinimum",               tmpb)) fWantMinimum = tmpb;
00248   if(r.Get("Want2DProjections",         tmpb)) fWant2DProjections = tmpb;
00249   if(r.Get("WantGridSearch",            tmpb)) fWantGridSearch = tmpb;
00250   if(r.Get("WantSlices",                tmpb)) fWantSlices = tmpb;
00251   if(r.Get("Want2DSlices",              tmpb)) fWant2DSlices = tmpb;
00252   if(r.Get("WantCovarianceMatrix",      tmpb)) fWantCovariance = tmpb;
00253   if(r.Get("AllowBestFitOutsideRange",  tmpb)) fAllowBestFitOutsideRange = tmpb;
00254   if(r.Get("AllowContoursOutsideRange", tmpb)) fAllowContoursOutsideRange = tmpb;
00255   if(r.Get("TryPreviousMinimum",        tmpb)) fTryPreviousMinimum = tmpb;
00256   if(r.Get("ForceBestFitToTruth",       tmpb)) fForceBestFitToTruth = tmpb;
00257   if(r.Get("PrecScale",                 tmpd)) fPrecScale = tmpd;
00258 
00259   if(r.Get("AnalyticNormalization",     tmpb)) fAnalyticNormalization = tmpb;
00260 
00261   fCoordConv.Prepare(r);
00262 
00263   if(r.Get("ContoursList", tmps)){
00264     vector<int> xs, ys;
00265     ParseContourList(tmps, xs, ys);
00266     fXaxes.clear(); fYaxes.clear();
00267     for(unsigned int n = 0; n < xs.size(); ++n){
00268       fXaxes.push_back(NCType::EFitParam(xs[n]));
00269       fYaxes.push_back(NCType::EFitParam(ys[n]));
00270     }
00271   }
00272 
00273   if(r.Get("ProjectionsList", tmps)){
00274     const vector<int> pl = NC::Utility::ParseNumberList(tmps);
00275     for(unsigned int n = 0; n < pl.size(); ++n)
00276       fProjectionsList.push_back(NCType::EFitParam(pl[n]));
00277   }
00278 }
00279 
00280 
00281 //----------------------------------------------------------------------
00282 void NC::FitMaster::Run(const NC::OscProb::OscPars* trueOscPars)
00283 {
00284   assert(fXaxes.size() == fYaxes.size());
00285 
00286   assert(fContourMethod == 0 || fContourMethod == 1 || fContourMethod == 2);
00287 
00288   //?!? TODO  fSoftPenalty = true;
00289 
00290   // Create functionoid that redirects to derived-class's implementation.
00291   GetChiSqrFromDerived chiSqrFunc(fExtrap, fCoordConv.fFitParams, !fAllowBestFitOutsideRange, fAnalyticNormalization);
00292 
00293   TMinuit* minu; // If we use a minuit object for minimization,
00294                  // keep hold of it in case we want minuit contours.
00295 
00296   // A minimum is required to find contours or to do the projections.
00297   if((fWantMinimum ||
00298       fWant68 || fWant90 || fWant99 ||
00299       !fProjectionsList.empty() ||
00300       fWantSlices || fWant2DSlices) &&
00301      !fForceBestFitToTruth){
00302     MSG("NCFitMaster", Msg::kInfo) << "Begin fit..." << endl;
00303 
00304     TStopwatch fit_sw;
00305 
00306     if(fContourMethod == 0){ // simple
00307       vector<NCParameter> preciseParams = fCoordConv.fFitParams;
00308       for(unsigned int n = 0; n < preciseParams.size(); ++n)
00309         preciseParams[n].SetPrecision(preciseParams[n].Precision()/100);
00310 
00311       MinFinderSimple mf(preciseParams,
00312                          !fAllowBestFitOutsideRange,
00313                          fTryPreviousMinimum,
00314                          &chiSqrFunc);
00315       fMinChiSqr = mf.FindMin(fMinCoord, true);
00316 
00317       if(fWantCovariance){
00318         MSG("NCFitMaster", Msg::kInfo)
00319           << "Finding covariance matrix using finite differences...\n";
00320         FindCovarianceMatrix(&chiSqrFunc, fMinCoord, preciseParams).Print();
00321       }
00322     }
00323     if(fContourMethod == 1 || fContourMethod == 2){ // hybrid or minuit
00324       fMinChiSqr = MinFinderMinuit(&chiSqrFunc, fCoordConv.fFitParams, fMinCoord, &minu);
00325       if(fWantCovariance){
00326         MSG("NCFitMaster", Msg::kInfo)
00327           << "Printing Minuit covariance matrix...\n";
00328         minu->mnmatu(1);
00329       }
00330     }
00331 
00332     MSG("NCFitMaster", Msg::kInfo) << endl << "Best fit  - chisq = "
00333                                    << fMinChiSqr << endl;
00334 
00335     for(unsigned int n = 0; n < fCoordConv.fFitParams.size(); ++n){
00336       MSG("NCFitMaster", Msg::kInfo) << "  "
00337                                      << fCoordConv.fFitParams[n].ShortName()
00338                                      << " = " << fMinCoord[n] << endl;
00339     }
00340     MSG("NCFitMaster", Msg::kInfo) << endl;
00341 
00342     // This populates the syst and oscpars translations
00343     SetBestFitCoordNDim(fMinCoord);
00344     fExtrap->SetBestFitCoordNDim(fMinCoord); // TODO - make so we don't need this
00345 
00346     MSG("NCFitMaster", Msg::kInfo) << "Fit took ";
00347     fit_sw.Print("m");
00348   } // end if need minimum
00349 
00350 
00351   if(fForceBestFitToTruth){
00352     MSG("NCFitMaster", Msg::kInfo) << "Forcing best fit point to be "
00353                                    << "input truth point" << endl;
00354     assert(trueOscPars);
00355     fMinCoord = fCoordConv.CoordNDimFromOscPars(trueOscPars);
00356     // This populates the syst and oscpars translations
00357     SetBestFitCoordNDim(fMinCoord);
00358     fExtrap->SetBestFitCoordNDim(fMinCoord); // TODO - make so we don't need this
00359   }
00360 
00361 
00362   if(fFixedValsForMarg) MargWithFixedVals(&chiSqrFunc);
00363 
00364 
00365   // TODO - This doesn't actually work??
00366   chiSqrFunc.UsePenalty(!fAllowContoursOutsideRange);
00367 
00368 
00369   //? fSoftPenalty = false;
00370 
00371   // Want any contours?
00372   if(fWant68 || fWant90 || fWant99){
00373     TStopwatch cont_sw;
00374 
00375     // These represent the 3 confidence levels 68%, 90%, 99%
00376     const double contVals[] = {2.30, 4.61, 9.21};
00377 
00378     for(int conf = 0; conf < 3; ++conf){
00379       for(unsigned int axisPair = 0; axisPair < fXaxes.size(); ++axisPair){
00380         if(conf == 0 && !fWant68) continue;
00381         if(conf == 1 && !fWant90) continue;
00382         if(conf == 2 && !fWant99) continue;
00383 
00384         // Look up which axes we should be using.
00385         const NCType::EFitParam x = fXaxes[axisPair];
00386         const NCType::EFitParam y = fYaxes[axisPair];
00387 
00388         const NCParameter xPar = fCoordConv.ParameterForFitParam(x);
00389         const NCParameter yPar = fCoordConv.ParameterForFitParam(y);
00390 
00391         MSG("NCFitMaster", Msg::kInfo) << "Building contour in "
00392                                            << xPar.ShortName()
00393                                            << " and " << yPar.ShortName()
00394                                            << " (up = " << contVals[conf] << ")..."
00395                                            << endl;
00396 
00397         if(fContourMethod == 2){ // minuit
00398           fContourGraphs.push_back(GetContourMinuit(minu, x, y, contVals[conf]));
00399           delete minu;
00400         }
00401         else{
00402           vector<TGraph> marg_graphs;
00403           vector<Coord> contour = GetContour(&chiSqrFunc,
00404                                              fCoordConv.fFitParams,
00405                                              x, y, contVals[conf],
00406                                              marg_graphs);
00407           /* TODO - hacked out because it's broken. FIX!
00408           assert(marg_graphs.size() == 4*fCoordConv.fFitParams.size());
00409 
00410           // This gets picked up later and made the title of the canvas
00411           marg_graphs[0].SetName(TString::Format("%s_%s",
00412                                                  xPar.ShortName().c_str(),
00413                                                  yPar.ShortName().c_str()));
00414           marg_graphs[0].SetTitle(xPar.LatexName().c_str());
00415           marg_graphs[4].SetTitle(yPar.LatexName().c_str());
00416 
00417           int m = 0;
00418           for(unsigned int n = 8; n < marg_graphs.size(); n+=4, ++m){
00419             if(m == fCoordConv.FitterIndex(x)) ++m;
00420             if(m == fCoordConv.FitterIndex(y)) ++m;
00421             marg_graphs[n].SetTitle(fCoordConv.ParameterForFitterIndex(m).LatexName().c_str());
00422           }
00423           fMarginalGraphs.push_back(marg_graphs);
00424           */
00425 
00426           TGraph* g = new TGraph(contour.size());
00427           for(unsigned int n = 0; n < contour.size(); ++n)
00428             g->SetPoint(n, contour[n].x, contour[n].y);
00429           fContourGraphs.push_back(g);
00430 
00431           MSG("NCFitMaster", Msg::kInfo) << "\nthere are " << contour.size()
00432                                              << " points on this contour" << endl;
00433         }
00434       } // end for axisPair
00435     } // end for conf
00436 
00437     MSG("NCFitMaster", Msg::kInfo) << "Contours took ";
00438     cont_sw.Print("m");
00439   } // end if fWant
00440 
00441 
00442   //? fSoftPenalty = true;
00443 
00444   if(fWant2DProjections){
00445     for(unsigned int axisPair = 0; axisPair < fXaxes.size(); ++axisPair){
00446       // Look up which axes we should be using.
00447       const NCType::EFitParam x = fXaxes[axisPair];
00448       const NCType::EFitParam y = fYaxes[axisPair];
00449 
00450       vector<NCParameter> lowResParams = fCoordConv.fFitParams;
00451       for(unsigned int n = 0; n < lowResParams.size(); ++n)
00452         lowResParams[n].SetPrecision(lowResParams[n].Precision()*10);
00453 
00454       const NCParameter xPar = fCoordConv.ParameterForFitParam(x);
00455       const NCParameter yPar = fCoordConv.ParameterForFitParam(y);
00456 
00457       TH2D* grid = Get2DGrid(&chiSqrFunc, lowResParams, x, y);
00458 
00459       grid->SetName(("grid_"+xPar.ShortName()+"-"+yPar.ShortName()).c_str());
00460       grid->SetTitle(("Grid;"+xPar.LatexName()+";"+yPar.LatexName()).c_str());
00461       fLowResGrids.push_back(grid);
00462     } // end for axisPair
00463   } // end if fWant2D
00464 
00465 
00466   if(!fProjectionsList.empty()){
00467     TStopwatch proj_sw;
00468 
00469     for(unsigned int nAxis = 0; nAxis < fProjectionsList.size(); ++nAxis){
00470       const NCType::EFitParam x = fProjectionsList[nAxis];
00471 
00472       const NCParameter xPar = fCoordConv.ParameterForFitParam(x);
00473 
00474       MSG("NCFitMaster", Msg::kInfo) << "Building 1D projection in "
00475                                      << xPar.ShortName() << "..." << endl;
00476 
00477       double leftErr, rightErr;
00478       vector<TGraph> marg_graphs;
00479 
00480       // Seemingly for the projections we need more precision in the marginalised variables.
00481       vector<NCParameter> pars = fCoordConv.fFitParams;
00482       for(unsigned int n = 0; n < pars.size(); ++n){
00483         if(n != UInt_t(x)) pars[n].SetPrecision(pars[n].Precision()/10);
00484       }
00485 
00486       TGraph* proj = Get1DProjection(&chiSqrFunc, pars, x,
00487                                      leftErr, rightErr, marg_graphs);
00488 
00489       const double bestFit1D = fMinCoord[fCoordConv.FitterIndex(x)];
00490 
00491       MSG("NCFitMaster", Msg::kInfo)
00492         << "Asymmetric errors in " << xPar.ShortName()
00493         << " " << leftErr-bestFit1D << " "
00494         << rightErr-bestFit1D << endl;
00495 
00496       fOneSigmaErrors[xPar.ShortName()] =
00497         pair<double, double>(bestFit1D-leftErr, rightErr-bestFit1D);
00498 
00499       proj->SetName(("projection_"+xPar.ShortName()).c_str());
00500       proj->GetHistogram()->SetTitle((";"+xPar.LatexName()+";#chi^{2}").c_str());
00501       fChiSqGraphs.push_back(proj);
00502 
00503       // This gets picked up later and made the title of the canvas
00504       marg_graphs[0].SetName(TString::Format("%s", xPar.ShortName().c_str()));
00505       unsigned int m = 0;
00506       for(unsigned int n = 0; n < marg_graphs.size(); ++n, ++m){
00507         if(m == UInt_t(x)) ++m;
00508         marg_graphs[n].SetTitle(fCoordConv.ParameterForFitterIndex(m).LatexName().c_str());
00509       }
00510       fMarginalGraphs1D.push_back(marg_graphs);
00511 
00512     } // end for nAxis
00513 
00514     MSG("NCFitMaster", Msg::kInfo) << "Projections took ";
00515     proj_sw.Print("m");
00516   } // end if projections
00517 
00518 
00519   if(fWantGridSearch){
00520     // Arbitrary rescaling to make plots look nice.
00521     //    if(fCoordConv.IsFit(NCType::kUMu4Sqr)){
00522       //      fCoordConv.fFitParams[fCoordConv.FitterIndex(NCType::kUMu4Sqr)].Max() = .2;
00523       //      fCoordConv.fFitParams[fCoordConv.FitterIndex(NCType::kUMu4Sqr)].prec *= .2;
00524       //      fCoordConv.fFitParams[2].prec = .02; // dmsq
00525     //    }
00526     PrintGridSearch(&chiSqrFunc, fCoordConv.fFitParams, cout);
00527   }
00528 
00529   if(fWantSlices){
00530     MSG("NCFitMaster", Msg::kInfo) << "Starting slices" << endl;
00531     fSlices = MakeSlices(&chiSqrFunc, fCoordConv.fFitParams, fMinCoord);
00532   }
00533 
00534   if(fWant2DSlices) 
00535     f2DSlices = Make2DSlices(&chiSqrFunc, fCoordConv.fFitParams, fMinCoord);
00536 
00537 //  TFile f("~/eval_pos.root", "RECREATE");
00538 //  chiSqrFunc.DrawAndWriteGraph();
00539 //  f.Close();
00540 }
00541 
00542 
00543 //----------------------------------------------------------------------
00544 void NC::FitMaster::WriteResources()
00545 {
00546   MSG("NCFitMaster", Msg::kInfo)
00547     << "NC::FitMaster::WriteResources() - "
00548     << fExtrap->GetShortName() << endl;
00549 
00550   /* ???
00551   DrawBestFitSpectra(Detector::kNear);
00552   DrawBestFitSpectra(Detector::kFar);
00553 
00554   DrawBestFitRatios(Detector::kNear);
00555   DrawBestFitRatios(Detector::kFar);
00556   */
00557 
00558   gDirectory->mkdir("fit", "fit")->cd();
00559 
00560   GetBestFitPointAsRegistry()->Write();
00561   if(!fContourGraphs.empty()) DrawAndWriteContourGraphs();
00562   if(!fChiSqGraphs.empty()) DrawAndWriteChiSqGraphs();
00563   if(!fLowResGrids.empty()) DrawAndWriteLowResGrids();
00564   if(!fSlices.empty()) DrawAndWriteSlices();
00565   if(!f2DSlices.empty()) DrawAndWrite2DSlices();
00566 }
00567 
00568 
00569 //----------------------------------------------------------------------
00570 void NC::FitMaster::ParseContourList(TString contList,
00571                                      vector<int>& xs, vector<int>& ys) const
00572 {
00573   const int p1 = contList.First('(');
00574   const int p2 = contList.First(',');
00575   const int p3 = contList.First(')');
00576 
00577   // Assuming failure is signalled by < 0
00578   // Hopefully this means we reached the end of the string
00579   if(p1 < 0 || p2 < 0 || p3 < 0) return;
00580 
00581   // Get the bits that should contain the numbers
00582   // Slicing operator takes start and length
00583   const TString strX = contList(p1+1, p2-p1-1);
00584   const TString strY = contList(p2+1, p3-p2-1);
00585 
00586   // If they're not numbers we're well and truly stuck
00587   assert(strX.IsDigit());
00588   assert(strY.IsDigit());
00589 
00590   xs.push_back(strX.Atoi());
00591   ys.push_back(strY.Atoi());
00592 
00593   // Repeat the same operation on the rest of the string
00594   const TString remain = contList(p3+1, contList.Length()-p3);
00595   ParseContourList(remain, xs, ys);
00596 }
00597 
00598 
00599 //----------------------------------------------------------------------
00600 vector<NCType::EFitParam> NC::FitMaster::GetUniqueAxes() const
00601 {
00602   vector<NCType::EFitParam> ret;
00603 
00604   for(unsigned int n = 0; n < fXaxes.size(); ++n){
00605     const NCType::EFitParam ax = fXaxes[n];
00606     bool add = true;
00607     for(unsigned int m = 0; m < ret.size(); ++m){
00608       if(ret[m] == ax) add = false;
00609     } // end for m
00610     if(add) ret.push_back(ax);
00611   } // end for n
00612   for(unsigned int n = 0; n < fYaxes.size(); ++n){
00613     const NCType::EFitParam ax = fYaxes[n];
00614     bool add = true;
00615     for(unsigned int m = 0; m < ret.size(); ++m){
00616       if(ret[m] == ax) add = false;
00617     } // end for m
00618     if(add) ret.push_back(ax);
00619   } // end for n
00620 
00621   return ret;
00622 }
00623 
00624 
00625 //----------------------------------------------------------------------
00626 vector<Coord> NC::FitMaster::GetContour(ICallableND* chiSqrFunc,
00627                                         const vector<NCParameter>& params,
00628                                         NCType::EFitParam x,
00629                                         NCType::EFitParam y,
00630                                         double up,
00631                                         vector<TGraph>& marg_graphs)
00632 {
00633   const int xi = fCoordConv.FitterIndex(x);
00634   const int yi = fCoordConv.FitterIndex(y);
00635 
00636   const NCParameter xp = fCoordConv.ParameterForFitParam(x);
00637   const NCParameter yp = fCoordConv.ParameterForFitParam(y);
00638 
00639   if(fContourMethod == 0){ // simple
00640     MarginalizeSimple func(chiSqrFunc, params, fTryPreviousMinimum,
00641                            xi, yi);
00642     return FindContour(&func,
00643                        Coord(fMinCoord[xi], fMinCoord[yi]),
00644                        fMinChiSqr+up,
00645                        Coord(xp.Precision(), yp.Precision()),
00646                        &marg_graphs);
00647   }
00648 
00649   if(fContourMethod == 1){ // hybrid
00650     MarginalizeHybrid func(chiSqrFunc, params, fTryPreviousMinimum, x, y);
00651     return FindContour(&func,
00652                        Coord(fMinCoord[xi], fMinCoord[yi]),
00653                        fMinChiSqr+up,
00654                        Coord(xp.Precision(), yp.Precision()),
00655                        &marg_graphs);
00656   }
00657 
00658   assert(0 && "This should never happen");
00659 }
00660 
00661 
00662 //----------------------------------------------------------------------
00663 TGraph* NC::FitMaster::GetContourMinuit(TMinuit* minu,
00664                                         NCType::EFitParam x,
00665                                         NCType::EFitParam y, double up)
00666 {
00667   const int numContourPoints = 300;
00668   minu->SetErrorDef(up);
00669   TGraph* g = (TGraph*)minu->Contour(numContourPoints,
00670                                      fCoordConv.FitterIndex(x),
00671                                      fCoordConv.FitterIndex(y));
00672   if(minu->GetStatus()) MSG("NCExtrapolation", Msg::kWarning) << "Couldn't find contour.\n";
00673   return g;
00674 }
00675 
00676 
00677 //----------------------------------------------------------------------
00678 TH2D* NC::FitMaster::Get2DGrid(ICallableND* chiSqrFunc,
00679                                const vector<NCParameter>& params,
00680                                NCType::EFitParam x, NCType::EFitParam y)
00681 {
00682   const int xi = fCoordConv.FitterIndex(x);
00683   const int yi = fCoordConv.FitterIndex(y);
00684 
00685   const NCParameter xp = fCoordConv.ParameterForFitParam(x);
00686   const NCParameter yp = fCoordConv.ParameterForFitParam(y);
00687 
00688   if(fContourMethod == 0){ // simple
00689     MarginalizeSimple func(chiSqrFunc, params, fTryPreviousMinimum, xi, yi);
00690     return GetLowResGrid(&func,
00691                          Coord(xp.Min(), yp.Min()),
00692                          Coord(xp.Max(), yp.Max()),
00693                          Coord(xp.Precision(), yp.Precision()));
00694   }
00695 
00696   if(fContourMethod == 1 || fContourMethod == 2){ // hybrid or minuit
00697     MarginalizeHybrid func(chiSqrFunc, params, fTryPreviousMinimum, xi, yi);
00698     return GetLowResGrid(&func,
00699                          Coord(xp.Min(), yp.Min()),
00700                          Coord(xp.Max(), yp.Max()),
00701                          Coord(xp.Precision(), yp.Precision()));
00702   }
00703 
00704   assert(0 && "This should never happen");
00705 }
00706 
00707 
00708 //----------------------------------------------------------------------
00709 TGraph* NC::FitMaster::Get1DProjection(ICallableND* chiSqrFunc,
00710                                        const vector<NCParameter>& params,
00711                                        NCType::EFitParam x,
00712                                        double& leftErr,
00713                                        double& rightErr,
00714                                        vector<TGraph>& marg_graphs)
00715 {
00716   const int xi = fCoordConv.FitterIndex(x);
00717   const NCParameter xp = fCoordConv.ParameterForFitParam(x);
00718 
00719   if(fContourMethod == 0){ // simple
00720     MarginalizeSimple func(chiSqrFunc, params, fTryPreviousMinimum, xi, -1);
00721     return CreateOneDimProjection(&func, xp, fMinChiSqr, leftErr, rightErr, marg_graphs);
00722   }
00723 
00724   if(fContourMethod == 1 || fContourMethod == 2){ // hybrid or minuit
00725     MarginalizeHybrid func(chiSqrFunc, params, fTryPreviousMinimum, xi, -1);
00726     return CreateOneDimProjection(&func, xp, fMinChiSqr, leftErr, rightErr, marg_graphs);
00727   }
00728 
00729   assert(0 && "This should never happen");
00730 }
00731 
00732 
00733 //----------------------------------------------------------------------
00734 Registry* NC::FitMaster::GetBestFitPointAsRegistry() const
00735 {
00736   Registry* rBestFit = new Registry;
00737   rBestFit->SetName("bestFit_registry");
00738   rBestFit->UnLockKeys();
00739   rBestFit->UnLockValues();
00740 
00741   for(unsigned int n = 0; n < fMinCoord.size(); ++n){
00742     rBestFit->Set(fCoordConv.ParameterForFitterIndex(n).ShortName().c_str(),
00743                   fMinCoord[n]);
00744   }
00745 
00746   rBestFit->Set("best_chisq", fMinChiSqr);
00747 
00748   for(OneSigmaErrors::const_iterator it = fOneSigmaErrors.begin();
00749       it != fOneSigmaErrors.end(); ++it){
00750     const string name = it->first;
00751     const double lo = it->second.first;
00752     const double hi = it->second.second;
00753     rBestFit->Set((name+"_one_sigma_up").c_str(), lo);
00754     rBestFit->Set((name+"_one_sigma_down").c_str(), hi);
00755   }
00756 
00757   for(ChisqMargWithFixed::const_iterator it = fChisqsMargWithFixed.begin();
00758       it != fChisqsMargWithFixed.end(); ++it){
00759     const string name = it->first;
00760     const double chisq = it->second;
00761     rBestFit->Set(("chisq_marg_"+name+"_fixed").c_str(), chisq);
00762   }
00763 
00764   return rBestFit;
00765 }
00766 
00767 
00768 //----------------------------------------------------------------------
00769 void NC::FitMaster::
00770 SetFixedValuesForMarginalization(const NC::OscProb::OscPars* pars)
00771 {
00772   fFixedValsForMarg = pars;
00773 }
00774 
00775 
00776 //----------------------------------------------------------------------
00777 void NC::FitMaster::MargWithFixedVals(const ICallableND* chiSqrFunc)
00778 {
00779   TStopwatch sw;
00780 
00781   const vector<NCType::EFitParam> axes = GetUniqueAxes();
00782 
00783   for(unsigned int nAxis = 0; nAxis < axes.size(); ++nAxis){
00784     const NCType::EFitParam x = axes[nAxis];
00785 
00786     const NCParameter xPar = fCoordConv.ParameterForFitParam(x);
00787 
00788     const int fixIndex = fCoordConv.FitterIndex(x);
00789     CoordNDim fix = fCoordConv.CoordNDimFromOscPars(fFixedValsForMarg);
00790     vector<int> vary;
00791     for(unsigned int n = 0; n < fix.size(); ++n){
00792       if(int(n) != fixIndex) vary.push_back(n);
00793     }
00794     FixVars fv(chiSqrFunc, fix, vary);
00795 
00796     vector<NCParameter> pars;
00797     for(unsigned int n = 0; n < fCoordConv.fFitParams.size(); ++n){
00798       if(int(n) != fixIndex) pars.push_back(fCoordConv.fFitParams[n]);
00799     }
00800     // Copy the increased precision used in projections, for fairness.
00801     for(unsigned int n = 0; n < pars.size(); ++n){
00802       pars[n].SetPrecision(pars[n].Precision()/10);
00803     }
00804 
00805     MinFinderSimple mf(pars, false, false, &fv); // ???
00806 
00807     MSG("NCFitMaster", Msg::kInfo) << "Holding " << xPar.ShortName()
00808                                    << " fixed at " << fix[fixIndex]
00809                                    << " while marginalizing over other"
00810                                    << " parameters..." << endl;
00811 
00812     CoordNDim junk;
00813     const double chisq = mf.FindMin(junk);
00814 
00815     fChisqsMargWithFixed[xPar.ShortName()] = chisq;
00816   } // end for nAxis
00817 
00818   MSG("NCFitMaster", Msg::kInfo) << "Marginalizations took ";
00819   sw.Print("m");
00820 }
00821 
00822 
00823 //----------------------------------------------------------------------
00824 void NC::FitMaster::DrawAndWriteContourGraphs()
00825 {
00826   assert(fXaxes.size() == fYaxes.size());
00827   for(unsigned int n = 0; n < fXaxes.size(); ++n){
00828     const NCParameter xPar = fCoordConv.ParameterForFitParam(fXaxes[n]);
00829     const NCParameter yPar = fCoordConv.ParameterForFitParam(fYaxes[n]);
00830 
00831     const TString canvasName = "contours_"+xPar.ShortName()+"_"+yPar.ShortName();
00832 
00833     const double xBest = fMinCoord[fCoordConv.FitterIndex(fXaxes[n])];
00834     const double yBest = fMinCoord[fCoordConv.FitterIndex(fYaxes[n])];
00835 
00836     TLegend leg(0.75, 0.75, 0.95, 0.95);
00837     leg.SetBorderSize(0);
00838 
00839     TCanvas canv(canvasName);
00840     TH2* forceAxes = fCoordConv.AxesForParameters("", "", fXaxes[n], fYaxes[n]);
00841     forceAxes->SetDirectory(0); // Don't write out useless axes to disk.
00842     forceAxes->GetXaxis()->CenterTitle();
00843     forceAxes->GetYaxis()->CenterTitle();
00844     forceAxes->Draw();
00845     int trueconf = 0; // because some confidences were never written, need to keep track of the effective index.
00846     for(int conf = 0; conf < 3; ++conf){
00847       if(conf == 0 && !fWant68) continue;
00848       if(conf == 1 && !fWant90) continue;
00849       if(conf == 2 && !fWant99) continue;
00850       TGraph* contGraph = fContourGraphs[trueconf*fXaxes.size()+n];
00851       if(contGraph && contGraph->GetN() > 0){
00852         const TString confText = (conf == 0) ? "68" : ( (conf == 1) ? "90" : "99");
00853         leg.AddEntry(contGraph, confText+"% Confidence Level", "l");
00854         contGraph->SetName(canvasName+confText+"Graph");
00855         contGraph->Draw("l");
00856         gDirectory->Append(contGraph);
00857       }
00858       ++trueconf;
00859     }
00860 
00861     TMarker bestFit(xBest, yBest, kFullStar);
00862     bestFit.SetMarkerSize(2);
00863     bestFit.SetMarkerColor(kBlack);
00864     bestFit.Draw("p same");
00865 
00866     leg.AddEntry(&bestFit, "Best Fit Point", "p");
00867     leg.Draw();
00868 
00869     canv.Write();
00870   }
00871 
00872   for(unsigned int n = 0; n < fMarginalGraphs.size(); ++n){
00873     vector<TGraph>& gs = fMarginalGraphs[n];
00874     if(gs.empty()) continue;
00875     TCanvas c(TString::Format("marg_vars_%s_canv", gs[0].GetName()).Data());
00876 
00877     double maxx = 0;
00878     for(unsigned int i = 0; i < gs.size(); ++i){
00879       double x, y;
00880       gs[i].GetPoint(gs[i].GetN()-1, x, y);
00881       if(x > maxx) maxx = x;
00882     }
00883 
00884     TH2D h("h", "Marginalized variables",
00885            100, 0, maxx, 100, -2, 4.5);
00886     h.Draw();
00887     TLegend l(.5, .6, .85, .85);
00888     l.SetBorderSize(0);
00889     for(unsigned int m = 0; m < gs.size(); ++m){
00890       TGraph& g = gs[m];
00891       g.SetName(TString::Format("marg_graph_%d_%d", n, m).Data());
00892       g.SetMarkerStyle(kFullCircle);
00893       g.SetLineColor(1+m/4);
00894       g.SetMarkerColor(1+m/4);
00895       g.Draw("same lp");
00896       if(m%4==0) l.AddEntry(&g, "", "lp");
00897       //      g.Write();
00898     }
00899     l.Draw();
00900     c.Write();
00901   }
00902 }
00903 
00904 
00905 //----------------------------------------------------------------------
00906 void NC::FitMaster::DrawAndWriteChiSqGraphs()
00907 {
00908   for(unsigned int n = 0; n < fChiSqGraphs.size(); ++n){
00909     TGraph* graph = fChiSqGraphs[n];
00910 
00911     TCanvas* canv = new TCanvas(TString::Format("canv_%s", graph->GetName()));
00912 
00913     graph->GetXaxis()->CenterTitle();
00914 
00915     TAxis* yax = graph->GetYaxis();
00916     yax->CenterTitle();
00917     graph->Draw("al");
00918     const double ymax = yax->GetXmax();
00919     yax->SetRangeUser(0, ymax < 20 ? ymax : 20);
00920 
00921     canv->Write();
00922     graph->Write();
00923   }
00924 
00925   for(unsigned int n = 0; n < fMarginalGraphs1D.size(); ++n){
00926     vector<TGraph>& gs = fMarginalGraphs1D[n];
00927     if(gs.empty()) continue;
00928     TCanvas c(TString::Format("marg_vars_%s_canv", gs[0].GetName()).Data());
00929 
00930     double minx, maxx, y;
00931     gs[0].GetPoint(0, minx, y);
00932     gs[0].GetPoint(gs[0].GetN()-1, maxx, y);
00933 
00934     TH2D h("h", "Marginalized variables",
00935            100, minx, maxx, 100, -2, 4.5);
00936     h.Draw();
00937     TLegend l(.5, .6, .85, .85);
00938     l.SetBorderSize(0);
00939     for(unsigned int m = 0; m < gs.size(); ++m){
00940       TGraph& g = gs[m];
00941       g.SetName(TString::Format("marg_graph_%d_%d", n, m).Data());
00942       g.SetMarkerStyle(kFullCircle);
00943       g.SetLineColor(1+m);
00944       g.SetMarkerColor(1+m);
00945       g.Draw("same lp");
00946       l.AddEntry(&g, "", "lp");
00947     }
00948     l.Draw();
00949     c.Write();
00950   }
00951 }
00952 
00953 
00954 //---------------------------------------------------------------------
00955 void NC::FitMaster::DrawAndWriteLowResGrids()
00956 {
00957   for(unsigned int n = 0; n < fLowResGrids.size(); ++n){
00958     TString name = "canv";
00959     name += fLowResGrids[n]->GetName();
00960     TCanvas* canv = new TCanvas(name);
00961     fLowResGrids[n]->Draw("colz");
00962     canv->Write();
00963     fLowResGrids[n]->Write();
00964   }
00965 }
00966 
00967 
00968 //---------------------------------------------------------------------
00969 void NC::FitMaster::DrawAndWriteSlices()
00970 {
00971   for(unsigned int n = 0; n < fSlices.size(); ++n){
00972     TGraph& graph = fSlices[n];
00973 
00974     TCanvas* canv = new TCanvas(TString::Format("canv_%s", graph.GetName()));
00975 
00976     graph.GetXaxis()->CenterTitle();
00977 
00978     TAxis* yax = graph.GetYaxis();
00979     yax->CenterTitle();
00980     graph.Draw("al");
00981     //    const double ymax = yax->GetXmax();
00982     //    yax->SetRangeUser(0, ymax < 20 ? ymax : 20);
00983     yax->SetRangeUser(fMinChiSqr, fMinChiSqr+20);
00984 
00985     canv->Write();
00986     graph.Write();
00987   }
00988 }
00989 
00990 //---------------------------------------------------------------------
00991 void NC::FitMaster::DrawAndWrite2DSlices()
00992 {
00993   for(unsigned int n = 0; n < f2DSlices.size(); ++n){
00994     TH2D* h = f2DSlices[n];
00995 
00996     TCanvas* canv = new TCanvas(TString::Format("canv_%s", h->GetName()));
00997 
00998     h->GetXaxis()->CenterTitle();
00999     h->GetYaxis()->CenterTitle();
01000 
01001     h->Draw("colz");
01002 
01003     canv->Write();
01004     h->Write();
01005   }
01006 }

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