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

NCExtrapolation.cxx

Go to the documentation of this file.
00001 
00002 //$Id: NCExtrapolation.cxx,v 1.75 2007/10/26 20:21:43 brebel Exp $
00003 //
00004 //NCExtrapolation.cxx
00005 //
00006 //class to hold pdfs for doing nccc separation
00007 //
00008 //B. Rebel 2/2007
00010 
00011 #include "NCUtils/Extrapolation/NCExtrapolation.h"
00012 #include "MessageService/MsgService.h"
00013 #include "AnalysisNtuples/ANtpAnalysisInfo.h"
00014 #include "AnalysisNtuples/ANtpBeamInfo.h"
00015 #include "AnalysisNtuples/ANtpRecoInfo.h"
00016 #include "AnalysisNtuples/ANtpHeaderInfo.h"
00017 #include "AnalysisNtuples/ANtpTruthInfoBeam.h"
00018 #include "Conventions/DetectorType.h"
00019 
00020 #include "TCanvas.h"
00021 #include "TGraphErrors.h"
00022 #include "TGraph.h"
00023 #include "TObjArray.h"
00024 #include "TList.h"
00025 #include "TLegend.h"
00026 #include "TMath.h"
00027 #include "TMarker.h"
00028 #include "TROOT.h"
00029 
00030 #include <cassert>
00031 
00032 using namespace NCType;
00033 
00034 CVSID("$Id: NCExtrapolation.cxx,v 1.75 2007/10/26 20:21:43 brebel Exp $");
00035 
00036 
00037 // ---------------------------------------------------------------------
00038 // Minimize func within the hypercube r1-r2. Returns the minimum value found.
00039 // The position of the minimum is returned in minCoord, which has precision
00040 // in each direction given by precision.
00041 template<class Callable>
00042 double NCExtrapolation::FindMinNDim(const Callable& func,
00043                                     const CoordNDim& r1,
00044                                     const CoordNDim& r2,
00045                                     CoordNDim& minCoord,
00046                                     const CoordNDim& precision)
00047 {
00048   // How many points to put check in a box, along each axis.
00049   const int searchGridSize = 2;
00050 
00051   for(unsigned int n = 0; n < precision.size(); ++n) assert(precision[n] > 0);
00052   // Check that the arguments have consistent dimensionality.
00053   assert(r1.size() == r2.size() && r2.size() == precision.size());
00054   const int numDims = r1.size();
00055   minCoord.resize(numDims);
00056 
00057   // Algorithm assumes that all r1 values are less than the corresponding r2.
00058   for(int n = 0; n < numDims; ++n) assert(r1[n] <= r2[n]);
00059 
00060   // Check if we are precise enough in all directions.
00061   bool isPrecise = true;
00062   for(int n = 0; n < numDims; ++n)
00063     if(r2[n]-r1[n] > precision[n])
00064       isPrecise = false;
00065   // If so, average the corner coordinates and return.
00066   if(isPrecise){
00067     for(int n = 0; n < numDims; ++n) minCoord[n] = (r1[n]+r2[n])/2;
00068     return func(minCoord);
00069   }
00070 
00071   // How far to go in any direction to reach the next grid point.
00072   CoordNDim step(numDims);
00073   for(int n = 0; n < numDims; ++n) step[n] = (r2[n]-r1[n])/(searchGridSize+1);
00074 
00075   // This part is confusing: We need a grid of points inside the search
00076   // volume. toCheck will eventually hold all the points we want to look at.
00077   std::vector<CoordNDim> toCheck;
00078   // To start with just insert the grid point nearest to r1.
00079   CoordNDim firstPoint(numDims);
00080   for(int n = 0; n < numDims; ++n) firstPoint[n] = r1[n]+step[n];
00081   toCheck.push_back(firstPoint);
00082 
00083   // Now, for every dimension...
00084   for(int n = 0; n < numDims; ++n){
00085     // ...we need to loop over all the points in the list so far...
00086     const int iMax = toCheck.size();
00087     for(int i = 0; i < iMax; ++i){
00088       for(int d = 2; d <= searchGridSize; ++d){
00089         //...copy that point...
00090         CoordNDim toAdd = toCheck[i];
00091         // ...and modify the value of the nth coordinate to be each of the
00092         // searchGridSize points along this dimension...
00093         toAdd[n] = r1[n]+d*step[n];
00094         // ...before appending this new point into the list of places to check.
00095         toCheck.push_back(toAdd);
00096       }
00097     }
00098   }
00099 
00100 
00101   // The minimimum value of func() found so far. FLT_MAX = infinity.
00102   double funcMin = FLT_MAX;
00103   for(unsigned int n = 0; n < toCheck.size(); ++n){
00104     const double funcVal = func(toCheck[n]);
00105     if(funcVal < funcMin){
00106       funcMin = funcVal;
00107       minCoord = toCheck[n];
00108     }
00109   }
00110 
00111   CoordNDim r1New = minCoord;
00112   CoordNDim r2New = minCoord;
00113 
00114   // The new hypercube to search in is the lowest point we found above
00115   // plus or minus one grid size in every direction.
00116   for(int n = 0; n < numDims; ++n){
00117     r1New[n] -= step[n];
00118     r2New[n] += step[n];
00119   }
00120 
00121   return FindMinNDim(func, r1New, r2New, minCoord, precision);
00122 }
00123 
00124 // ---------------------------------------------------------------------
00125 // Find contour of height 'height' in the function 'func'. Search will be
00126 // to precision 'precision'. You must pass the previously located minimum
00127 // of the function in 'minCoord'. The contour must be continuous, finite
00128 // and closed.
00129 template<class Callable>
00130 std::vector<Coord> NCExtrapolation::FindContour(const Callable& func,
00131                                                 const Coord& minCoord,
00132                                                 const double& height,
00133                                                 const Coord& precision)
00134 {
00135   const double dx = precision.x;
00136   const double dy = precision.y;
00137 
00138   typedef pair<int, int> Box; // first == left, second == top
00139 
00140   std::map<Box, bool> results; // Is this box already in the result set?
00141   std::vector<Box> todo;
00142 
00143   // Top left corner of the box containing the best fit.
00144   const int bfxi = int(minCoord.x/dx);
00145   const int bfyi = int(minCoord.y/dy);
00146 
00147   // Walk to the left
00148   for(int x = bfxi; ; --x){
00149     // As soon as we exceed the contour
00150     if(func(Coord(x*dx, bfyi*dy)) > height){
00151       // make it the first element in the todo list
00152       todo.push_back(Box(x, bfyi));
00153       // and stop going left.
00154       break;
00155     }
00156   }
00157 
00158   std::vector<Coord> contour;
00159 
00160   while(!todo.empty()){
00161     Box now = todo.back();
00162     todo.pop_back();
00163 
00164     // We end up evaluating the function multiple times at each point, so are
00165     // relying heavily on the cacheing done in GetChiSqrFromDerived()
00166 
00167     // Evaluate the function at all the corners.
00168     const double topleft =     func(Coord( now.first   *dx,  now.second   *dy));
00169     const double topright =    func(Coord((now.first+1)*dx,  now.second   *dy));
00170     const double bottomleft =  func(Coord( now.first   *dx, (now.second+1)*dy));
00171     const double bottomright = func(Coord((now.first+1)*dx, (now.second+1)*dy));
00172 
00173     // For each side of the box: see if one corner is high and the other low.
00174     // If so, and if the box adjacent on this side isn't already part of the
00175     // results, then append the adjacent box to the todo list and linearly
00176     // interpolate to find where to put the contour point on that edge.
00177     if( (topleft-height)*(topright-height) <= 0 ){
00178       Box up(now.first, now.second-1);
00179       if(!results[up]){
00180         todo.push_back(up);
00181         results[up] = true;
00182         contour.push_back(Coord((now.first+(height-topleft)/(topright-topleft))*dx, now.second*dy));
00183       }
00184     }
00185     if( (bottomleft-height)*(bottomright-height) <= 0){
00186       Box down(now.first, now.second+1);
00187       if(!results[down]){
00188         todo.push_back(down);
00189         results[down] = true;
00190         contour.push_back(Coord((now.first+(height-bottomleft)/(bottomright-bottomleft))*dx, (now.second+1)*dy));
00191       }
00192     }
00193     if( (topleft-height)*(bottomleft-height) <= 0){
00194       Box left(now.first-1, now.second);
00195       if(!results[left]){
00196         todo.push_back(left);
00197         results[left] = true;
00198         contour.push_back(Coord(now.first*dx, (now.second+(height-topleft)/(bottomleft-topleft))*dy));
00199       }
00200     }
00201     if( (topright-height)*(bottomright-height) <=0 ){
00202       Box right(now.first+1, now.second);
00203       if(!results[right]){
00204         todo.push_back(right);
00205         results[right] = true;
00206         contour.push_back(Coord((now.first+1)*dx, (now.second+(height-topright)/(bottomright-topright))*dy));
00207       }
00208     }
00209   }
00210 
00211   if(contour.size()) contour.push_back(contour[0]); // Close the loop.
00212   return contour;
00213 }
00214 
00215 // ---------------------------------------------------------------------
00216 // Evaluate callable fun for a single varying value and some fixed values.
00217 // Initialise the fixed values by passing a CoordNDim fix with the
00218 // fixed values required, and the indices of the parameter to be varied.
00219 // Then, calling this object as a function will evaluate fun() with
00220 // these fixed values, and the values passed substituted in.
00221 template<class Callable>
00222 NCExtrapolation::GetFuncWithConstVars<Callable>::
00223 GetFuncWithConstVars(const Callable& fun,
00224                      const CoordNDim& fix,
00225                      const std::vector<int>& vary)
00226   :func(fun), fixed(fix), tovary(vary){}
00227 
00228 template<class Callable>
00229 double NCExtrapolation::GetFuncWithConstVars<Callable>::
00230 operator()(const CoordNDim& r) const
00231 {
00232   assert(tovary.size() == r.size());
00233   // For every parameter in the list of what we are to vary - substitute
00234   // in, in order, from the parameters we were passed.
00235   for(unsigned int n = 0; n < tovary.size(); ++n) fixed[tovary[n]] = r[n];
00236   return func(fixed);
00237 }
00238 
00239 
00240 // ---------------------------------------------------------------------
00241 // Minimize callable f with respect to one of its arguments. toMin is the
00242 // position of the argument that will be minimized min, max and prec give
00243 // its range and precision. Call the object like a function with a Coord2D,
00244 // the minimized parameter will be inserted in the correct place in the
00245 // argument sequence and the minimum value returned.
00246 template<class Callable>
00247 NCExtrapolation::GetFuncMinWRTSomeVars<Callable>::
00248 GetFuncMinWRTSomeVars(const Callable& f,
00249                       const std::vector<int>& toMin,
00250                       const CoordNDim& min,
00251                       const CoordNDim& max,
00252                       const CoordNDim& prec)
00253   :func(f), tomin(toMin), r1(min), r2(max), precision(prec)
00254 {
00255   assert(r1.size() == r2.size() && r2.size() == precision.size());
00256 
00257   // Where we are going to substiture in r.x and r.y
00258   xpos = ypos = -1;
00259   // Keep increasing the index tried until ypos is set.
00260   for(int n = 0; ypos < 0 ;++n){
00261     // Is n in the list of variables to minimize?
00262     bool inmin = false;
00263     for(unsigned int m = 0; m < tomin.size(); ++m)
00264       if(tomin[m] == n) inmin = true;
00265     // If not, then fill in xpos, and then ypos next time we find one.
00266     if(!inmin){
00267       if(xpos < 0)
00268         xpos = n;
00269       else
00270         ypos = n;
00271     }
00272   }
00273 }
00274 
00275 template<class Callable>
00276 double NCExtrapolation::GetFuncMinWRTSomeVars<Callable>::
00277 operator()(const Coord& r) const
00278 {
00279   CoordNDim fix(r1.size()+2);
00280   fix[xpos] = r.x;
00281   fix[ypos] = r.y;
00282   GetFuncWithConstVars<Callable> f(func, fix, tomin);
00283   CoordNDim minCoord;
00284   return NCExtrapolation::FindMinNDim(f, r1, r2, minCoord, precision);
00285 }
00286 
00287 
00288 // Override TMinuit's Eval function - so that this gets called as the
00289 // minimization function. Forward to the functoid passed in the constructor.
00290 template<class Callable>
00291 Int_t NCExtrapolation::NCExtrapolationMinuit<Callable>::Eval(Int_t /*npar*/,
00292                                                              Double_t* /*grad*/,
00293                                                              Double_t& fval,
00294                                                              Double_t* par,
00295                                                              Int_t flag)
00296 {
00297   // If we are being asked to do something that isn't just
00298   // calculate the function then we don't know how...
00299   assert(flag == 4);
00300   CoordNDim r(numpar);
00301   for(int n = 0; n < numpar; ++n) r[n] = par[n];
00302   fval = func(r);
00303   return 0;
00304 }
00305 
00306 
00307 // ---------------------------------------------------------------------
00308 // Minimize callable f with respect to some of its arguments. xcoord and
00309 // ycoord are positions of the arguments that shouldn't be minimized over.
00310 // min and max give the range of all parameters (values for the parameters
00311 //  not being minimized over are ignored).
00312 template<class Callable>
00313 NCExtrapolation::GetFuncMinWRTSomeVarsHybrid<Callable>::
00314 GetFuncMinWRTSomeVarsHybrid(const Callable& f,
00315                             const int xcoord,
00316                             const int ycoord,
00317                             const CoordNDim& min,
00318                             const CoordNDim& max)
00319   :func(f), xpos(xcoord), ypos(ycoord), r1(min), r2(max)
00320 {
00321   assert(r1.size() == r2.size());
00322   assert(xpos < int(r1.size()) && ypos < int(r1.size()));
00323   assert(ypos > xpos);
00324 
00325   pminu = new NCExtrapolationMinuit<Callable>(func, r1.size());
00326 
00327   pminu->SetPrintLevel(-1);
00328   //  minu.Command("set strategy 2"); // Be careful, instead of fast.
00329 
00330   for(int n = 0; n < int(r1.size()); ++n){
00331     const TString title = (n == xpos) ? "x" : (n == ypos) ? "y" : "";
00332     pminu->DefineParameter(n, title, (r1[n]+r2[n])/2, (r2[n]-r1[n])/4, 0, 0);
00333   }
00334 }
00335 
00336 template<class Callable>
00337 double NCExtrapolation::GetFuncMinWRTSomeVarsHybrid<Callable>::
00338 operator()(const Coord& r) const
00339 {
00340   assert(pminu);
00341 
00342   // Minuit tries to return parameters we don't want to keep.
00343   double junkd; int junki;
00344 
00345   // Add one to the index because of ridiculous fortran numbering scheme.
00346   double args1[] = {xpos+1, r.x};
00347   pminu->mnexcm("set param", args1, 2, junki);
00348   double args2[] = {ypos+1, r.y};
00349   pminu->mnexcm("set param", args2, 2, junki);
00350 
00351   pminu->mnfixp(xpos, junki);
00352   pminu->mnfixp(ypos-1, junki); // The parameters all got renumbered when we fixed x.
00353 
00354   // Simplex seems to be much faster than Migrad.
00355   // I think Migrad can fail when put in a bad place, and spends
00356   // a long time doing it.
00357   // However - I have had bad results using Simplex, so stick with Migrad.
00358   //  minu.mnsimp();
00359   if(pminu->Migrad())
00360     ;//return FLT_MAX; // this messes up the contours...
00361 
00362   double minval;
00363   pminu->mnstat(minval, junkd, junkd, junki, junki, junki);
00364   pminu->mnfree(0); // Free all the parameters, we will refix them next time round.
00365   return minval;
00366 }
00367 
00368 
00369 // ---------------------------------------------------------------------
00370 // Wrap NCExtrapolation::GetChiSqrForMap so that it can be called more simply,
00371 // additionally keep a cache to speed up repeated queries.
00372 // Evaluates points outside the physical region using a penalty term.
00373 
00374 std::map<CoordNDim, double> NCExtrapolation::GetChiSqrFromDerived::cache;
00375 
00376 double NCExtrapolation::GetChiSqrFromDerived::operator()(const CoordNDim& r) const
00377 {
00378   const std::map<CoordNDim, double>::const_iterator it = cache.find(r);
00379   if(it != cache.end()) return it->second;
00380   // Maximum cache size is arbitrary, tune for performance.
00381   const unsigned int maxCacheSize = int(1e7); // on the order of 10meg
00382   if(cache.size() > maxCacheSize) cache.clear();
00383 
00384   CoordNDim evalAt = r;
00385 
00386   if(usePenalty){
00387     // If the point is outside the physical region - move it to the boundary
00388     for(unsigned int n = 0; n < start.size(); ++n){
00389       if(r[n] < start[n]) evalAt[n] = start[n];
00390       if(r[n] > end[n]) evalAt[n] = end[n];
00391     }
00392   }
00393 
00394   double ret = p->GetChiSqrForMap(evalAt, names);
00395 
00396   if(usePenalty){
00397     // If we had to move the point then apply a quadratic penalty term.
00398     // The factor of 1000 was arrived at through trial and error.
00399     for(unsigned int n = 0; n < start.size(); ++n){
00400       const double wsqr = (start[n]-end[n])*(start[n]-end[n]);
00401       if(r[n] < start[n]) ret+=1e3*(start[n]-r[n])*(start[n]-r[n])/wsqr;
00402       if(r[n] > end[n]) ret+=1e3*(r[n]-end[n])*(r[n]-end[n])/wsqr;
00403     }
00404   }
00405 
00406   cache[r] = ret;
00407   return ret;
00408 }
00409 
00410 
00411 //......................................................................
00412 NCExtrapolation::NCExtrapolation() :
00413   fLocNormalization(0),
00414   fLocRelativeHadronicCalibration(0),
00415   fLocAbsoluteHadronicCalibration(0),
00416   fLocTrackEnergy(0),
00417   fLocNCBkg(0),
00418   fLocCCBkg(0),
00419   fLocPhi43(0),
00420   fLocPE(0),
00421   fLocPMu(0),
00422   fLocPS(0),
00423   fShowerScale(1.),
00424   fTrackScale(1.),
00425   fWeightNormalization(0.),
00426   fWeightRelativeHadronicCalibration(0.),
00427   fWeightAbsoluteHadronicCalibration(0.),
00428   fWeightTrackEnergy(0.),
00429   fWeightNCBkg(0.),
00430   fWeightCCBkg(0.),
00431   fUseWSDeltaMContour(false),
00432   fUseWSU3Contour(false),
00433   fUseWSWMuContour(false),
00434   fUseWSWEContour(false),
00435   fUseU3DeltaMContour(false),
00436   fUseU3WMuContour(false),
00437   fUseU3WEContour(false),
00438   fUseDeltaMWMuContour(false),
00439   fUseDeltaWEContour(false),
00440   fUseWEWMuContour(false)
00441 {
00442   fUtils = new NCAnalysisUtils();
00443   fUseCC = false;
00444   fUseNC = false;
00445 
00446   for(int i = 0; i < NCType::kNumParameters; ++i)
00447     fSystematicsToUse.push_back(false);
00448 
00449 
00450   fDeltaChiSqrDeltaMVsFSterile = new TH2F("DeltaChiSqrDeltaMVsFSterile",
00451                                           "",
00452                                           NCType::kNumFSterileBins,
00453                                           NCType::kFSterileStart,
00454                                           NCType::kFSterileEnd,
00455                                           NCType::kNumDeltaMSqrBins,
00456                                           NCType::kDeltaMSqrStart,
00457                                           NCType::kDeltaMSqrEnd);
00458   fDeltaChiSqrDeltaMVsFSterile->SetXTitle("f_{s}");
00459   fDeltaChiSqrDeltaMVsFSterile->SetYTitle("#Delta m^{2} (eV^{2})");
00460 
00461   fDeltaChiSqrSinSqrVsFSterile = new TH2F("DeltaChiSqrSinSqrVsFSterile",
00462                                           "",
00463                                           NCType::kNumFSterileBins,
00464                                           NCType::kFSterileStart,
00465                                           NCType::kFSterileEnd,
00466                                           NCType::kNumSinSqrBins,
00467                                           NCType::kSinSqrStart,
00468                                           NCType::kSinSqrEnd);
00469   fDeltaChiSqrSinSqrVsFSterile->SetXTitle("f_{s}");
00470   fDeltaChiSqrSinSqrVsFSterile->SetYTitle("sin^{2}(2#theta)");
00471 
00472   fDeltaChiSqrDeltaMVsSinSqr = new TH2F("DeltaChiSqrDeltaMVsSinSqr",
00473                                         "",
00474                                         NCType::kNumSinSqrBins,
00475                                         NCType::kSinSqrStart,
00476                                         NCType::kSinSqrEnd,
00477                                         NCType::kNumDeltaMSqrBins,
00478                                         NCType::kDeltaMSqrStart,
00479                                         NCType::kDeltaMSqrEnd);
00480   fDeltaChiSqrDeltaMVsSinSqr->SetXTitle("sin^{2}(2#theta)");
00481   fDeltaChiSqrDeltaMVsSinSqr->SetYTitle("#Delta m^{2} (eV^{2})");
00482 
00483 }
00484 
00485 //.......................................................................
00486 NCExtrapolation::NCExtrapolation(NCAnalysisUtils *utils,
00487                                  std::map<Int_t,double>& dataNear,
00488                                  std::map<Int_t,double>& mcNear,
00489                                  std::map<Int_t,double>& dataFar,
00490                                  std::map<Int_t,double>& mcFar,
00491                                  bool useCC, bool useNC) :
00492   fDataPOTNear(dataNear),
00493   fMCPOTNear(mcNear),
00494   fDataPOTFar(dataFar),
00495   fMCPOTFar(mcFar),
00496   fUseCC(useCC),
00497   fUseNC(useNC),
00498   fUtils(utils),
00499   fLocNormalization(0),
00500   fLocRelativeHadronicCalibration(0),
00501   fLocAbsoluteHadronicCalibration(0),
00502   fLocTrackEnergy(0),
00503   fLocNCBkg(0),
00504   fLocCCBkg(0),
00505   fLocPhi43(0),
00506   fLocPE(0),
00507   fLocPMu(0),
00508   fLocPS(0),
00509   fShowerScale(1.),
00510   fTrackScale(1.),
00511   fWeightNormalization(0.),
00512   fWeightRelativeHadronicCalibration(0.),
00513   fWeightAbsoluteHadronicCalibration(0.),
00514   fWeightTrackEnergy(0.),
00515   fWeightNCBkg(0.),
00516   fWeightCCBkg(0.)
00517 {
00518   BeamType::BeamType_t beam = BeamType::kL010z185i;
00519   int run = NCType::kRunI;
00520 
00521   for(std::map<Int_t,double>::const_iterator i = fDataPOTNear.begin();
00522       i != fDataPOTNear.end(); ++i){
00523 
00524     NCType::ConvertIndexToBeamRun(i->first, beam, run);
00525 
00526     MSG("NCExtrapolation", Msg::kInfo)
00527       << "fDataPOTNear["
00528       << BeamType::AsString(beam) << ", " << run << "] = "
00529       << i->second << endl;
00530   }
00531   for(std::map<Int_t,double>::const_iterator i = fMCPOTNear.begin();
00532       i != fMCPOTNear.end(); ++i){
00533 
00534     NCType::ConvertIndexToBeamRun(i->first, beam, run);
00535 
00536     MSG("NCExtrapolation", Msg::kInfo)
00537       << "fMCPOTNear["
00538       << BeamType::AsString(beam) << ", " << run << "] = "
00539       << i->second << endl;
00540   }
00541 
00542   for(std::map<Int_t,double>::const_iterator i = fDataPOTFar.begin();
00543       i != fDataPOTFar.end(); ++i){
00544 
00545     NCType::ConvertIndexToBeamRun(i->first, beam, run);
00546 
00547     MSG("NCExtrapolation", Msg::kInfo)
00548       << "fDataPOTFar["
00549       << BeamType::AsString(beam) << ", " << run << "] = "
00550       << i->second << endl;
00551   }
00552 
00553   for(std::map<Int_t,double>::const_iterator i = fMCPOTFar.begin();
00554       i != fMCPOTFar.end(); ++i){
00555 
00556     NCType::ConvertIndexToBeamRun(i->first, beam, run);
00557 
00558     MSG("NCExtrapolation", Msg::kInfo)
00559       << "fMCPOTFar["
00560       << BeamType::AsString(beam) << ", " << run << "] = "
00561       << i->second << endl;
00562   }
00563 
00564   for(int i = 0; i < NCType::kNumParameters; ++i){
00565     fSystematicsToUse.push_back(false);
00566     fSystematicsAdjust.push_back(NCType::kParameterDefaults[i]);
00567   }
00568 
00569 
00570   fDeltaChiSqrDeltaMVsFSterile = new TH2F("DeltaChiSqrDeltaMVsFSterile",
00571                                           "DeltaChiSqrDeltaMVsFSterile",
00572                                           NCType::kNumFSterileBins,
00573                                           NCType::kFSterileStart,
00574                                           NCType::kFSterileEnd,
00575                                           NCType::kNumDeltaMSqrBins,
00576                                           NCType::kDeltaMSqrStart,
00577                                           NCType::kDeltaMSqrEnd);
00578 
00579   fDeltaChiSqrSinSqrVsFSterile = new TH2F("DeltaChiSqrSinSqrVsFSterile",
00580                                           "DeltaChiSqrSinSqrVsFSterile",
00581                                           NCType::kNumFSterileBins,
00582                                           NCType::kFSterileStart,
00583                                           NCType::kFSterileEnd,
00584                                           NCType::kNumSinSqrBins,
00585                                           NCType::kSinSqrStart,
00586                                           NCType::kSinSqrEnd);
00587 
00588   fDeltaChiSqrDeltaMVsSinSqr = new TH2F("DeltaChiSqrDeltaMVsSinSqr",
00589                                         "DeltaChiSqrDeltaMVsSinSqr",
00590                                         NCType::kNumSinSqrBins,
00591                                         NCType::kSinSqrStart,
00592                                         NCType::kSinSqrEnd,
00593                                         NCType::kNumDeltaMSqrBins,
00594                                         NCType::kDeltaMSqrStart,
00595                                         NCType::kDeltaMSqrEnd);
00596 }
00597 
00598 //----------------------------------------------------------------------
00599 NCExtrapolation::~NCExtrapolation()
00600 {
00601 }
00602 
00603 //----------------------------------------------------------------------
00604 //this method allows the user to pass in appropriate settings for the
00605 //extrapolation such as locations of files, whether to generate the files
00606 //again, etc.  the registry comes from the job module GetConfig method
00607 void NCExtrapolation::Prepare(const Registry& r)
00608 {
00609   MSG("NCExtrapolation", Msg::kInfo) << "NCExtrapolation::Prepare(const Registry& r)"
00610                                      << endl;
00611   int         tmpb;  // a temp bool. See comment under DefaultConfig...
00612   int         tmpi;  // a temp int.
00613   double      tmpd;  // a temp double.
00614   const char* tmps;  // a temp string
00615 
00616   //get the value of theta_13
00617   if( r.Get("FixedTheta13", tmpd) ) fTheta13 = tmpd;
00618 
00619   //set the defaults for the systematic parameters
00620   //set them all off by default
00621   TString adjust = "Adjust";
00622   for(int i = 0; i < NCType::kNumParameters; ++i){
00623     if( r.Get(NCType::kParameterNames[i], tmpb)) fSystematicsToUse[i] = tmpb;
00624     if( r.Get(adjust + NCType::kParameterNames[i], tmpd)) fSystematicsAdjust[i] = tmpd;
00625   }
00626 
00627   MSG("NCExtrapolation", Msg::kInfo) << "PARAMETERS WE ARE USING:" << endl;
00628   for(int i = 0; i < NCType::kNumParameters; ++i){
00629     MSG("NCExtrapolation", Msg::kInfo) << i << ") "
00630                                        << NCType::kParameterNames[i]
00631                                        << " = " << fSystematicsToUse[i]
00632                                        << " with default = "
00633                                        << NCType::kParameterDefaults[i]
00634                                        << " adjust = "
00635                                        << fSystematicsAdjust[i] << endl;
00636   }
00637 
00638   tmpi = 0;
00639   tmps = "s";
00640 
00641   r.Get("LazyContoursUseMinuit", fLazyContoursUseMinuit);
00642   r.Get("LazyContoursWant68", fWant68);
00643   r.Get("LazyContoursWant90", fWant90);
00644   r.Get("LazyContoursWant99", fWant99);
00645   r.Get("LazyContoursWantFsterSinsq", fWantFsterSinsq);
00646   r.Get("LazyContoursWantFsterDmsq", fWantFsterDmsq);
00647   r.Get("LazyContoursWantSinsqDmsq", fWantSinsqDmsq);
00648   r.Get("AllowBestFitOutsideRange", fAllowBestFitOutsideRange);
00649   r.Get("AllowContoursOutsideRange", fAllowContoursOutsideRange);
00650 
00651   if(r.Get("UseWSDeltaMContour",  tmpb)) fUseWSDeltaMContour  = tmpb;
00652   if(r.Get("UseWSU3Contour",      tmpb)) fUseWSU3Contour      = tmpb;
00653   if(r.Get("UseWSWMuContour",     tmpb)) fUseWSWMuContour     = tmpb;
00654   if(r.Get("UseWSWEContour",      tmpb)) fUseWSWEContour      = tmpb;
00655   if(r.Get("UseU3DeltaMContour",  tmpb)) fUseU3DeltaMContour  = tmpb;
00656   if(r.Get("UseU3WMuContour",     tmpb)) fUseU3WMuContour     = tmpb;
00657   if(r.Get("UseU3WEContour",      tmpb)) fUseU3WEContour      = tmpb;
00658   if(r.Get("UseDeltaMWMuContour", tmpb)) fUseDeltaMWMuContour = tmpb;
00659   if(r.Get("UseDeltaWEContour",   tmpb)) fUseDeltaWEContour   = tmpb;
00660   if(r.Get("UseWEWMuContour",     tmpb)) fUseWEWMuContour     = tmpb;
00661   
00662   fXAxes.clear();
00663   fYAxes.clear();
00664     
00665   //set which axes to use in the contours
00666   if(fUseWSDeltaMContour)
00667     fXAxes.push_back(NCType::kFSterile);  fYAxes.push_back(NCType::kDeltaMSqr);
00668   if(fUseWSU3Contour)
00669     fXAxes.push_back(NCType::kFSterile);  fYAxes.push_back(NCType::kSinSqr);
00670   if(fUseWSWMuContour)
00671     fXAxes.push_back(NCType::kFSterile);  fYAxes.push_back(fLocPMu);
00672   if(fUseWSWEContour)
00673     fXAxes.push_back(NCType::kFSterile);  fYAxes.push_back(fLocPE);
00674   if(fUseU3DeltaMContour)
00675     fXAxes.push_back(NCType::kSinSqr);    fYAxes.push_back(NCType::kDeltaMSqr);
00676   if(fUseU3WMuContour)
00677     fXAxes.push_back(NCType::kSinSqr);    fYAxes.push_back(fLocPMu);
00678   if(fUseU3WEContour)
00679     fXAxes.push_back(NCType::kSinSqr);    fYAxes.push_back(fLocPE);
00680   if(fUseDeltaMWMuContour)
00681     fXAxes.push_back(NCType::kDeltaMSqr); fYAxes.push_back(fLocPMu);
00682   if(fUseDeltaWEContour)
00683     fXAxes.push_back(NCType::kDeltaMSqr); fYAxes.push_back(fLocPE);
00684   if(fUseWEWMuContour)
00685     fXAxes.push_back(fLocPE);             fYAxes.push_back(fLocPMu);
00686 
00687   int locCounter   = 2; // first three elements are osc parameters
00688   double max = 0.;
00689   double min = 0.;
00690 
00691   if (r.Get("Normalization", tmpb)){
00692     if ( tmpb == true ){
00693 
00694       min = -NCType::kParameterSigmas[NCType::kNormalization];
00695       max =  NCType::kParameterSigmas[NCType::kNormalization];
00696 
00697       fExtraVarsNames.push_back("Normalization");
00698       fExtraVarsMin.push_back( min );
00699       fExtraVarsMax.push_back( max );
00700       fExtraVarsPrec.push_back( TMath::Abs((max - min)*.01) );
00701       fLocNormalization = ++locCounter;
00702     }
00703   }
00704   if (r.Get("RelativeHadronicCalibration", tmpb)){
00705     if ( tmpb == true ){
00706 
00707       min = -NCType::kParameterSigmas[NCType::kRelativeHadronicCalibration];
00708       max =  NCType::kParameterSigmas[NCType::kRelativeHadronicCalibration];
00709 
00710       fExtraVarsNames.push_back("Relative Hadronic Calibration");
00711       fExtraVarsMin.push_back( min );
00712       fExtraVarsMax.push_back( max );
00713       fExtraVarsPrec.push_back( TMath::Abs((max - min)*.01) );
00714       fLocRelativeHadronicCalibration = ++locCounter;
00715     }
00716   }
00717   if (r.Get("AbsoluteHadronicCalibration", tmpb)){
00718     if ( tmpb == true ){
00719 
00720       min = -NCType::kParameterSigmas[NCType::kAbsoluteHadronicCalibration];
00721       max =  NCType::kParameterSigmas[NCType::kAbsoluteHadronicCalibration];
00722 
00723       fExtraVarsNames.push_back("Absolute Hadronic Calibration");
00724       fExtraVarsMin.push_back( min );
00725       fExtraVarsMax.push_back( max );
00726       fExtraVarsPrec.push_back( TMath::Abs((max - min)*.01) );
00727       fLocAbsoluteHadronicCalibration = ++locCounter;
00728     }
00729   }
00730   if (r.Get("TrackEnergy", tmpb)){
00731     if ( tmpb == true ){
00732 
00733       min = -NCType::kParameterSigmas[NCType::kTrackEnergy];
00734       max =  NCType::kParameterSigmas[NCType::kTrackEnergy];
00735 
00736       fExtraVarsNames.push_back("Track Energy");
00737       fExtraVarsMin.push_back( min );
00738       fExtraVarsMax.push_back( max );
00739       fExtraVarsPrec.push_back( TMath::Abs((max - min)*.01) );
00740       fLocTrackEnergy = ++locCounter;
00741     }
00742   }
00743   if (r.Get("NCBackground", tmpb)){
00744     if ( tmpb == true ){
00745 
00746       min = -NCType::kParameterSigmas[NCType::kNCBackground];
00747       max =  NCType::kParameterSigmas[NCType::kNCBackground];
00748 
00749       fExtraVarsNames.push_back("NC Background");
00750       fExtraVarsMin.push_back( min );
00751       fExtraVarsMax.push_back( max );
00752       fExtraVarsPrec.push_back( TMath::Abs((max - min)*.01) );
00753       fLocNCBkg = ++locCounter;
00754     }
00755   }
00756   if (r.Get("CCBackground", tmpb)){
00757     if ( tmpb == true ){
00758 
00759       min = -NCType::kParameterSigmas[NCType::kCCBackground];
00760       max =  NCType::kParameterSigmas[NCType::kCCBackground];
00761 
00762       fExtraVarsNames.push_back("CC Background");
00763       fExtraVarsMin.push_back( min );
00764       fExtraVarsMax.push_back( max );
00765       fExtraVarsPrec.push_back( TMath::Abs((max - min)*.01) );
00766       fLocCCBkg = ++locCounter;
00767     }
00768   }
00769   if (r.Get("WE", tmpb)){
00770     if ( tmpb == true ){
00771 
00772       min = 0.;
00773       max = 0.2;
00774 
00775       fExtraVarsNames.push_back("w_{e}");
00776       fExtraVarsMin.push_back( min );
00777       fExtraVarsMax.push_back( max );
00778       fExtraVarsPrec.push_back( TMath::Abs((max - min)*.01) );
00779       fLocPE = ++locCounter;
00780 
00781       cout << "w_e location = " << fLocPE << endl;
00782     }
00783   }
00784   if (r.Get("WMu", tmpb)){
00785     if ( tmpb == true ){
00786 
00787       min = 0.;
00788       max = 0.5;
00789 
00790       fExtraVarsNames.push_back("w_{#mub}");
00791       fExtraVarsMin.push_back( min );
00792       fExtraVarsMax.push_back( max );
00793       fExtraVarsPrec.push_back( TMath::Abs((max - min)*.01) );
00794       fLocPMu = ++locCounter;
00795 
00796       cout << "w_mub location = " << fLocPMu << endl;
00797     }
00798   }
00799 //   if (r.Get("Phi43", tmpb)){
00800 //     if ( tmpb == true ){
00801 
00802 //       min = 0.;
00803 //       max = 2.*TMath::Pi();
00804 
00805 //       fExtraVarsNames.push_back("phi_43");
00806 //       fExtraVarsMin.push_back( min );
00807 //       fExtraVarsMax.push_back( max );
00808 //       fExtraVarsPrec.push_back( TMath::Abs((max - min)*.01) );
00809 //       fLocPhi43 = ++locCounter;
00810 
00811 //       cout << "phi_43 location = " << fLocPhi43 << endl;
00812 //     }
00813 //   }
00814 
00815   return;
00816 }
00817 
00818 //----------------------------------------------------------------------
00819 void NCExtrapolation::AddEvent(ANtpHeaderInfo *headerInfo,
00820                                ANtpBeamInfo *beamInfo,
00821                                ANtpRecoInfo *recoInfo,
00822                                ANtpAnalysisInfo *analysisInfo,
00823                                ANtpTruthInfoBeam *truthInfo,
00824                                int runType,
00825                                bool useMCAsData,
00826                                int fileType)
00827 {
00828 
00829   //method to add events to near detector beams.  all methods should see
00830   //the same near detector spectra, so there is no loss of generalization.
00831 
00832   //dont bother with events outside the fiducial volume
00833   if(recoInfo->inFiducialVolume < 1 ||
00834      (headerInfo->detector == (int)Detector::kNear
00835       && recoInfo->isCleanHighMultSnarl < 1)
00836      )
00837      return;
00838 
00839   //need to check if this type of beam already exists in the vector.
00840   //if so add the event to that beam. if not, make it the beam then
00841   //the add event to it
00842   Detector::Detector_t detector = Detector::kNear;
00843   BeamType::BeamType_t beamType = BeamType::FromZarko(beamInfo->beamType);
00844   int beamRunIndex = NCType::ConvertBeamRunToIndex(beamType, runType);
00845   //MC events only have run type = NCType::kRunI
00846   int beamRunIndexMC = NCType::ConvertBeamRunToIndex(beamType, NCType::kRunI);
00847   double dataPOT = fDataPOTNear[beamRunIndex];
00848   double mcPOT = fMCPOTNear[beamRunIndexMC];
00849   if(headerInfo->detector == (int)Detector::kFar){
00850     detector = Detector::kFar;
00851     dataPOT = fDataPOTFar[beamRunIndex];
00852     mcPOT = fMCPOTFar[beamRunIndexMC];
00853   }
00854   int beam = FindBeamIndex(detector, beamType, runType, true, dataPOT, mcPOT);
00855 
00856   fBeams[beam].AddEvent(headerInfo, beamInfo, recoInfo,
00857                         analysisInfo, truthInfo, useMCAsData, fileType);
00858 
00859   //if this is MC and not useMCAsData, look to see if there are
00860   //other run types for the same beam.  default run type for MC is
00861   //NCType::kRunI
00862   if(headerInfo->dataType == (int)SimFlag::kMC && !useMCAsData){
00863     for(int i = NCType::kRunII; i < NCType::kMaxRun+1; ++i){
00864       beam = FindBeamIndex(detector, beamType, i);
00865       if(beam < 100)
00866         fBeams[beam].AddEvent(headerInfo, beamInfo, recoInfo,
00867                               analysisInfo, truthInfo, useMCAsData, fileType);
00868     }//end loop over possible runs
00869   }//end if mc and needs to be added to other runs for this beam
00870 
00871   return;
00872 }
00873 
00874 //----------------------------------------------------------------------
00875 void NCExtrapolation::PrepareNearDetector()
00876 {
00877   return;
00878 }
00879 
00880 //----------------------------------------------------------------------
00881 int NCExtrapolation::GetExtrapolationType() const
00882 {
00883   return fExtrapolationType;
00884 }
00885 
00886 //----------------------------------------------------------------------
00887 TH1F* NCExtrapolation::GetPredictedSpectrum(Detector::Detector_t detector,
00888                                             BeamType::BeamType_t beamType,
00889                                             int nccc)
00890 {
00891   TH1F *spectrum = 0;
00892 
00893   for(uint i = 0; i < fBeams.size(); ++i){
00894     if(fBeams[i].GetBeamType() == beamType
00895        && fBeams[i].GetDetector() == detector)
00896       spectrum = fBeams[i].GetMCHistogram(nccc);
00897   }
00898 
00899   return spectrum;
00900 }
00901 
00902 //----------------------------------------------------------------------
00903 TH1F* NCExtrapolation::GetFitSpectrum(Detector::Detector_t detector,
00904                                       BeamType::BeamType_t beamType,
00905                                       int nccc)
00906 {
00907   TH1F *spectrum = 0;
00908 
00909   for(uint i = 0; i < fBeams.size(); ++i){
00910     if(fBeams[i].GetBeamType() == beamType
00911        && fBeams[i].GetDetector() == detector)
00912       spectrum = fBeams[i].GetMCFitHistogram(nccc);
00913   }
00914 
00915   return spectrum;
00916 }
00917 
00918 //----------------------------------------------------------------------
00919 TH1F* NCExtrapolation::GetBackgroundSpectrum(Detector::Detector_t detector,
00920                                              BeamType::BeamType_t beamType,
00921                                              int nccc)
00922 {
00923   TH1F *spectrum = 0;
00924 
00925   for(uint i = 0; i < fBeams.size(); ++i){
00926     if(fBeams[i].GetBeamType() == beamType
00927        && fBeams[i].GetDetector() == detector)
00928       spectrum = fBeams[i].GetMCBackgroundHistogram(nccc);
00929   }
00930 
00931   return spectrum;
00932 }
00933 
00934 //----------------------------------------------------------------------
00935 TGraphAsymmErrors* NCExtrapolation::GetDataSpectrum(Detector::Detector_t detector,
00936                                                     BeamType::BeamType_t beamType,
00937                                                     int nccc)
00938 {
00939   TGraphAsymmErrors *spectrum = 0;
00940 
00941   for(uint i = 0; i < fBeams.size(); ++i){
00942     if(fBeams[i].GetBeamType() == beamType
00943        && fBeams[i].GetDetector() == detector)
00944       spectrum = fBeams[i].GetDataGraph(nccc);
00945   }
00946 
00947   return spectrum;
00948 }
00949 
00950 //----------------------------------------------------------------------
00951 void NCExtrapolation::ResetBeams()
00952 {
00953 
00954   for(uint i = 0; i < fBeams.size(); ++i) fBeams[i].Reset();
00955 
00956   return;
00957 }
00958 
00959 //----------------------------------------------------------------------
00960 NCBeam NCExtrapolation::GetNCBeam(Detector::Detector_t det,
00961                                   BeamType::BeamType_t beam,
00962                                   int runType)
00963 {
00964   int beamPos = FindBeamIndex(det, beam, runType);
00965 
00966   if(beamPos > 100){
00967 
00968     MSG("NCExtrapolation", Msg::kWarning) << "could not find chosen beam "
00969                                           << BeamType::AsString(beam)
00970                                           << " in " << Detector::AsString(det)
00971                                           << " detector, returning empty beam "
00972                                           << beamPos
00973                                           << endl;
00974     NCBeam empty;
00975     return empty;
00976   }
00977 
00978   return fBeams[beamPos];
00979 
00980 }
00981 
00982 //----------------------------------------------------------------------
00983 void NCExtrapolation::DrawContours(TH2F *deltaChiSqr,
00984                                    double bestX,
00985                                    double bestY)
00986 {
00987 
00988   TString name = deltaChiSqr->GetName();
00989   TString clName[] = {name+"68CL", name+"90CL", name+"99CL"};
00990   TString drawOpt[] = {"cont1", "cont1same", "cont1same"};
00991   TCanvas *canv = new TCanvas("contoursCanv"+name,
00992                               "contours", 150, 10, 900, 600);
00993 
00994   //make histograms with the same dimensions as the one passed
00995   //into the method
00996   vector<TH2F *> contours;
00997   double contVals[] = {2.3, 4.6, 9.2};
00998   double contVals1[] = {0., 0., 1.e6};
00999   int lineStyles[] = {3, 2, 1};
01000   int colors[] = {2, 4, 1};
01001   int colors1[] = {10, 4, 10};
01002   for(int i = 0; i < 3; ++i){
01003     contours.push_back(new TH2F(clName[i], "",
01004                                 deltaChiSqr->GetXaxis()->GetNbins(),
01005                                 deltaChiSqr->GetXaxis()->GetXmin(),
01006                                 deltaChiSqr->GetXaxis()->GetXmax(),
01007                                 deltaChiSqr->GetYaxis()->GetNbins(),
01008                                 deltaChiSqr->GetYaxis()->GetXmin(),
01009                                 deltaChiSqr->GetYaxis()->GetXmax()));
01010     contVals1[2] = contVals[i];
01011     colors1[2] = colors[i];
01012     contours[i]->Add(deltaChiSqr);
01013     contours[i]->SetContour(3, contVals1);
01014     contours[i]->SetLineStyle(lineStyles[i]);
01015     contours[i]->SetLineColor(colors[i]);
01016     contours[i]->Draw(drawOpt[i]);
01017   }
01018 
01019   TMarker *bestFit = new TMarker(bestX, bestY, 29);
01020   bestFit->SetMarkerSize(3.5);
01021   bestFit->SetMarkerColor(1);
01022   bestFit->Draw("p");
01023   TString bestFitLabel = "Best Fit ";
01024   bestFitLabel += deltaChiSqr->GetXaxis()->GetTitle() + TString::Format(" = %3.2e,", bestX);
01025   bestFitLabel += deltaChiSqr->GetYaxis()->GetTitle() + TString::Format(" = %3.2e", bestY);
01026 
01027   TLegend *leg = new TLegend(0.75, 0.75, 0.95, 0.95);
01028   leg->SetBorderSize(0);
01029   leg->AddEntry(contours[0], "68% Confidence Level", "l");
01030   leg->AddEntry(contours[1], "90% Confidence Level", "l");
01031   leg->AddEntry(contours[2], "99% Confidence Level", "l");
01032   leg->AddEntry(bestFit, bestFitLabel, "p");
01033   leg->Draw();
01034 
01035   canv->Update();
01036 
01037   // Append the canvas object to the current directory
01038   // otherwise it can't be found and saved later
01039   gDirectory->Append(canv);
01040 
01041   return;
01042 
01043 }
01044 
01045 //----------------------------------------------------------------------
01046 //loop over all the beams.  draw pairs of plots for each beam in the
01047 //chosen detector - NC and CC
01048 void NCExtrapolation::DrawBestFitSpectra(Detector::Detector_t det)
01049 {
01050 
01051   for(uint b = 0; b < fBeams.size(); ++b){
01052     if(fBeams[b].GetDetector() != det) continue;
01053 
01054     TString name = "bestFitSpectraCanv"+NCType::kExtrapolationNames[fExtrapolationType];
01055     name += DetectorType::AsString(det);
01056     name += BeamType::AsString(fBeams[b].GetBeamType());
01057     name += NCType::kRunNames[fBeams[b].GetRunType()];
01058     TCanvas *canv = new TCanvas(name, name, 150, 10, 1200, 300);
01059     TPad *pad1 = new TPad(name+"pad1", "", 0.00, 0.0, 0.50, 1.0, 10);
01060     TPad *pad2 = new TPad(name+"pad2", "", 0.50, 0.0, 1.00, 1.0, 10);
01061     pad1->Draw();
01062     pad2->Draw();
01063     pad1->cd();
01064 
01065     TString bestDeltaM;
01066     bestDeltaM.Format("#Deltam^{2} = %5.4f", fBestDeltaMSqr);
01067     TString bestSinSqr;
01068     bestSinSqr.Format("sin^{2}(2#theta) = %3.2f", fBestSinSqr);
01069     TString bestFSterile;
01070     bestFSterile.Format("f_{s} = %3.2f", fBestFSterile);
01071     TString minChiSqr;
01072     minChiSqr.Format("#chi^{2} = %3.2f", fMinChiSqr);
01073 
01074     double maxY = 0.;
01075 
01076     for(int i = 0; i < 2; ++i){
01077       if(i > 0){
01078         pad2->cd();
01079       }
01080 
01081       maxY = 1.3*TMath::Max(fBeams[b].GetMCHistogram(i)->GetMaximum(),
01082                             fBeams[b].GetDataGraph(i)->GetHistogram()->GetMaximum());
01083 
01084       fBeams[b].GetMCHistogram(i)->SetMaximum(maxY);
01085       fBeams[b].GetMCHistogram(i)->Draw();
01086       //if the fit histogram was filled, draw the fits
01087       if(fBeams[b].GetMCFitHistogram(i)->Integral() > 0.){
01088         fBeams[b].GetMCFitHistogram(i)->Draw("same");
01089         fBeams[b].GetMCBackgroundHistogram(i)->Draw("same");
01090         fBeams[b].GetMCFitNuMuToNuTauHistogram(i)->Draw("same");
01091         fBeams[b].GetMCFitNuEToNuEHistogram(i)->Draw("same");
01092         fBeams[b].GetMCFitNuMuToNuEHistogram(i)->Draw("same");
01093       }
01094       else{
01095         //no fit, no point drawing NuMuToNuTau or NuMuToNuE
01096         fBeams[b].GetMCNoFitBackgroundHistogram(i)->Draw("same");
01097         fBeams[b].GetMCNoFitNuEToNuEHistogram(i)->Draw("same");
01098       }
01099 
01100       fBeams[b].GetDataGraph(i)->Draw("pe1same");
01101 
01102       TLegend *leg = new TLegend(0.75, 0.75, 0.95, 0.95);
01103       leg->SetBorderSize(0);
01104       leg->AddEntry(fBeams[b].GetDataGraph(i), "Data", "lp");
01105       leg->AddEntry(fBeams[b].GetMCHistogram(i), "Monte Carlo (Nominal)", "f");
01106       if(fBeams[b].GetMCFitHistogram(i)->Integral() > 0.){
01107         leg->AddEntry(fBeams[b].GetMCFitHistogram(i), "Monte Carlo (Best Fit)", "l");
01108         leg->AddEntry(fBeams[b].GetMCBackgroundHistogram(i), "Background", "lf");
01109         leg->AddEntry(fBeams[b].GetMCFitNuMuToNuTauHistogram(i), "Background - #nu_{#tau} CC", "lf");
01110         leg->AddEntry(fBeams[b].GetMCFitNuEToNuEHistogram(i), "Background - Beam #nu_{e} CC", "lf");
01111         leg->AddEntry(fBeams[b].GetMCFitNuMuToNuEHistogram(i), "Background - #nu_{e} CC", "lf");
01112       }
01113       else{
01114         leg->AddEntry(fBeams[b].GetMCNoFitBackgroundHistogram(i), "Background", "lf");
01115         leg->AddEntry(fBeams[b].GetMCNoFitNuEToNuEHistogram(i), "Background - Beam #nu_{e} CC", "lf");
01116       }
01117 //       leg->AddEntry(fBeams[b].GetDataGraph(i), bestDeltaM, "");
01118 //       leg->AddEntry(fBeams[b].GetDataGraph(i), bestFSterile, "");
01119 //       leg->AddEntry(fBeams[b].GetDataGraph(i), bestSinSqr, "");
01120 //       leg->AddEntry(fBeams[b].GetDataGraph(i), minChiSqr, "");
01121       leg->Draw();
01122 
01123     }//end loop over NC/CC
01124 
01125 
01126     canv->Update();
01127 
01128     // Append the canvas object to the current directory
01129     // otherwise it can't be found and saved later
01130     gDirectory->Append(canv);
01131 
01132   }//end loop over beams
01133 
01134   return;
01135 }
01136 
01137 // Only in case of NoMinuit
01138 //----------------------------------------------------------------------
01139 void NCExtrapolation::DrawAndWriteLazyContours()
01140 {
01141   assert(fLazyContours.size() == 9);
01142 
01143   for(int n = 0; n < 3; ++n){
01144     TString canvasName, axisLabels;
01145     double xStart = 0.;
01146     double xEnd = 0.;
01147     double yStart = 0.;
01148     double yEnd = 0.;
01149     double xBest = 0.;
01150     double yBest = 0.;
01151 
01152     switch(n){
01153     case(0):
01154       canvasName = "contours-sinsq-dmsq";
01155       axisLabels = ";sin^{2}2\\theta;\\Delta m^{2}";
01156       xStart = NCType::kSinSqrStart; yStart = NCType::kDeltaMSqrStart*1e-3;
01157       xEnd   = NCType::kSinSqrEnd;   yEnd   = NCType::kDeltaMSqrEnd*1e-3;
01158       xBest  = fBestSinSqr;          yBest  = fBestDeltaMSqr;
01159       break;
01160     case(1):
01161       canvasName = "contours-fster-dmsq";
01162       axisLabels = ";f_{s};\\Delta m^{2}";
01163       xStart = NCType::kFSterileStart; yStart = NCType::kDeltaMSqrStart*1e-3;
01164       xEnd   = NCType::kFSterileEnd;   yEnd   = NCType::kDeltaMSqrEnd*1e-3;
01165       xBest  = fBestFSterile;          yBest  = fBestDeltaMSqr;
01166       break;
01167     case(2):
01168       canvasName = "contours-fster-sinsq";
01169       axisLabels = ";f_{s};sin^{2}\\theta";
01170       xStart = NCType::kFSterileStart; yStart = NCType::kSinSqrStart;
01171       xEnd   = NCType::kFSterileEnd;   yEnd   = NCType::kSinSqrEnd;
01172       xBest  = fBestFSterile;          yBest  = fBestSinSqr;
01173       break;
01174     }
01175 
01176     TLegend leg(0.75, 0.75, 0.95, 0.95);
01177     leg.SetBorderSize(0);
01178 
01179     TCanvas canv(canvasName);
01180     TH2F forceAxes ("", axisLabels, 10, xStart, xEnd, 10, yStart, yEnd);
01181     forceAxes.SetDirectory(0); // Don't write out useless axes to disk.
01182     forceAxes.Draw();
01183     TGraph* contGraph[3];
01184     for(int conf = 0; conf < 3; ++conf){
01185       const std::vector<Coord>& contVec = fLazyContours[conf*3+n];
01186       if(contVec.size() > 0){
01187         contGraph[conf] = new TGraph();
01188         for(unsigned int i = 0; i < contVec.size(); ++i)
01189           contGraph[conf]->SetPoint(i, contVec[i].x, contVec[i].y);
01190         const TString confText = (conf == 0) ? "68" : ( (conf == 1) ? "90" : "99");
01191         leg.AddEntry(contGraph[conf], confText+"% Confidence Level", "l");
01192         contGraph[conf]->SetName(canvasName+confText+"Graph");
01193         contGraph[conf]->Draw("l");
01194         //      contGraph[conf]->Write();
01195         gDirectory->Append(contGraph[conf]);
01196       }
01197     }
01198 
01199     TMarker bestFit(xBest, yBest, kFullStar);
01200     bestFit.SetMarkerSize(2);
01201     bestFit.SetMarkerColor(kBlack);
01202     bestFit.Draw("p same");
01203 
01204     leg.AddEntry(&bestFit, "Best Fit Point", "p");
01205     leg.Draw();
01206 
01207     canv.Write();
01208   }
01209 }
01210 
01211 //----------------------------------------------------------------------
01212 void NCExtrapolation::WriteResources()
01213 {
01214 
01215   MSG("NCExtrapolation", Msg::kInfo)
01216     << "NCExtrapolation::WriteResources() - "
01217     << NCType::kExtrapolationNames[fExtrapolationType]
01218     << endl;
01219 
01220   // get a pointer to the current directory
01221   // this is one of the output files
01222   TDirectory* saveDir = gDirectory;
01223   TString plotName = "plots"+NCType::kExtrapolationNames[fExtrapolationType];
01224   TDirectory* plotsDir = saveDir->mkdir(plotName, plotName);
01225   plotsDir->cd();
01226 
01227   //write out the spectra etc from the beam objects
01228   for(uint i = 0; i < fBeams.size(); ++i){
01229     fBeams[i].MakeResultPlots();
01230     fBeams[i].WriteResources();
01231   }//end loop over beams
01232 
01233   if(fDeltaChiSqrDeltaMVsFSterile->GetEntries() > 0){
01234     fDeltaChiSqrDeltaMVsFSterile->Write();
01235     this->DrawContours(fDeltaChiSqrDeltaMVsFSterile, fBestFSterile, fBestDeltaMSqr);
01236   }
01237 
01238   if(fDeltaChiSqrSinSqrVsFSterile->GetEntries() > 0){
01239     fDeltaChiSqrSinSqrVsFSterile->Write();
01240     this->DrawContours(fDeltaChiSqrSinSqrVsFSterile, fBestFSterile, fBestSinSqr);
01241   }
01242 
01243   if(fDeltaChiSqrDeltaMVsSinSqr->GetEntries() > 0){
01244     fDeltaChiSqrDeltaMVsSinSqr->Write();
01245     this->DrawContours(fDeltaChiSqrDeltaMVsSinSqr, fBestSinSqr, fBestDeltaMSqr);
01246   }
01247 
01248   this->DrawBestFitSpectra(Detector::kNear);
01249   this->DrawBestFitSpectra(Detector::kFar);
01250 
01251   if(fLazyContours.size() > 0) DrawAndWriteLazyContours(); // Only in case of NoMinuit
01252   if(fContourGraphs.size() > 0) DrawAndWriteLazyContoursMinuit();
01253 
01254   saveDir->cd();
01255 
01256   return;
01257 }
01258 
01259 //----------------------------------------------------------------------
01260 void NCExtrapolation::DrawAndWriteLazyContoursMinuit()
01261 {
01262   // TODO - this function is now hideous:
01263   //   should eventually stop special-casing fster,sinsq and dmsq
01264   //   should not rely on the fact that we know fExtraVars* will be filled, need to make this an
01265   //     explicit part of the contract with the base class.
01266   for(unsigned int n = 0; n < fXaxes.size(); ++n){
01267     TString canvasName, axisLabels;
01268     double xStart = 0.;
01269     double xEnd = 0.;
01270     double yStart = 0.;
01271     double yEnd = 0.;
01272     double xBest = 0.;
01273     double yBest = 0.;
01274 
01275     switch(fXaxes[n]){
01276     case(0):
01277       canvasName = "contours-fster-";
01278       axisLabels = ";f_{s};";
01279       xStart = NCType::kFSterileStart;
01280       xEnd   = NCType::kFSterileEnd;
01281       xBest  = fBestFSterile;
01282       break;
01283     case(1):
01284       canvasName = "contours-sinsq-";
01285       axisLabels = ";sin^{2}2\\theta;";
01286       xStart = NCType::kSinSqrStart;
01287       xEnd   = NCType::kSinSqrEnd;
01288       xBest  = fBestSinSqr;
01289       break;
01290     case(2):
01291       canvasName += "contours-dmsq-";
01292       axisLabels += ";\\Delta m^{2};";
01293       xStart = NCType::kDeltaMSqrStart*1e-3;
01294       xEnd   = NCType::kDeltaMSqrEnd*1e-3;
01295       xBest  = fBestDeltaMSqr;
01296       break;
01297     default:
01298       canvasName = "contours-"+fExtraVarsNames[fXaxes[n]-3]+"-";
01299       axisLabels = ";"+fExtraVarsNames[fXaxes[n]-3]+";";
01300       xStart = fExtraVarsMin[fXaxes[n]-3];
01301       xEnd = fExtraVarsMax[fXaxes[n]-3];
01302       xBest = fMinCoord[fXaxes[n]];
01303     }
01304     switch(fYaxes[n]){
01305     case(0):
01306       canvasName += "fster";
01307       axisLabels += ";f_{s};";
01308       yStart = NCType::kFSterileStart;
01309       yEnd   = NCType::kFSterileEnd;
01310       yBest  = fBestFSterile;
01311       break;
01312     case(1):
01313       canvasName += "sinsq";
01314       axisLabels += "sin^{2}2\\theta";
01315       yStart = NCType::kSinSqrStart;
01316       yEnd   = NCType::kSinSqrEnd;
01317       yBest  = fBestSinSqr;
01318       break;
01319     case(2):
01320       canvasName += "dmsq";
01321       axisLabels += "\\Delta m^{2}";
01322       yStart = NCType::kDeltaMSqrStart*1e-3;
01323       yEnd   = NCType::kDeltaMSqrEnd*1e-3;
01324       yBest  = fBestDeltaMSqr;
01325       break;
01326     default:
01327       canvasName += fExtraVarsNames[fYaxes[n]-3];
01328       axisLabels += fExtraVarsNames[fYaxes[n]-3];
01329       yStart = fExtraVarsMin[fYaxes[n]-3];
01330       yEnd = fExtraVarsMax[fYaxes[n]-3];
01331       yBest = fMinCoord[fYaxes[n]];
01332     }
01333 
01334     TLegend leg(0.75, 0.75, 0.95, 0.95);
01335     leg.SetBorderSize(0);
01336 
01337     TCanvas canv(canvasName);
01338     TH2F forceAxes ("", axisLabels, 10, xStart, xEnd, 10, yStart, yEnd);
01339     forceAxes.SetDirectory(0); // Don't write out useless axes to disk.
01340     forceAxes.Draw();
01341     int trueconf = 0; // because some confidences were never written, need to keep track of the effective index.
01342     for(int conf = 0; conf < 3; ++conf){
01343       if(conf==0 && !fWant68) continue;
01344       if(conf==1 && !fWant90) continue;
01345       if(conf==2 && !fWant99) continue;
01346       TGraph* contGraph = fContourGraphs[trueconf*fXaxes.size()+n];
01347       if(contGraph && contGraph->GetN() > 0){
01348         const TString confText = (conf == 0) ? "68" : ( (conf == 1) ? "90" : "99");
01349         leg.AddEntry(contGraph, confText+"% Confidence Level", "l");
01350         contGraph->SetName(canvasName+confText+"Graph");
01351         contGraph->Draw("l");
01352         gDirectory->Append(contGraph);
01353       }
01354       ++trueconf;
01355     }
01356 
01357     TMarker bestFit(xBest, yBest, kFullStar);
01358     bestFit.SetMarkerSize(2);
01359     bestFit.SetMarkerColor(kBlack);
01360     bestFit.Draw("p same");
01361 
01362     leg.AddEntry(&bestFit, "Best Fit Point", "p");
01363     leg.Draw();
01364 
01365     canv.Write();
01366   }
01367 }
01368 
01369 //----------------------------------------------------------------------
01370 //add says whether to add a new beam if this one isnt found, scalefactor is
01371 //the pot normalization for data to mc
01372 int NCExtrapolation::FindBeamIndex(Detector::Detector_t det,
01373                                    BeamType::BeamType_t bt,
01374                                    int rt,
01375                                    bool add,
01376                                    double dataPOT,
01377                                    double mcPOT)
01378 {
01379   int index = 999;
01380   for(uint i = 0; i < fBeams.size(); ++i){
01381     if(fBeams[i].GetDetector() == det
01382        && fBeams[i].GetBeamType() == bt
01383        && fBeams[i].GetRunType() == rt) index = (int)i;
01384   }
01385   if(index > 100){
01386     if(add){
01387       fBeams.push_back(NCBeam(bt, det, rt, dataPOT, mcPOT, fUseCC, fUseNC));
01388       index = fBeams.size()-1;
01389       MSG("NCExtrapolation", Msg::kInfo) << "adding beam type "
01390                                          << BeamType::AsString(bt)
01391                                          << " run type "
01392                                          << rt
01393                                          << " to "
01394                                          << Detector::AsString(det)
01395                                          << " data pot = " << dataPOT
01396                                          << " mc pot = " << mcPOT
01397                                          << " index = " << index << endl;
01398     }//end if add beams when not found
01399 //     else{
01400 //       MAXMSG("NCExtrapolation", Msg::kWarning,1) << "could not find "
01401 //                                               << Detector::AsString(det)
01402 //                                               << " " << BeamType::AsString(bt)
01403 //                                               << " " << rt
01404 //                                               << " beam in vector - return index = "
01405 //                                               << index << endl;
01406 //     }//end if cant find beam
01407 
01408   }//end if beam not found
01409 
01410   return index;
01411 }
01412 
01413 //----------------------------------------------------------------------
01414 //method to fill the result histograms based on the best fit to the
01415 //oscillation parameters and penalty terms
01416 void NCExtrapolation::FillResultHistograms(int beam)
01417 {
01418 
01419   NCEnergyBin *bin       = 0;
01420   int mcSize             = 0;
01421   int mcSize_bkg         = 0;
01422   int mcSize_NuMuToNuTau = 0;
01423   int mcSize_NuEToNuE    = 0;
01424   int mcSize_NuMuToNuE   = 0;
01425   double trueEnergy      = 0.;
01426   double recoShowerE     = 0.;
01427   double recoMuonE       = 0.;
01428   double weight          = 0.;
01429   int    flavor          = 0;
01430   double survivalProb    = 1.;
01431   int sigType  = NCType::kNC;
01432   int bkgType  = NCType::kCC;
01433   double baseLine = NCType::kBaseLineFar;
01434   Detector::Detector_t det = fBeams[beam].GetDetector();
01435   if(det == Detector::kNear) baseLine = NCType::kBaseLineNear;
01436 
01437   CoordNDim coords = GetLazyBestFitPoint();
01438 
01439   // Alters the systematics 'weights' to reflect the current
01440   // value returned by the fitter.
01441   if( fExtraVarsNames.size() > 0 ){
01442     if( fLocNormalization > 0 ){
01443       fWeightNormalization = coords.at( fLocNormalization );
01444     }
01445     if( fLocRelativeHadronicCalibration > 0 ){
01446       fWeightRelativeHadronicCalibration = coords.at( fLocRelativeHadronicCalibration );
01447     }
01448     if( fLocAbsoluteHadronicCalibration > 0 ){
01449       fWeightAbsoluteHadronicCalibration = coords.at( fLocAbsoluteHadronicCalibration );
01450     }
01451     if( fLocTrackEnergy > 0 ){
01452       fWeightTrackEnergy = coords.at( fLocTrackEnergy );
01453     }
01454     if( fLocNCBkg > 0 ){
01455       fWeightNCBkg = coords.at( fLocNCBkg );
01456     }
01457     if( fLocCCBkg > 0 ){
01458       fWeightCCBkg = coords.at( fLocCCBkg );
01459     }
01460   }//end if fitting systematic nuisance parameters
01461 
01462   fShowerScale = 1.+fWeightRelativeHadronicCalibration;
01463   fShowerScale *= 1.+fWeightAbsoluteHadronicCalibration;
01464   fTrackScale  = 1.+fWeightTrackEnergy;
01465 
01466   //set oscillation parameters
01467   vector<double> pars;
01468   SetParametersForOscillationFit(coords, pars);
01469 
01470   //loop over NC/CC energy bins in beam
01471   for(int j = 0; j < 2; ++j){
01472 
01473     if(j == NCType::kNC && det == Detector::kFar && !fUseNC) continue;
01474     if(j == NCType::kCC && det == Detector::kFar && !fUseCC) continue;
01475 
01476     sigType = j;
01477     bkgType = NCType::kNC;
01478 
01479     if( j == NCType::kNC) bkgType = NCType::kCC;
01480 
01481     for(int i = 0; i < fBeams[beam].GetNumberEnergyBins(j); ++i){
01482 
01483       bin = fBeams[beam].GetEnergyBin(i, j);
01484 
01485       mcSize             = bin->GetMCSignalVectorSize();
01486       mcSize_bkg         = bin->GetMCBackgroundVectorSize();
01487       mcSize_NuMuToNuTau = bin->GetMCNuMuToNuTauVectorSize();
01488       mcSize_NuEToNuE    = bin->GetMCNuEToNuEVectorSize();
01489       mcSize_NuMuToNuE   = bin->GetMCNuMuToNuEVectorSize();
01490 
01491       for( int e = 0; e < mcSize; ++e ){
01492         bin->GetMCInformation(trueEnergy, recoShowerE, recoMuonE, weight, flavor, e);
01493         survivalProb = FindSurvivalProbability(NCType::kNuMuToNuMu,
01494                                                sigType,
01495                                                NCType::kBaseLineFar,
01496                                                trueEnergy,
01497                                                pars);
01498         fBeams[beam].GetMCHistogram(sigType)->Fill(recoShowerE*fShowerScale
01499                                                    + recoMuonE*fTrackScale,
01500                                                    weight*(1.+fWeightNormalization));
01501         fBeams[beam].GetMCTrueHistogram(sigType)->Fill(trueEnergy,weight);
01502 
01503         fBeams[beam].GetMCFitHistogram(sigType)->Fill(recoShowerE*fShowerScale
01504                                                       + recoMuonE*fTrackScale,
01505                                                       weight*survivalProb*(1.+fWeightNormalization));
01506       }//end loop over signal
01507 
01508       for( int e = 0; e < mcSize_bkg; ++e ){
01509         bin->GetMCBackgroundInformation(trueEnergy, recoShowerE, recoMuonE, weight, flavor, e);
01510         survivalProb = FindSurvivalProbability(NCType::kNuMuToNuMu,
01511                                                bkgType,
01512                                                NCType::kBaseLineFar,
01513                                                trueEnergy,
01514                                                pars);
01515         fBeams[beam].GetMCBackgroundHistogram(sigType)->Fill(recoShowerE*fShowerScale
01516                                                              + recoMuonE*fTrackScale,
01517                                                              weight*survivalProb*(1.+fWeightNormalization));
01518         fBeams[beam].GetMCHistogram(sigType)->Fill(recoShowerE*fShowerScale
01519                                                    + recoMuonE*fTrackScale,
01520                                                    weight*(1.+fWeightNormalization));
01521         fBeams[beam].GetMCFitHistogram(sigType)->Fill(recoShowerE*fShowerScale
01522                                                       + recoMuonE*fTrackScale,
01523                                                       weight*survivalProb*(1.+fWeightNormalization));
01524       }//end loop over background
01525 
01526       //nutau
01527       for( int e = 0; e < mcSize_NuMuToNuTau; ++e ){
01528         bin->GetMCNuMuToNuTauInformation(trueEnergy, recoShowerE, recoMuonE, weight, flavor, e);
01529         survivalProb = FindSurvivalProbability(NCType::kNuMuToNuTau,
01530                                                NCType::kCC,
01531                                                NCType::kBaseLineFar,
01532                                                trueEnergy,
01533                                                pars);
01534         fBeams[beam].GetMCFitNuMuToNuTauHistogram(sigType)->Fill(recoShowerE*fShowerScale
01535                                                                  + recoMuonE*fTrackScale,
01536                                                                  weight*survivalProb*(1.+fWeightNormalization));
01537         fBeams[beam].GetMCFitHistogram(sigType)->Fill(recoShowerE*fShowerScale
01538                                                       + recoMuonE*fTrackScale,
01539                                                       weight*survivalProb*(1.+fWeightNormalization));
01540         fBeams[beam].GetMCNoFitNuMuToNuTauHistogram(sigType)->Fill(recoShowerE*fShowerScale
01541                                                                    + recoMuonE*fTrackScale,
01542                                                                    weight*(1.+fWeightNormalization));
01543       }//end loop over taus
01544 
01545       //nue
01546       for( int e = 0; e < mcSize_NuEToNuE; ++e ){
01547         bin->GetMCNuEToNuEInformation(trueEnergy, recoShowerE, recoMuonE, weight, flavor, e);
01548         survivalProb = FindSurvivalProbability(NCType::kNuEToNuE,
01549                                                NCType::kCC,
01550                                                NCType::kBaseLineFar,
01551                                                trueEnergy,
01552                                                pars);
01553         fBeams[beam].GetMCFitHistogram(sigType)->Fill(recoShowerE*fShowerScale
01554                                                       + recoMuonE*fTrackScale,
01555                                                       weight*(1.+fWeightNormalization));
01556         fBeams[beam].GetMCNoFitNuEToNuEHistogram(sigType)->Fill(recoShowerE*fShowerScale
01557                                                                 + recoMuonE*fTrackScale,
01558                                                                 weight*(1.+fWeightNormalization));
01559         fBeams[beam].GetMCFitNuEToNuEHistogram(sigType)->Fill(recoShowerE*fShowerScale
01560                                                               + recoMuonE*fTrackScale,
01561                                                               weight*(1.+fWeightNormalization));
01562       }//end loop over electrons
01563 
01564       //nue appearance
01565       for( int e = 0; e < mcSize_NuMuToNuE; ++e ){
01566         bin->GetMCNuMuToNuEInformation(trueEnergy, recoShowerE,
01567                                        recoMuonE, weight, flavor, e);
01568         survivalProb = FindSurvivalProbability(NCType::kNuMuToNuE,
01569                                                NCType::kCC,
01570                                                NCType::kBaseLineFar,
01571                                                trueEnergy,
01572                                                pars);
01573         fBeams[beam].GetMCFitHistogram(sigType)->Fill(recoShowerE*fShowerScale
01574                                                       + recoMuonE*fTrackScale,
01575                                                       weight*survivalProb*(1.+fWeightNormalization));
01576         fBeams[beam].GetMCNoFitNuMuToNuEHistogram(sigType)->Fill(recoShowerE*fShowerScale
01577                                                                  + recoMuonE*fTrackScale,
01578                                                                  weight*(1.+fWeightNormalization));
01579         fBeams[beam].GetMCFitNuMuToNuEHistogram(sigType)->Fill(recoShowerE*fShowerScale
01580                                                                + recoMuonE*fTrackScale,
01581                                                                weight*survivalProb*(1.+fWeightNormalization));
01582       }//end loop over electron appearance
01583 
01584     }//end loop over energy bins
01585 
01586   }//end loop over nc/cc
01587 
01588   return;
01589 }
01590 
01591 //----------------------------------------------------------------------
01592 void NCExtrapolation::SetParametersForOscillationFit(CoordNDim coords,
01593                                                      std::vector<double>& pars)
01594 {
01595   pars.clear();
01596   pars.push_back(coords.at(NCType::kSinSqr));
01597   pars.push_back(coords.at(NCType::kDeltaMSqr));
01598   if(fLocPhi43 > 0)
01599     pars.push_back(coords.at(fLocPhi43));
01600   else pars.push_back(0.);
01601   if(fLocPMu > 0)
01602     pars.push_back(coords.at(fLocPMu));
01603   else pars.push_back(0.);
01604   pars.push_back(coords.at(NCType::kFSterile));
01605   if(fLocPE > 0)
01606     pars.push_back(coords.at(fLocPE));
01607   else pars.push_back(0.0);
01608 
01609   for(uint i = 0; i < pars.size(); ++i){
01610     if(pars[i] < 0. && TMath::Abs(pars[i]) < 1.e-3) pars[i] = 0.;
01611   }
01612 
01613   //3 Flavor mixing
01614 //   pars.push_back(0.5*TMath::ASin(TMath::Sqrt(coords.at(NCType::kSinSqr))));
01615 //   pars.push_back(coords.at(NCType::kDeltaMSqr));
01616 //   pars.push_back(0.);
01617 //   pars.push_back(0.61);//SNO+KamLAND
01618 //   pars.push_back(7.59e-5);//SNO+KamLAND
01619 //   pars.push_back(2.7);//g/cc standard rock
01620 //   pars.push_back(0.);//why not?
01621 //   pars.push_back(1.);//again, why not?
01622 
01623   return;
01624 }
01625 
01626 //----------------------------------------------------------------------
01627 //method to find survival probability based on passed in parameters
01628 //in pars vector.  the order of the parameters in pars depends on
01629 //the function used to calculate the probability.
01630 double NCExtrapolation::FindSurvivalProbability(int oscillationMode,
01631                                                 int interactionType,
01632                                                 double baseline,
01633                                                 double trueEnergy,
01634                                                 std::vector<double>& pars)
01635 {
01636   double probability = 1.;
01637 
01638 //   probability = fUtils->Find3FlavorProbability(oscillationMode,
01639 //                                             interactionType,
01640 //                                             baseline,
01641 //                                             trueEnergy,
01642 //                                             pars);
01643 
01644 //   probability = fUtils->FindExtendedModelIProbability(oscillationMode,
01645 //                                                    interactionType,
01646 //                                                    baseline,
01647 //                                                    trueEnergy,
01648 //                                                    pars);
01649 
01650   probability = fUtils->FindParkeModelProbability(oscillationMode,
01651                                                   interactionType,
01652                                                   baseline,
01653                                                   trueEnergy,
01654                                                   pars);
01655 
01656   return probability;
01657 }
01658 
01659 //----------------------------------------------------------------------
01660 void NCExtrapolation::CombineRuns(Detector::Detector_t det)
01661 {
01662   //make a map of the number of run types for each beam condition
01663   map<BeamType::BeamType_t, int> numRuns;
01664   map<BeamType::BeamType_t, int>::iterator itr = numRuns.begin();
01665 
01666   int totIndex = 0;
01667   int beamIndex = 0;
01668 
01669   for(uint i = 0; i < fBeams.size(); ++i){
01670     if(fBeams[i].GetDetector() == det){
01671       itr = numRuns.find(fBeams[i].GetBeamType());
01672       if(itr != numRuns.end()) itr->second++;
01673       else numRuns[fBeams[i].GetBeamType()] = 1;
01674       MSG("NCExtrapolation", Msg::kInfo) << "beam "
01675                                          << BeamType::AsString(fBeams[i].GetBeamType())
01676                                          << " in " << Detector::AsString(det)
01677                                          << " has " << numRuns[fBeams[i].GetBeamType()]
01678                                          << " runs " << endl;
01679 
01680     }//end if the same detector as what i want
01681   }//end loop over beams
01682 
01683   //now figure out how many beam objects to add
01684   for(itr = numRuns.begin(); itr != numRuns.end(); ++itr){
01685 
01686     //see if there is more than one run for this beam type,
01687     //and if so create a total beam for it, then get the individual
01688     //runs and add them to the total
01689     if(itr->second > 1){
01690       totIndex = FindBeamIndex(det, itr->first, NCType::kRunAll, true, 0., 0.);
01691       for(int i = NCType::kRunI; i < NCType::kMaxRun+1; ++i){
01692         beamIndex = FindBeamIndex(det, itr->first, i);
01693         if(beamIndex < 100){
01694           fBeams[totIndex].Add(fBeams[beamIndex]);
01695           MSG("NCExtrapolation", Msg::kInfo) << "combining runs for beam "
01696                                              << BeamType::AsString(itr->first)
01697                                              << " in " << Detector::AsString(det)
01698                                              << endl;
01699         }//end if run type exists
01700       }//end loop over run types
01701     }//end if more than one run for the beam
01702     else{
01703       for(int i = NCType::kRunI; i < NCType::kMaxRun+1; ++i){
01704         beamIndex = FindBeamIndex(det, itr->first, i);
01705         if(beamIndex < 100){
01706           fBeams[beamIndex].SetRunType(NCType::kRunAll);
01707           MSG("NCExtrapolation", Msg::kInfo) << "setting run " << i
01708                                              << " to "  << NCType::kRunAll
01709                                              << " for beam "
01710                                              << BeamType::AsString(itr->first)
01711                                              << " in " << Detector::AsString(det)
01712                                              << endl;
01713         }//end if the run for this beam exists
01714       }//end loop over runs
01715     }//end if only one run for the beam
01716   }//end loop over map of beam type to # of runs
01717 
01718   return;
01719 }
01720 
01721 //----------------------------------------------------------------------
01722 //make sure the fMinChiSqr variable is set before calling this method
01723 //assumes the vector of vector of vectors of doubles has the indicies
01724 //[Delta m^2][f_sterile][sin^2(2theta)]
01725 void NCExtrapolation::FillDeltaChiSqrMaps(std::vector< std::vector< std::vector<double> > > &chiSqrPnts)
01726 {
01727 
01728   //loop over the parameter space values of chi^2 to save the delta chi^2 to
01729   //the histograms
01730   double minSinSqrChiSqr = 1.e10;
01731   for (int dm = 0; dm < NCType::kNumDeltaMSqrBins; dm++) {
01732     float dmsq = (1.*dm + 0.5)*NCType::kDeltaDeltaMSqr+NCType::kDeltaMSqrStart;
01733 
01734     // fsterile loop
01735     for (int fs = 0; fs < NCType::kNumFSterileBins; fs++) {
01736       float fster = (1.*fs + 0.5)*NCType::kDeltaFSterile+NCType::kFSterileStart;
01737       minSinSqrChiSqr = 1.e10;
01738 
01739       // sin2theta loop
01740       for (int st = 0; st < NCType::kNumSinSqrBins; st++) {
01741 
01742         if(chiSqrPnts[dm][fs][st] < minSinSqrChiSqr)
01743           minSinSqrChiSqr = chiSqrPnts[dm][fs][st];
01744 
01745       }//end s2t
01746 
01747       //found the minimum in sin^2 2theta for this point in delta m^2 vs f_s
01748       fDeltaChiSqrDeltaMVsFSterile->Fill(fster, dmsq, minSinSqrChiSqr-fMinChiSqr);
01749 
01750     }//end fs
01751   }//end dmsq
01752 
01753   double minDeltaMSqrChiSqr = 1.e10;
01754   // sin2theta loop
01755   for (int st=0;st<NCType::kNumSinSqrBins;st++) {
01756     float s2t=(1.*st + 0.5)*NCType::kDeltaSinSqr+NCType::kSinSqrStart;
01757 
01758     // fsterile loop
01759     for (int fs=0;fs<NCType::kNumFSterileBins;fs++) {
01760       float fster=(1.*fs + 0.5)*NCType::kDeltaFSterile+NCType::kFSterileStart;
01761 
01762       minDeltaMSqrChiSqr = 1.e10;
01763       for (int dm=0;dm<NCType::kNumDeltaMSqrBins;dm++) {
01764 
01765         if(chiSqrPnts[dm][fs][st] < minDeltaMSqrChiSqr)
01766           minDeltaMSqrChiSqr = chiSqrPnts[dm][fs][st];
01767 
01768       }//end s2t
01769 
01770       //found the minimum in sin^2 2theta for this point in delta m^2 vs f_s
01771       fDeltaChiSqrSinSqrVsFSterile->Fill(fster, s2t, minDeltaMSqrChiSqr-fMinChiSqr);
01772 
01773     }//end fs
01774   }//end dmsq
01775 
01776   double minFSterileChiSqr = 1.e10;
01777   for (int dm=0;dm<NCType::kNumDeltaMSqrBins;dm++) {
01778     float dmsq=(1.*dm + 0.5)*NCType::kDeltaDeltaMSqr+NCType::kDeltaMSqrStart;
01779 
01780     // sin2theta loop
01781     for (int st=0;st<NCType::kNumSinSqrBins;st++) {
01782       float s2t=(1.*st + 0.5)*NCType::kDeltaSinSqr+NCType::kSinSqrStart;
01783       minFSterileChiSqr = 1.e10;
01784 
01785       // fsterile loop
01786       for (int fs=0;fs<NCType::kNumFSterileBins;fs++) {
01787 
01788         if(chiSqrPnts[dm][fs][st] < minFSterileChiSqr)
01789           minFSterileChiSqr = chiSqrPnts[dm][fs][st];
01790 
01791       }//end s2t
01792 
01793       //found the minimum in sin^2 2theta for this point in delta m^2 vs f_s
01794       fDeltaChiSqrDeltaMVsSinSqr->Fill(s2t, dmsq, minFSterileChiSqr-fMinChiSqr);
01795 
01796     }//end fs
01797   }//end dmsq
01798 
01799   return;
01800 }
01801 
01802 
01803 // ---------------------------------------------------------------------
01804 // Make sure your derived class has overridden GetChiSqrForMap() and that
01805 // everything is ready, and then call this function. It finds the best-fit
01806 // point, and contours at 3 levels of significance, projected onto 3 different
01807 // axes. Sets fMinChiSqr, fBestSinSqr, fBestDeltaMSqr, fBestFSterile.
01808 void NCExtrapolation::MakeDeltaChiSqrMaps(CoordNDim extraVarsMin,
01809                                           CoordNDim extraVarsMax,
01810                                           CoordNDim extraVarsPrecision,
01811                                           std::vector<std::string> extraVarsNames,
01812                                           std::vector<int> xAxes,
01813                                           std::vector<int> yAxes)
01814 {
01815   assert(xAxes.size() == yAxes.size());
01816   fXaxes = xAxes;
01817   fYaxes = yAxes;
01818 
01819   switch(fLazyContoursUseMinuit){
01820   default:
01821     MSG("NCExtrapolation", Msg::kWarning) << "LazyContoursUseMinuit not set. Assuming zero.\n";
01822     // fall through
01823   case(0):
01824     MakeDeltaChiSqrMapsNoMinuit(extraVarsMin, extraVarsMax, extraVarsPrecision, extraVarsNames, fWant68, fWant90, fWant99);
01825     break;
01826   case(1):
01827     MakeDeltaChiSqrMapsHybrid(extraVarsMin,
01828                               extraVarsMax,
01829                               extraVarsPrecision,
01830                               extraVarsNames);
01831     break;
01832   case(2):
01833     MakeDeltaChiSqrMapsMinuit(extraVarsMin, extraVarsMax, extraVarsNames, fWant68, fWant90, fWant99);
01834     break;
01835   }
01836 }
01837 
01838 // ---------------------------------------------------------------------
01839 // Make sure your derived class has overridden GetChiSqrForMap() and that
01840 // everything is ready, and then call this function. It finds the best-fit
01841 // point, and contours at 3 levels of significance, projected onto 3 different
01842 // axes. Sets fMinChiSqr, fBestSinSqr, fBestDeltaMSqr, fBestFSterile.
01843 void NCExtrapolation::MakeDeltaChiSqrMapsNoMinuit(CoordNDim extraVarsMin,
01844                                                   CoordNDim extraVarsMax,
01845                                                   CoordNDim extraVarsPrecision,
01846                                                   std::vector<std::string> extraVarsNames,
01847                                                   bool want68,
01848                                                   bool want90,
01849                                                   bool want99)
01850 {
01851   assert(extraVarsMin.size() == extraVarsMax.size() &&
01852          extraVarsMax.size() == extraVarsPrecision.size());
01853 
01854   enum{FSTER, SINSQ, DMSQ}; // Is this already defined somewhere else?
01855 
01856   // Use NCType to get the range of the oscillation parameters.
01857   CoordNDim start(3);
01858   start[FSTER] = NCType::kFSterileStart;
01859   start[SINSQ] = NCType::kSinSqrStart;
01860   start[DMSQ]  = NCType::kDeltaMSqrStart*1e-3;
01861   // Add the ranges of the additional parameters we were passed.
01862   start.insert(start.end(), extraVarsMin.begin(), extraVarsMin.end());
01863 
01864   CoordNDim end(3);
01865   end[FSTER] = NCType::kFSterileEnd;
01866   end[SINSQ] = NCType::kSinSqrEnd;
01867   end[DMSQ]  = NCType::kDeltaMSqrEnd*1e-3;
01868   end.insert(end.end(), extraVarsMax.begin(), extraVarsMax.end());
01869 
01870   CoordNDim minimPrec(3);
01871   minimPrec[FSTER] = NCType::kDeltaFSterile;
01872   minimPrec[SINSQ] = NCType::kDeltaSinSqr;
01873   minimPrec[DMSQ]  = NCType::kDeltaDeltaMSqr*1e-3;
01874   minimPrec.insert(minimPrec.end(),
01875                    extraVarsPrecision.begin(), extraVarsPrecision.end());
01876 
01877   std::vector<std::string> allNames(3);
01878   allNames[FSTER] = "fster";
01879   allNames[SINSQ] = "sinsq";
01880   allNames[DMSQ] = "dmsq";
01881   allNames.insert(allNames.end(), extraVarsNames.begin(), extraVarsNames.end());
01882   while(allNames.size() < start.size()) allNames.push_back("[unknown]");
01883 
01884   // Create functionoid that redirects to derived-class's implementation.
01885   // FIXME - currently always using unphysical penalties.
01886   GetChiSqrFromDerived chiSqrFunc(this, start, end, allNames, true);
01887 
01888   // Store the best-fit point in here.
01889   CoordNDim minCoord;
01890 
01891   // Find the best fit point.
01892   fMinChiSqr = FindMinNDim(chiSqrFunc, start, end, minCoord, minimPrec);
01893 
01894   MSG("NCExtrapolation", Msg::kInfo) << "Best fit : f_s = " << minCoord[FSTER]
01895                                              << " sin^2 = " << minCoord[SINSQ]
01896                                               << " dm^2 = " << minCoord[DMSQ];
01897   if(minCoord.size() > 3){
01898     MSG("NCExtrapolation", Msg::kInfo) << endl
01899                                        << " Additional parameters:";
01900     for(unsigned int n = 3; n < minCoord.size(); ++n)
01901       MSG("NCExtrapolation", Msg::kInfo) << allNames.at(n) << " = "
01902                                          << minCoord[n] << " ";
01903   }
01904   MSG("NCExtrapolation", Msg::kInfo) << endl;
01905 
01906   // The three functions we will be plotting the contours of.
01907   GetFuncMinWRTSomeVars<GetChiSqrFromDerived> minWRT[3];
01908 
01909   // For each of the oscillation parameters we will minimize over:
01910   for(int minVar = 0; minVar < 3; ++minVar){
01911     // Store its index, range and precision.
01912     std::vector<int> toMin(1);
01913     toMin[0] = minVar;
01914     CoordNDim min(1), max(1), prec(1);
01915     min[0] = start[minVar];
01916     max[0] = end[minVar];
01917     prec[0] = minimPrec[minVar];
01918 
01919     // And then append the indices, ranges and precisions of all
01920     // additional variables we will minimize over.
01921     for(unsigned int n = 0; n < extraVarsMin.size(); ++n){
01922       toMin.push_back(3+n);
01923       min.push_back(extraVarsMin[n]);
01924       max.push_back(extraVarsMax[n]);
01925       prec.push_back(extraVarsPrecision[n]);
01926     }
01927     // Create the functionoid that minimizes over all of these.
01928     minWRT[minVar] = GetFuncMinWRTSomeVars<GetChiSqrFromDerived>
01929                        (chiSqrFunc, toMin, min, max, prec);
01930   }
01931 
01932   // QUESTION: are these the right values for a fit with more variables?
01933   const double contVals[] = {2.3, 4.6, 9.2};
01934 
01935   // The axes that should be used when minimizing over each of the three variables.
01936   const int xAxis[] = {SINSQ, FSTER, FSTER};
01937   const int yAxis[] = {DMSQ, DMSQ, SINSQ};
01938   // And human-readable form.
01939   const TString text[] = {"sin^2 and dm^2", "f_s and dm^2", "f_s and sin^2"};
01940 
01941   // For each of the 3 confidence levels (68, 90, 99)
01942   for(int conf = 0; conf < 3; ++conf){
01943     // If we don't want to draw contours at this confidence, add empty dummy contours.
01944     if((conf == 0 && !want68) || (conf == 1 && !want90) || (conf == 2 && !want99)){
01945       for(int i = 0; i < 3; ++i) fLazyContours.push_back(std::vector<Coord>());
01946       continue;
01947     }
01948 
01949     // For each of the 3 oscillation parameters we are minimizing.
01950     for(int minVar = 0; minVar < 3; ++minVar){
01951       MSG("NCExtrapolation", Msg::kInfo) << "Building contour in " << text[minVar]
01952                                          << " (up = " << contVals[conf] << ")...\n";
01953       // Look up which axes we should be using.
01954       const int x = xAxis[minVar];
01955       const int y = yAxis[minVar];
01956       const std::vector<Coord> contour = FindContour(minWRT[minVar],
01957                                                      //Coord(start[x], start[y]),
01958                                                      //Coord(end[x], end[y]),
01959                                                      Coord(minCoord[x], minCoord[y]),
01960                                                      fMinChiSqr+contVals[conf],
01961                                                      Coord(minimPrec[x], minimPrec[y]));
01962       fLazyContours.push_back(contour);
01963       MSG("NCExtrapolation", Msg::kInfo) << "there are " << contour.size()
01964                                          << " points on this contour" << endl;
01965     }
01966   }
01967 
01968   // The best-fit parameters are stored as member variables for later use.
01969   fBestFSterile = minCoord[FSTER];
01970   fBestSinSqr = minCoord[SINSQ];
01971   fBestDeltaMSqr = minCoord[DMSQ];
01972 }
01973 
01974 // ---------------------------------------------------------------------
01975 // Make sure your derived class has overridden GetChiSqrForMap() and that
01976 // everything is ready, and then call this function. It finds the best-fit
01977 // point, and contours at 3 levels of significance, projected onto 3 different
01978 // axes. Sets fMinChiSqr, fBestSinSqr, fBestDeltaMSqr, fBestFSterile.
01979 void NCExtrapolation::MakeDeltaChiSqrMapsHybrid(CoordNDim extraVarsMin,
01980                                                 CoordNDim extraVarsMax,
01981                                                 CoordNDim extraVarsPrecision,
01982                                                 std::vector<std::string> extraVarsNames)
01983 {
01984   assert(extraVarsMin.size() == extraVarsMax.size() &&
01985          extraVarsMax.size() == extraVarsPrecision.size());
01986 
01987   enum{FSTER, SINSQ, DMSQ}; // Is this already defined somewhere else?
01988 
01989   // Use NCType to get the range of the oscillation parameters.
01990   CoordNDim start(3);
01991   start[FSTER] = NCType::kFSterileStart;
01992   start[SINSQ] = NCType::kSinSqrStart;
01993   start[DMSQ]  = NCType::kDeltaMSqrStart*1e-3;
01994   // Add the ranges of the additional parameters we were passed.
01995   start.insert(start.end(), extraVarsMin.begin(), extraVarsMin.end());
01996 
01997   CoordNDim end(3);
01998   end[FSTER] = NCType::kFSterileEnd;
01999   end[SINSQ] = NCType::kSinSqrEnd;
02000   end[DMSQ]  = NCType::kDeltaMSqrEnd*1e-3;
02001   end.insert(end.end(), extraVarsMax.begin(), extraVarsMax.end());
02002 
02003   CoordNDim prec(3);
02004   prec[FSTER] = NCType::kDeltaFSterile;
02005   prec[SINSQ] = NCType::kDeltaSinSqr;
02006   prec[DMSQ]  = NCType::kDeltaDeltaMSqr*1e-3;
02007   prec.insert(prec.end(), extraVarsPrecision.begin(), extraVarsPrecision.end());
02008 
02009   std::vector<std::string> allNames(3);
02010   allNames[FSTER] = "fster";
02011   allNames[SINSQ] = "sinsq";
02012   allNames[DMSQ] = "dmsq";
02013   allNames.insert(allNames.end(), extraVarsNames.begin(), extraVarsNames.end());
02014   while(allNames.size() < start.size()) allNames.push_back("[unknown]");
02015 
02016   // Create functionoid that redirects to derived-class's implementation.
02017   GetChiSqrFromDerived chiSqrFunc(this, start, end, allNames, !fAllowBestFitOutsideRange);
02018 
02019 
02020   NCExtrapolationMinuit<GetChiSqrFromDerived> minu(chiSqrFunc, 3+extraVarsMin.size());
02021   minu.SetPrintLevel(-1); // Shut Minuit up.
02022   minu.Command("set strategy 2"); // Be careful, instead of fast.
02023 
02024   for(int n = 0; n < int(start.size()); ++n)
02025     // NB - no parameter limits imposed.
02026     minu.DefineParameter(n, "", (start[n]+end[n])/2, (end[n]-start[n])/4, 0, 0);
02027 
02028   // Minuit tries to return a lot of parameters we don't want to keep.
02029   double junkd; int junki; TString junks;
02030 
02031   if(minu.Migrad()){
02032     MSG("NCExtrapolation", Msg::kWarning) << "Migrad failed, falling back to Simplex.\n";
02033     minu.SetPrintLevel(0); // Things are going wrong, we should let the user see.
02034     minu.mnsimp();
02035     minu.Migrad();
02036   }
02037 
02038   minu.mnstat(fMinChiSqr, junkd, junkd, junki, junki, junki);
02039 
02040   fMinCoord.resize(start.size());
02041   for(unsigned int n = 0; n < start.size(); ++n)
02042     minu.GetParameter(n, fMinCoord[n], junkd);
02043 
02044   // The best-fit parameters are stored as member variables for later use.
02045   fBestFSterile = fMinCoord[FSTER];
02046   fBestSinSqr = fMinCoord[SINSQ];
02047   fBestDeltaMSqr = fMinCoord[DMSQ];
02048 
02049   MSG("NCExtrapolation", Msg::kInfo) << "Best fit :" << endl;
02050   for(unsigned int n = 0; n < allNames.size(); ++n)
02051     MSG("NCExtrapolation", Msg::kInfo) << "  " << allNames[n] << " = " << fMinCoord[n] << endl;
02052 
02053 
02054   // The axes that should be used when minimizing over each of the three variables.
02055   //  const int xAxis[] = {SINSQ, FSTER, FSTER};
02056   //  const int yAxis[] = {DMSQ, DMSQ, SINSQ};
02057 
02058   chiSqrFunc.UsePenalty(!fAllowContoursOutsideRange);
02059 
02060   // These represent the 3 confidence levels 68%, 90%, 99%
02061   const double contVals[] = {2.3, 4.6, 9.2};
02062 
02063   for(int conf = 0; conf < 3; ++conf){
02064     for(unsigned int axisPair = 0; axisPair < fXaxes.size(); ++axisPair){
02065       if(conf == 0 && !fWant68) continue;
02066       if(conf == 1 && !fWant90) continue;
02067       if(conf == 2 && !fWant99) continue;
02068 
02069       // Look up which axes we should be using.
02070       const int x = fXaxes[axisPair];
02071       const int y = fYaxes[axisPair];
02072 
02073       MSG("NCExtrapolation", Msg::kInfo) << "Building contour in "
02074                                          << allNames[x]
02075                                          << " and " << allNames[y]
02076                                          << " (up = " << contVals[conf] << ")...\n";
02077 
02078       GetFuncMinWRTSomeVarsHybrid<GetChiSqrFromDerived> func(chiSqrFunc,
02079                                                              x, y,
02080                                                              start, end);
02081       const std::vector<Coord> contour = FindContour(func,
02082                                                      Coord(fMinCoord[x], fMinCoord[y]),
02083                                                      fMinChiSqr+contVals[conf],
02084                                                      Coord(prec[x], prec[y]));
02085       TGraph* g = new TGraph(contour.size());
02086       for(unsigned int n = 0; n < contour.size(); ++n)
02087         g->SetPoint(n, contour[n].x, contour[n].y);
02088       fContourGraphs.push_back(g);
02089 
02090       MSG("NCExtrapolation", Msg::kInfo) << "there are " << contour.size()
02091                                          << " points on this contour" << endl;
02092     } // end for minVar
02093   } // end for conf
02094 }
02095 
02096 
02097 // ---------------------------------------------------------------------
02098 // Make sure your derived class has overridden GetChiSqrForMap() and that
02099 // everything is ready, and then call this function. It finds the best-fit
02100 // point, and contours at 3 levels of significance, projected onto 3 different
02101 // axes. Sets fMinChiSqr, fBestSinSqr, fBestDeltaMSqr, fBestFSterile.
02102 void NCExtrapolation::MakeDeltaChiSqrMapsMinuit(CoordNDim extraVarsMin,
02103                                                 CoordNDim extraVarsMax,
02104                                                 std::vector<std::string> extraVarsNames,
02105                                                 bool want68,
02106                                                 bool want90,
02107                                                 bool want99)
02108 {
02109   class NCExtrapolationMinuit: public TMinuit
02110   {
02111   public:
02112     NCExtrapolationMinuit(NCExtrapolation* pDeriv, CoordNDim r1, CoordNDim r2, std::vector<std::string> n)
02113       :pDerived(pDeriv), start(r1), end(r2), penalty(true), names(n)
02114     {
02115       assert(start.size() == end.size());
02116     }
02117     // Override TMinuit's Eval function - so that this gets called as the
02118     // minimization function. Redirects to GetChiSqrForMap in an NCExtrapolation
02119     // derived class - and applies quadratic penalties around the physical
02120     // region if asked to.
02121     virtual Int_t Eval(Int_t /*npar*/, Double_t* /*grad*/, Double_t& fval, Double_t* par, Int_t flag)
02122     {
02123       // If we are being asked to do something that isn't just
02124       // calculate the function then we don't know how...
02125       assert(flag == 4);
02126 
02127       CoordNDim r(start.size());
02128       for(unsigned int n = 0; n < start.size(); ++n) r[n] = par[n];
02129 
02130       // If the point is outside the physical region - move it to the boundary
02131       if(penalty)
02132         for(unsigned int n = 0; n < start.size(); ++n){
02133           if(par[n] < start[n]) r[n] = start[n];
02134           if(par[n] > end[n]) r[n] = end[n];
02135         }
02136 
02137       fval = pDerived->GetChiSqrForMap(r, names);
02138 
02139       // If we had to move the point then apply a quadratic penalty term.
02140       // The factor of 1000 was arrived at through trial and error.
02141       if(penalty)
02142         for(unsigned int n = 0; n < start.size(); ++n){
02143           const double wsqr = (start[n]-end[n])*(start[n]-end[n]);
02144           if(par[n] < start[n]) fval+=1e3*(start[n]-par[n])*(start[n]-par[n])/wsqr;
02145           if(par[n] > end[n]) fval+=1e3*(par[n]-end[n])*(par[n]-end[n])/wsqr;
02146         }
02147 
02148       return 0;
02149     }
02150     // The penalty terms are required to keep the best-fit point within physical limits.
02151     // But they interact badly with the contour finder - so turn them off before that.
02152     // CURRENTLY UNUSED
02153     void SetPenalty(bool p){penalty = p;}
02154   protected:
02155     NCExtrapolation* pDerived;
02156     int numberOfParameters;
02157     CoordNDim start, end;
02158     bool penalty;
02159     std::vector<std::string> names;
02160   };
02161 
02162 
02163   assert(extraVarsMin.size() == extraVarsMax.size());
02164 
02165   enum{FSTER, SINSQ, DMSQ}; // Is this already defined somewhere else?
02166 
02167   // Use NCType to get the range of the oscillation parameters.
02168   // We shouldn't be using the dm^2 limits as they aren't physical
02169   // limits - keep them in because we need them to aim the  fitter
02170   // in the right general direction.
02171   CoordNDim start(3);
02172   start[FSTER] = NCType::kFSterileStart;
02173   start[SINSQ] = NCType::kSinSqrStart;
02174   start[DMSQ]  = NCType::kDeltaMSqrStart*1e-3;
02175   // Add the ranges of the additional parameters we were passed.
02176   start.insert(start.end(), extraVarsMin.begin(), extraVarsMin.end());
02177 
02178   CoordNDim end(3);
02179   end[FSTER] = NCType::kFSterileEnd;
02180   end[SINSQ] = NCType::kSinSqrEnd;
02181   end[DMSQ]  = NCType::kDeltaMSqrEnd*1e-3;
02182   end.insert(end.end(), extraVarsMax.begin(), extraVarsMax.end());
02183 
02184   std::vector<std::string> allNames(3);
02185   allNames[FSTER] = "fster";
02186   allNames[SINSQ] = "sinsq";
02187   allNames[DMSQ] = "dmsq";
02188   allNames.insert(allNames.end(), extraVarsNames.begin(), extraVarsNames.end());
02189   while(allNames.size() < start.size()) allNames.push_back("[unknown]");
02190 
02191   NCExtrapolationMinuit minu(this, start, end, allNames);
02192   minu.SetPrintLevel(-1); // Shut Minuit up.
02193   minu.Command("set strategy 2"); // Be careful, instead of fast.
02194 
02195   for(int n = 0; n < int(3+extraVarsMin.size()); ++n)
02196     // NB - no parameter limits imposed.
02197     minu.DefineParameter(n, "", (start[n]+end[n])/2, (end[n]-start[n])/4, 0, 0);
02198 
02199   // Minuit tries to return a lot of parameters we don't want to keep.
02200   double junkd; int junki; TString junks;
02201 
02202   if(minu.Migrad()){
02203     MSG("NCExtrapolation", Msg::kWarning) << "Migrad failed, falling back to Simplex.\n";
02204     minu.SetPrintLevel(0); // Things are going wrong, we should let the user see.
02205     minu.mnsimp();
02206     minu.Migrad();
02207   }
02208 
02209   minu.mnstat(fMinChiSqr, junkd, junkd, junki, junki, junki);
02210 
02211   minu.GetParameter(0, fBestFSterile, junkd);
02212   minu.GetParameter(1, fBestSinSqr, junkd);
02213   minu.GetParameter(2, fBestDeltaMSqr, junkd);
02214 
02215   MSG("NCExtrapolation", Msg::kInfo) << "Best fit : f_s = " << fBestFSterile
02216                                              << " sin^2 = " << fBestSinSqr
02217                                               << " dm^2 = " << fBestDeltaMSqr;
02218   if(extraVarsMin.size() > 0){
02219     MSG("NCExtrapolation", Msg::kInfo) << endl
02220                                        << " Additional parameters:";
02221     for(unsigned int n = 3; n < 3+extraVarsMin.size(); ++n){
02222       double val;
02223       minu.GetParameter(n, val, junkd);
02224       MSG("NCExtrapolation", Msg::kInfo) << allNames.at(n) << " "
02225                                          << val << " ";
02226     }
02227   }
02228   MSG("NCExtrapolation", Msg::kInfo) << endl;
02229 
02230   // The edge penalties break the contour finder so turn them off.
02231   // It causes wobbles in the contours - but seemingly not too bad.
02232   // And it allows us to get the right results re physical limits,
02233   // none of the other methods I tried work.
02234   //  minu.SetPenalty(false);
02235 
02236   // QUESTION: are these the right values for a fit with more variables?
02237   const double contVals[] = {2.3, 4.6, 9.2};
02238 
02239   // The axes that should be used when minimizing over each of the three variables.
02240   const int xAxis[] = {SINSQ, FSTER, FSTER};
02241   const int yAxis[] = {DMSQ, DMSQ, SINSQ};
02242   // And human-readable form.
02243   const TString text[] = {"sin^2 and dm^2", "f_s and dm^2", "f_s and sin^2"};
02244 
02245   const int numContourPoints = 300;
02246 
02247   for(int c = 0; c < 3; ++c){
02248     for(int n = 0; n < 3; ++n){
02249       if( (c == 0 && !want68) || (c == 1 && !want90) || (c == 2 && !want99) ){
02250         fContourGraphs.push_back(new TGraph);
02251         continue;
02252       }
02253       MSG("NCExtrapolation", Msg::kInfo) << "Building contour in " << text[n]
02254                                          << " (up = " << contVals[c] << ")...\n";
02255 
02256       // Apply physical limits to those parameters being minimized over.
02257       // for(int p = 0; p < int(3+extraVarsMin.size()); ++p){
02258       //   if(n != xAxis[n] && n != yAxis[n]){
02259       //     // Passing the axis number as a double is bad - but unavoidable.
02260       //     double paramList[] = {p, start[p], end[p]};
02261       //     minu.mnexcm("set limits", paramList, 3, junki);
02262       //   }
02263       // }
02264 
02265       minu.SetErrorDef(contVals[c]);
02266       TGraph* g = (TGraph*)minu.Contour(numContourPoints, xAxis[n], yAxis[n]);
02267       fContourGraphs.push_back(g);
02268       if(minu.GetStatus()) MSG("NCExtrapolation", Msg::kWarning) << "Couldn't find contour.\n";
02269 
02270       //      minu.Command("set limits"); // Remove all parameter limits.
02271     }
02272   }
02273 }

Generated on Thu Nov 1 11:51:50 2007 for loon by  doxygen 1.3.9.1