00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00060
00061 #include "Minuit2/MinuitParameter.h"
00062 #include "TFile.h"
00063 #include "TH1D.h"
00064 #include "TH1F.h"
00065 #include "TMinuit.h"
00066
00067 #include "MessageService/MsgService.h"
00068 #include "NtupleUtils/NuCrossSectionFitter.h"
00069 #include "NtupleUtils/NuCuts.h"
00070 #include "NtupleUtils/NuSystematic.h"
00071 #include "NtupleUtils/NuTreeWrapper.h"
00072 #include "NtupleUtils/NuXMLConfig.h"
00073
00074 ClassImp(NuCrossSectionFitter)
00075
00076 CVSID("$Id: NuCrossSectionFitter.cxx,v 1.10 2008/05/02 19:36:16 evans Exp $");
00077
00078 using namespace NuXSecFit;
00079
00080 using std::string;
00081 using std::vector;
00082 using ROOT::Minuit2::MinuitParameter;
00083 using ROOT::Minuit2::MnUserParameterState;
00084
00085
00086 NuCrossSectionFitter::NuCrossSectionFitter()
00087 : fndDataPoT(0.0),
00088 fndMCPoT(0.0)
00089 {
00090
00091 fanaVersion = NuCuts::kJJE1;
00092
00093 fnuSystematic = new NuSystematic();
00094
00095 fhNDMCRecoENuMuCC = 0;
00096 fhNDMCRecoENuMuBarCC = 0;
00097 fhNDDataRecoENuMuCC = 0;
00098 fhNDDataRecoENuMuBarCC = 0;
00099 fhNDRawMCTrueECCNuMu = 0;
00100 fhNDRawMCTrueECCNuMuBar = 0;
00101 fhNDRawMCRecoECCNuMu = 0;
00102 fhNDRawMCRecoECCNuMuBar = 0;
00103
00104 fhNDNuMuCCDataFromFile = 0;
00105 fhNDNuMuBarCCDataFromFile = 0;
00106
00107 fOutputFile = 0;
00108
00109 ftNDDataTree = 0;
00110 ftNDMCTree = 0;
00111
00112 fFitter = new TFitterMinuit();
00113 fFitter->CreateMinimizer();
00114 fFitter->SetMinuitFCN(this);
00115
00116
00117 fvNDFakeTrueENuMuCCBins.push_back(30.0);
00118 fvNDFakeTrueENuMuBarCCBins.push_back(30.0);
00119 for (Int_t counter=0; counter<10; ++counter){
00120 fvfakepars.push_back(1.0);
00121 }
00122 }
00123
00124
00125 NuCrossSectionFitter::NuCrossSectionFitter(const NuXMLConfig& xmlConfig)
00126 : fndDataPoT(0.0),
00127 fndMCPoT(0.0)
00128 {
00129
00130 fanaVersion = NuCuts::kJJE1;
00131
00132 fnuSystematic = new NuSystematic(xmlConfig);
00133
00134 fhNDMCRecoENuMuCC = 0;
00135 fhNDMCRecoENuMuBarCC = 0;
00136 fhNDDataRecoENuMuCC = 0;
00137 fhNDDataRecoENuMuBarCC = 0;
00138 fhNDRawMCTrueECCNuMu = 0;
00139 fhNDRawMCTrueECCNuMuBar = 0;
00140 fhNDRawMCRecoECCNuMu = 0;
00141 fhNDRawMCRecoECCNuMuBar = 0;
00142
00143 fhNDNuMuCCDataFromFile = 0;
00144 fhNDNuMuBarCCDataFromFile = 0;
00145
00146 fOutputFile = 0;
00147
00148 ftNDDataTree = 0;
00149 ftNDMCTree = 0;
00150
00151 fFitter = new TFitterMinuit();
00152 fFitter->CreateMinimizer();
00153 fFitter->SetMinuitFCN(this);
00154
00155
00156 fvNDFakeTrueENuMuCCBins.push_back(30.0);
00157 fvNDFakeTrueENuMuBarCCBins.push_back(30.0);
00158 for (Int_t counter=0; counter<10; ++counter){
00159 fvfakepars.push_back(1.0);
00160 }
00161 }
00162
00163
00164 NuCrossSectionFitter::~NuCrossSectionFitter()
00165 {
00166 if (fOutputFile){
00167 fOutputFile->Close();
00168 delete fOutputFile;
00169 fOutputFile = 0;
00170 }
00171 if (fhNDMCRecoENuMuCC){delete fhNDMCRecoENuMuCC; fhNDMCRecoENuMuCC=0;}
00172 if (fhNDMCRecoENuMuBarCC){
00173 delete fhNDMCRecoENuMuBarCC; fhNDMCRecoENuMuBarCC = 0;
00174 }
00175 if (fhNDDataRecoENuMuCC){
00176 delete fhNDDataRecoENuMuCC; fhNDDataRecoENuMuCC = 0;
00177 }
00178 if (fhNDDataRecoENuMuBarCC){
00179 delete fhNDDataRecoENuMuBarCC; fhNDDataRecoENuMuBarCC = 0;
00180 }
00181 if (fhNDRawMCTrueECCNuMu){
00182 delete fhNDRawMCTrueECCNuMu; fhNDRawMCTrueECCNuMu = 0;
00183 }
00184 if (fhNDRawMCTrueECCNuMuBar){
00185 delete fhNDRawMCTrueECCNuMuBar; fhNDRawMCTrueECCNuMuBar = 0;
00186 }
00187 if (fhNDRawMCRecoECCNuMu){
00188 delete fhNDRawMCRecoECCNuMu; fhNDRawMCRecoECCNuMu = 0;
00189 }
00190 if (fhNDRawMCRecoECCNuMuBar){
00191 delete fhNDRawMCRecoECCNuMuBar; fhNDRawMCRecoECCNuMuBar = 0;
00192 }
00193
00194 if (fhNDNuMuCCDataFromFile){
00195 delete fhNDNuMuCCDataFromFile; fhNDNuMuCCDataFromFile = 0;
00196 }
00197 if (fhNDNuMuBarCCDataFromFile){
00198 delete fhNDNuMuBarCCDataFromFile; fhNDNuMuBarCCDataFromFile = 0;
00199 }
00200
00201 if (ftNDDataTree){
00202 delete ftNDDataTree; ftNDDataTree = 0;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212 }
00213
00214
00215 void NuCrossSectionFitter::OutputFileName(const string outFile)
00216 {
00217 if (fOutputFile){
00218 fOutputFile->Close();
00219 delete fOutputFile;
00220 fOutputFile = 0;
00221 }
00222 fOutputFile = new TFile(outFile.c_str(),"RECREATE");
00223 }
00224
00225
00226 double NuCrossSectionFitter::operator () (const vector<double>& pars) const
00227 {
00228 static Int_t fitcounter = 0;
00229 if (!(fitcounter%50)){
00230 cout << "Minuit TF call " << fitcounter << endl;
00231 }
00232 ++fitcounter;
00233 this->FillTruthWeightedHistograms(pars);
00234 return this->CalculateLikelihood();
00235 }
00236
00237
00238 const Double_t NuCrossSectionFitter::CalculateLikelihood() const
00239 {
00240
00241
00242 Double_t like = 0;
00243
00244 for (Int_t i=1; i<=fhNDMCRecoENuMuCC->GetNbinsX(); ++i){
00245
00246 Double_t mnu = fhNDMCRecoENuMuCC->GetBinContent(i);
00247 Double_t dnu = fhNDDataRecoENuMuCC->GetBinContent(i);
00248 if (mnu<0.0001){mnu = 0.0001;}
00249 if (dnu){
00250 like += 2*(mnu - dnu + dnu*log(dnu/mnu));
00251 }
00252 else{like += 2*(mnu - dnu);}
00253 }
00254
00255 for (Int_t i=1; i<=fhNDMCRecoENuMuBarCC->GetNbinsX(); ++i){
00256 Double_t mbar = fhNDMCRecoENuMuBarCC->GetBinContent(i);
00257 Double_t dbar = fhNDDataRecoENuMuBarCC->GetBinContent(i);
00258 if (mbar<0.0001){mbar = 0.0001;}
00259 if (dbar){
00260 like += 2*(mbar - dbar + dbar*log(dbar/mbar));
00261 }
00262 else{like += 2*(mbar - dbar);}
00263 }
00264
00265 return like;
00266 }
00267
00268
00269 void NuCrossSectionFitter::FillTruthWeightedHistograms
00270 (const vector<double>& par) const
00271 {
00272
00273 fhNDMCRecoENuMuCC->Reset();
00274 fhNDMCRecoENuMuBarCC->Reset();
00275
00276 Int_t numnubins = fvNDTrueENuMuCCBins.size();
00277 Int_t numbarbins = fvNDTrueENuMuBarCCBins.size();
00278
00279 Int_t shwEpar = numnubins + numbarbins + 1;
00280 Double_t shwEShift = par[shwEpar];
00281 Int_t trkEpar = numnubins + numbarbins + 2;
00282 Double_t trkEShift = par[trkEpar];
00283
00284
00285 for (vector<NuEvent>::const_iterator itBar
00286 = fvNDMCCCNuMuBarEvents.begin();
00287 itBar!=fvNDMCCCNuMuBarEvents.end();
00288 ++itBar){
00289 NuEvent barEvent = *itBar;
00290 Int_t truthpar = this->TruthIndex(barEvent);
00291 Double_t barweight = 1.0;
00292 barweight *= barEvent.rw;
00293 if (truthpar>=0){
00294 barweight *= par[truthpar];
00295 }
00296
00297 Double_t recoNuE = shwEShift*(barEvent.shwEn)
00298 + trkEShift*(barEvent.trkEn);
00299 fhNDMCRecoENuMuBarCC->Fill(recoNuE,barweight);
00300 }
00301 if (fndMCPoT){fhNDMCRecoENuMuBarCC->Scale(fndDataPoT/fndMCPoT);}
00302
00303
00304 for (vector<NuEvent>::const_iterator itNu
00305 = fvNDMCCCNuMuEvents.begin();
00306 itNu!=fvNDMCCCNuMuEvents.end();
00307 ++itNu){
00308 NuEvent nuEvent = *itNu;
00309 Int_t truthpar = this->TruthIndex(nuEvent);
00310 Double_t nuweight = 1.0;
00311 nuweight *= nuEvent.rw;
00312 if (truthpar>=0){
00313 nuweight *= par[truthpar];
00314 }
00315
00316 Double_t recoNuE = shwEShift*(nuEvent.shwEn)
00317 + trkEShift*(nuEvent.trkEn);
00318 fhNDMCRecoENuMuCC->Fill(recoNuE,nuweight);
00319 }
00320 if (fndMCPoT){fhNDMCRecoENuMuCC->Scale(fndDataPoT/fndMCPoT);}
00321 }
00322
00323
00324 void NuCrossSectionFitter::FillTruthWeightedHistogramsSmooth
00325 (const vector<double>& par) const
00326 {
00327
00328 fhNDMCRecoENuMuCC->Reset();
00329 fhNDMCRecoENuMuBarCC->Reset();
00330
00331 Int_t numnubins = fvNDTrueENuMuCCBins.size();
00332 Int_t numbarbins = fvNDTrueENuMuBarCCBins.size();
00333
00334 Int_t shwEpar = numnubins + numbarbins + 1;
00335 Double_t shwEShift = par[shwEpar];
00336 Int_t trkEpar = numnubins + numbarbins + 2;
00337 Double_t trkEShift = par[trkEpar];
00338
00339
00340 for (vector<NuEvent>::const_iterator itBar
00341 = fvNDMCCCNuMuBarEvents.begin();
00342 itBar!=fvNDMCCCNuMuBarEvents.end();
00343 ++itBar){
00344 NuEvent barEvent = *itBar;
00345 Int_t truthpar = this->TruthIndex(barEvent);
00346 Double_t barweight = 1.0;
00347 barweight *= barEvent.rw;
00348 if (truthpar>=0){
00349 barweight *= par[truthpar];
00350 }
00351
00352 Double_t recoNuE = shwEShift*(barEvent.shwEn)
00353 + trkEShift*(barEvent.trkEn);
00354
00355
00356
00357
00358 Int_t thisBin = fhNDMCRecoENuMuBarCC->GetXaxis()->FindFixBin(recoNuE);
00359
00360 Double_t binWidth = fhNDMCRecoENuMuBarCC->GetXaxis()->GetBinWidth(thisBin);
00361
00362 Double_t binCenter = fhNDMCRecoENuMuBarCC->GetXaxis()->GetBinCenter(thisBin);
00363
00364 Double_t fracThis =
00365 1.0 - (fabs(recoNuE-binCenter))/binWidth;
00366 if ((fhNDMCRecoENuMuBarCC->GetXaxis()->GetNbins()+1)==thisBin){
00367 fracThis = 1.0;
00368 }
00369 if (fracThis<0.0){cout << "Too many bar events!!!!!!!!!!!!!!!" << fracThis << endl;}
00370 fhNDMCRecoENuMuBarCC->AddBinContent(thisBin,fracThis*barweight);
00371
00372 if (recoNuE>=binCenter){
00373 fhNDMCRecoENuMuBarCC->AddBinContent(thisBin+1,(1.0-fracThis)*barweight);
00374 }
00375 else{
00376 if (thisBin>1){
00377 fhNDMCRecoENuMuBarCC->AddBinContent(thisBin-1,(1.0-fracThis)*barweight);
00378 }
00379 else{
00380 fhNDMCRecoENuMuBarCC->AddBinContent(thisBin,(1.0-fracThis)*barweight);
00381 }
00382 }
00383
00384
00385
00386 this->FillSmooth(fhNDMCRecoENuMuBarCC,recoNuE,barweight);
00387 }
00388 if (fndMCPoT){fhNDMCRecoENuMuBarCC->Scale(fndDataPoT/fndMCPoT);}
00389
00390
00391 for (vector<NuEvent>::const_iterator itNu
00392 = fvNDMCCCNuMuEvents.begin();
00393 itNu!=fvNDMCCCNuMuEvents.end();
00394 ++itNu){
00395 NuEvent nuEvent = *itNu;
00396 Int_t truthpar = this->TruthIndex(nuEvent);
00397 Double_t nuweight = 1.0;
00398 nuweight *= nuEvent.rw;
00399 if (truthpar>=0){
00400 nuweight *= par[truthpar];
00401 }
00402
00403 Double_t recoNuE = shwEShift*(nuEvent.shwEn)
00404 + trkEShift*(nuEvent.trkEn);
00405 fhNDMCRecoENuMuCC->Fill(recoNuE,nuweight);
00406 }
00407 if (fndMCPoT){fhNDMCRecoENuMuCC->Scale(fndDataPoT/fndMCPoT);}
00408 }
00409
00410
00411 void NuCrossSectionFitter::FillSmooth(const TH1D*,
00412 Double_t ,
00413 Double_t ) const
00414 {
00415 }
00416
00417
00418 const Int_t NuCrossSectionFitter::TruthIndex(const NuEvent& info) const
00419 {
00420 Int_t numnubins = fvNDTrueENuMuCCBins.size();
00421 Int_t numbarbins = fvNDTrueENuMuBarCCBins.size();
00422
00423 Int_t type = info.inu;
00424 const vector<Double_t>* truthbins;
00425 Int_t offset = 0;
00426 Int_t numbins = 0;
00427 if (14 == type){
00428 truthbins = &fvNDTrueENuMuCCBins;
00429 numbins = numnubins;
00430 offset = 0;
00431 }
00432 else if (-14 == type){
00433 truthbins = &fvNDTrueENuMuBarCCBins;
00434 numbins = numbarbins;
00435 offset = numnubins;
00436 }
00437 else{
00438 return numnubins + numbarbins;
00439 }
00440 for (Int_t i=1; i<numbins; ++i){
00441 if ((*truthbins)[i]>info.neuEnMC){
00442 return i - 1 + offset;
00443 }
00444 }
00445 if ((14 == type) || (-14 == type)){
00446 return (numbins + offset);
00447 }
00448 return numnubins + numbarbins;
00449 }
00450
00451
00452 const Int_t NuCrossSectionFitter::FakeTruthIndex(const NuEvent& info) const
00453 {
00454 Int_t numnubins = fvNDFakeTrueENuMuCCBins.size();
00455 Int_t numbarbins = fvNDFakeTrueENuMuBarCCBins.size();
00456
00457 Int_t type = info.inu;
00458 const vector<Double_t>* truthbins;
00459 Int_t offset = 0;
00460 Int_t numbins = 0;
00461 if (14 == type){
00462 truthbins = &fvNDFakeTrueENuMuCCBins;
00463 numbins = numnubins;
00464 offset = 0;
00465 }
00466 else if (-14 == type){
00467 truthbins = &fvNDFakeTrueENuMuBarCCBins;
00468 numbins = numbarbins;
00469 offset = numnubins;
00470 }
00471 else{
00472 return numnubins + numbarbins;
00473 }
00474 for (Int_t i=1; i<numbins; ++i){
00475 if ((*truthbins)[i]>info.neuEnMC){
00476 return i - 1 + offset;
00477 }
00478 }
00479 if ((14 == type) || (-14 == type)){
00480 return (numbins + offset);
00481 }
00482 return numnubins + numbarbins;
00483 }
00484
00485
00486 void NuCrossSectionFitter::CalculateFDWeights()
00487 {
00488 const Bool_t goodConfig = this->Config();
00489 if (!goodConfig){
00490 MSG("NuCrossSectionFitter",Msg::kFatal)
00491 << "About to die due to bad config."
00492 << endl;
00493 return;
00494 }
00495 MSG("NuCrossSectionFitter",Msg::kInfo)
00496 << "Configured successfully. Starting XFit."
00497 << endl;
00498
00499 this->DoNDFit();
00500
00501
00502 }
00503
00504
00505 void NuCrossSectionFitter::SetupPars()
00506 {
00507
00508
00509 Int_t parnum=0;
00510 for (UInt_t i=0; i<(fvNDTrueENuMuCCBins.size()); ++i,++parnum){
00511 if (fvNDTrueENuMuCCBins.size()-1 == i){
00512 fFitter->SetParameter(parnum,
00513 Form("NuMuOverflow",i),
00514 1.0,0.2,1.0,0.0);
00515 fFitter->FixParameter(parnum);
00516 }
00517 else{
00518 fFitter->SetParameter(parnum,Form("NuMu%d",i),1.0,0.2,1.0,0.0);
00519 }
00520 }
00521
00522 for (UInt_t i=0; i<(fvNDTrueENuMuBarCCBins.size()); ++i,++parnum){
00523 if (fvNDTrueENuMuBarCCBins.size()-1 == i){
00524 fFitter->SetParameter(parnum,
00525 Form("NuMuBarOverFlow",i),
00526 1.0,0.2,1.0,0.0);
00527 fFitter->FixParameter(parnum);
00528 }
00529 else{
00530 fFitter->SetParameter(parnum,Form("NuMuBar%d",i),1.0,0.2,1.0,0.0);
00531 }
00532 }
00533 fFitter->SetParameter(parnum,"OtherPar",1.0,0.2,1.0,0.0);
00534 fFitter->FixParameter(parnum);
00535 parnum++;
00536 fFitter->SetParameter(parnum,"ShwEShift",1.0,0.0001,1.0,0.0);
00537 fFitter->FixParameter(parnum);
00538 parnum++;
00539 fFitter->SetParameter(parnum,"TrkEShift",1.0,0.2,1.0,0.0);
00540 fFitter->FixParameter(parnum);
00541
00542 return;
00543 }
00544
00545
00546 void NuCrossSectionFitter::ReleaseNonOverflowNonNDFitPars()
00547 {
00548 const TFitterMinuit* stupidRoot = fFitter;
00549 const vector<MinuitParameter>& vMinuitPars =
00550 stupidRoot->State().MinuitParameters();
00551
00552 Int_t parnum=0;
00553 for (UInt_t i=0; i<(fvNDTrueENuMuCCBins.size()); ++i,++parnum){
00554 if (fvNDTrueENuMuCCBins.size()-1 == i){
00555 if (!vMinuitPars[parnum].IsFixed()){
00556 fFitter->FixParameter(parnum);
00557 }
00558 }
00559 else{
00560 if (vMinuitPars[parnum].IsFixed()){
00561 fFitter->ReleaseParameter(parnum);
00562 }
00563 }
00564 }
00565 for (UInt_t i=0; i<(fvNDTrueENuMuBarCCBins.size()); ++i,++parnum){
00566 if (fvNDTrueENuMuBarCCBins.size()-1 == i){
00567 if (!vMinuitPars[parnum].IsFixed()){
00568 fFitter->FixParameter(parnum);
00569 }
00570 }
00571 else{
00572 if (vMinuitPars[parnum].IsFixed()){
00573 fFitter->ReleaseParameter(parnum);
00574 }
00575 }
00576 }
00577 if (!vMinuitPars[parnum].IsFixed()){
00578 fFitter->FixParameter(parnum);
00579 }
00580 parnum++;
00581 if (!vMinuitPars[parnum].IsFixed()){
00582 fFitter->FixParameter(parnum);
00583 }
00584 parnum++;
00585 if (!vMinuitPars[parnum].IsFixed()){
00586 fFitter->FixParameter(parnum);
00587 }
00588
00589 return;
00590 }
00591
00592
00593 void NuCrossSectionFitter::ReleaseNonOverflowPars()
00594 {
00595 const TFitterMinuit* stupidRoot = fFitter;
00596 const vector<MinuitParameter>& vMinuitPars =
00597 stupidRoot->State().MinuitParameters();
00598
00599 Int_t parnum=0;
00600 for (UInt_t i=0; i<(fvNDTrueENuMuCCBins.size()); ++i,++parnum){
00601 if (fvNDTrueENuMuCCBins.size()-1 == i){
00602 if (!vMinuitPars[parnum].IsFixed()){
00603 fFitter->FixParameter(parnum);
00604 }
00605 }
00606 else{
00607 if (vMinuitPars[parnum].IsFixed()){
00608 fFitter->ReleaseParameter(parnum);
00609 }
00610 }
00611 }
00612 for (UInt_t i=0; i<(fvNDTrueENuMuBarCCBins.size()); ++i,++parnum){
00613 if (fvNDTrueENuMuBarCCBins.size()-1 == i){
00614 if (!vMinuitPars[parnum].IsFixed()){
00615 fFitter->FixParameter(parnum);
00616 }
00617 }
00618 else{
00619 if (vMinuitPars[parnum].IsFixed()){
00620 fFitter->ReleaseParameter(parnum);
00621 }
00622 }
00623 }
00624 if (!vMinuitPars[parnum].IsFixed()){
00625 fFitter->FixParameter(parnum);
00626 }
00627 parnum++;
00628 if (vMinuitPars[parnum].IsFixed()){
00629 fFitter->ReleaseParameter(parnum);
00630 }
00631 parnum++;
00632 if (vMinuitPars[parnum].IsFixed()){
00633 fFitter->ReleaseParameter(parnum);
00634 }
00635
00636 return;
00637 }
00638
00639
00640 void NuCrossSectionFitter::FixAllParsExcept(const Int_t freeparnum)
00641 {
00642 const TFitterMinuit* stupidRoot = fFitter;
00643 const vector<MinuitParameter>& vMinuitPars =
00644 stupidRoot->State().MinuitParameters();
00645
00646 Int_t parnum=0;
00647 for (UInt_t i=0; i<(fvNDTrueENuMuCCBins.size()); ++i,++parnum){
00648 if (!vMinuitPars[parnum].IsFixed()){
00649 fFitter->FixParameter(parnum);
00650 }
00651 }
00652 for (UInt_t i=0; i<(fvNDTrueENuMuBarCCBins.size()); ++i,++parnum){
00653 if (!vMinuitPars[parnum].IsFixed()){
00654 fFitter->FixParameter(parnum);
00655 }
00656 }
00657 if (!vMinuitPars[parnum].IsFixed()){
00658 fFitter->FixParameter(parnum);
00659 }
00660 parnum++;
00661 if (!vMinuitPars[parnum].IsFixed()){
00662 fFitter->FixParameter(parnum);
00663 }
00664 parnum++;
00665 if (!vMinuitPars[parnum].IsFixed()){
00666 fFitter->FixParameter(parnum);
00667 }
00668
00669 fFitter->ReleaseParameter(freeparnum);
00670
00671 return;
00672 }
00673
00674
00675 const Bool_t NuCrossSectionFitter::DoNDFit()
00676 {
00677 this->SetupPars();
00678
00679 this->FixAllParsExcept(0);
00680
00681 fFitter->Minimize();
00682 fFitter->PrintResults(0,0);
00683
00684 this->FixAllParsExcept(1);
00685
00686 fFitter->Minimize();
00687 fFitter->PrintResults(0,0);
00688
00689 this->ReleaseNonOverflowNonNDFitPars();
00690 fFitter->Minimize();
00691 fFitter->PrintResults(0,0);
00692
00693
00694
00695
00696
00697 const vector<Double_t> vBestFit = this->GetBestFitPars();
00698 this->FillTruthWeightedHistograms(vBestFit);
00699 fOutputFile->cd();
00700 fhNDMCRecoENuMuCC->Write("BestFitNDMCRecoENuMuCC");
00701 fhNDMCRecoENuMuBarCC->Write("BestFitNDMCRecoENuMuBarCC");
00702 return true;
00703 }
00704
00705
00706 const vector<Double_t> NuCrossSectionFitter::GetBestFitPars() const
00707 {
00708 vector<Double_t> vbestfit;
00709 Int_t parnum=0;
00710 for (UInt_t i=0; i<(fvNDTrueENuMuCCBins.size()); ++i,++parnum){
00711 vbestfit.push_back(fFitter->GetParameter(parnum));
00712 }
00713 for (UInt_t i=0; i<(fvNDTrueENuMuBarCCBins.size()); ++i,++parnum){
00714 vbestfit.push_back(fFitter->GetParameter(parnum));
00715 }
00716 vbestfit.push_back(fFitter->GetParameter(parnum));
00717 parnum++;
00718 vbestfit.push_back(fFitter->GetParameter(parnum));
00719 parnum++;
00720 vbestfit.push_back(fFitter->GetParameter(parnum));
00721
00722 return vbestfit;
00723 }
00724
00725
00726 const Bool_t NuCrossSectionFitter::Config()
00727 {
00728 Bool_t goodConfig = true;
00729 if (!this->ConfigND()) goodConfig = false;
00730 if (!this->ConfigFD()) goodConfig = false;
00731 return goodConfig;
00732 }
00733
00734
00735 const Bool_t NuCrossSectionFitter::ConfigND()
00736 {
00737 Bool_t goodConfig = true;
00738 if (!this->CreateNDHistograms()) goodConfig = false;
00739
00740 MSG("NuCrossSectionFitter",Msg::kInfo)
00741 << "NDHistograms created"
00742 << endl;
00743
00744 if (!this->FillNDDataHistograms()) goodConfig = false;
00745
00746 MSG("NuCrossSectionFitter",Msg::kInfo)
00747 << "NDHistograms filled"
00748 << endl;
00749
00750 if (!this->CacheNDMCEvents()) goodConfig = false;
00751
00752 MSG("NuCrossSectionFitter",Msg::kInfo)
00753 << "ND MC events cached"
00754 << endl;
00755
00756 return goodConfig;
00757 }
00758
00759
00760 const Bool_t NuCrossSectionFitter::ConfigFD()
00761 {
00762 return true;
00763 }
00764
00765
00766 const Bool_t NuCrossSectionFitter::CreateNDHistograms()
00767 {
00768 Bool_t goodConfig = true;
00769 if (!this->CreateNDNuMuCCDataHisto()) goodConfig = false;
00770 if (!this->CreateNDNuMuBarCCDataHisto()) goodConfig = false;
00771 if (!this->CreateNDNuMuCCMCHisto()) goodConfig = false;
00772 if (!this->CreateNDNuMuBarCCMCHisto()) goodConfig = false;
00773 if (!this->CreateNDRawMCRecoECCNuMuHisto()) goodConfig = false;
00774 if (!this->CreateNDRawMCRecoECCNuMuBarHisto()) goodConfig = false;
00775 if (!this->CreateNDRawMCTrueECCNuMuHisto()) goodConfig = false;
00776 if (!this->CreateNDRawMCTrueECCNuMuBarHisto()) goodConfig = false;
00777 return goodConfig;
00778 }
00779
00780
00781 const Bool_t NuCrossSectionFitter::CreateNDNuMuCCMCHisto()
00782 {
00783 if (fhNDMCRecoENuMuCC) {
00784 delete fhNDMCRecoENuMuCC; fhNDMCRecoENuMuCC = 0;
00785 }
00786
00787 if (fhNDNuMuCCDataFromFile && fhNDNuMuBarCCDataFromFile){
00788 fhNDMCRecoENuMuCC = new TH1D(*fhNDNuMuCCDataFromFile);
00789 fhNDMCRecoENuMuCC->Reset();
00790 return true;
00791 }
00792
00793 Int_t size = fvNDRecoENuMuCCBins.size();
00794 if (!size){
00795 MSG("NuCrossSectionFitter",Msg::kWarning)
00796 << "ND reconstructed energy binning not supplied."
00797 << endl;
00798 return false;
00799 }
00800
00801 Double_t* recoEBinEdges = new Double_t[size];
00802
00803 Int_t i=0;
00804 for (vector<Double_t>::const_iterator it =
00805 fvNDRecoENuMuCCBins.begin();
00806 it != fvNDRecoENuMuCCBins.end();
00807 ++it, ++i){
00808 recoEBinEdges[i] = *it;
00809 }
00810
00811 fhNDMCRecoENuMuCC = new TH1D("fhNDMCRecoENuMuCC",
00812 "",
00813 size-1,
00814 recoEBinEdges);
00815
00816 if (!fhNDMCRecoENuMuCC) return false;
00817 return true;
00818 }
00819
00820
00821 const Bool_t NuCrossSectionFitter::CreateNDRawMCRecoECCNuMuHisto()
00822 {
00823 if (fhNDRawMCRecoECCNuMu) {
00824 delete fhNDRawMCRecoECCNuMu; fhNDRawMCRecoECCNuMu = 0;
00825 }
00826
00827 if (fhNDNuMuCCDataFromFile && fhNDNuMuBarCCDataFromFile){
00828 fhNDRawMCRecoECCNuMu = new TH1D(*fhNDNuMuCCDataFromFile);
00829 fhNDRawMCRecoECCNuMu->Reset();
00830 return true;
00831 }
00832
00833 Int_t size = fvNDRecoENuMuCCBins.size();
00834 if (!size){
00835 MSG("NuCrossSectionFitter",Msg::kWarning)
00836 << "ND reconstructed energy binning not supplied."
00837 << endl;
00838 return false;
00839 }
00840
00841 Double_t* recoEBinEdges = new Double_t[size];
00842
00843 Int_t i=0;
00844 for (vector<Double_t>::const_iterator it =
00845 fvNDRecoENuMuCCBins.begin();
00846 it != fvNDRecoENuMuCCBins.end();
00847 ++it, ++i){
00848 recoEBinEdges[i] = *it;
00849 }
00850
00851 fhNDRawMCRecoECCNuMu = new TH1D("fhNDRawMCRecoECCNuMu",
00852 "",
00853 size-1,
00854 recoEBinEdges);
00855
00856 if (!fhNDRawMCRecoECCNuMu) return false;
00857 return true;
00858 }
00859
00860
00861 const Bool_t NuCrossSectionFitter::CreateNDRawMCRecoECCNuMuBarHisto()
00862 {
00863 if (fhNDRawMCRecoECCNuMuBar) {
00864 delete fhNDRawMCRecoECCNuMuBar; fhNDRawMCRecoECCNuMuBar = 0;
00865 }
00866
00867 if (fhNDNuMuCCDataFromFile && fhNDNuMuBarCCDataFromFile){
00868 fhNDRawMCRecoECCNuMuBar = new TH1D(*fhNDNuMuBarCCDataFromFile);
00869 fhNDRawMCRecoECCNuMuBar->Reset();
00870 return true;
00871 }
00872
00873 Int_t size = fvNDRecoENuMuBarCCBins.size();
00874 if (!size){
00875 MSG("NuCrossSectionFitter",Msg::kWarning)
00876 << "ND reconstructed energy binning not supplied."
00877 << endl;
00878 return false;
00879 }
00880
00881 Double_t* recoEBinEdges = new Double_t[size];
00882
00883 Int_t i=0;
00884 for (vector<Double_t>::const_iterator it =
00885 fvNDRecoENuMuBarCCBins.begin();
00886 it != fvNDRecoENuMuBarCCBins.end();
00887 ++it, ++i){
00888 recoEBinEdges[i] = *it;
00889 }
00890
00891 fhNDRawMCRecoECCNuMuBar = new TH1D("fhNDRawMCRecoECCNuMuBar",
00892 "",
00893 size-1,
00894 recoEBinEdges);
00895
00896 if (!fhNDRawMCRecoECCNuMuBar) return false;
00897 return true;
00898 }
00899
00900
00901 const Bool_t NuCrossSectionFitter::CreateNDRawMCTrueECCNuMuHisto()
00902 {
00903 if (fhNDRawMCTrueECCNuMu) {
00904 delete fhNDRawMCTrueECCNuMu; fhNDRawMCTrueECCNuMu = 0;
00905 }
00906
00907 Int_t size = fvNDTrueENuMuCCBins.size();
00908 if (!size){
00909 MSG("NuCrossSectionFitter",Msg::kWarning)
00910 << "ND true energy binning not supplied."
00911 << endl;
00912 return false;
00913 }
00914
00915 Double_t* recoEBinEdges = new Double_t[size];
00916
00917 Int_t i=0;
00918 for (vector<Double_t>::const_iterator it =
00919 fvNDTrueENuMuCCBins.begin();
00920 it != fvNDTrueENuMuCCBins.end();
00921 ++it, ++i){
00922 recoEBinEdges[i] = *it;
00923 }
00924
00925 fhNDRawMCTrueECCNuMu = new TH1D("fhNDRawMCTrueECCNuMu",
00926 "",
00927 size-1,
00928 recoEBinEdges);
00929
00930 if (!fhNDRawMCTrueECCNuMu) return false;
00931 return true;
00932 }
00933
00934
00935 const Bool_t NuCrossSectionFitter::CreateNDRawMCTrueECCNuMuBarHisto()
00936 {
00937 if (fhNDRawMCTrueECCNuMuBar) {
00938 delete fhNDRawMCTrueECCNuMuBar; fhNDRawMCTrueECCNuMuBar = 0;
00939 }
00940
00941 Int_t size = fvNDTrueENuMuBarCCBins.size();
00942 if (!size){
00943 MSG("NuCrossSectionFitter",Msg::kWarning)
00944 << "ND true energy binning not supplied."
00945 << endl;
00946 return false;
00947 }
00948
00949 Double_t* recoEBinEdges = new Double_t[size];
00950
00951 Int_t i=0;
00952 for (vector<Double_t>::const_iterator it =
00953 fvNDTrueENuMuBarCCBins.begin();
00954 it != fvNDTrueENuMuBarCCBins.end();
00955 ++it, ++i){
00956 recoEBinEdges[i] = *it;
00957 }
00958
00959 fhNDRawMCTrueECCNuMuBar = new TH1D("fhNDRawMCTrueECCNuMuBar",
00960 "",
00961 size-1,
00962 recoEBinEdges);
00963
00964 if (!fhNDRawMCTrueECCNuMuBar) return false;
00965 return true;
00966 }
00967
00968
00969 const Bool_t NuCrossSectionFitter::CreateNDNuMuBarCCMCHisto()
00970 {
00971 if (fhNDMCRecoENuMuBarCC){
00972 delete fhNDMCRecoENuMuBarCC; fhNDMCRecoENuMuBarCC = 0;
00973 }
00974
00975 if (fhNDNuMuCCDataFromFile && fhNDNuMuBarCCDataFromFile){
00976 fhNDMCRecoENuMuBarCC = new TH1D(*fhNDNuMuBarCCDataFromFile);
00977 fhNDMCRecoENuMuBarCC->Reset();
00978 return true;
00979 }
00980
00981 Int_t size = fvNDRecoENuMuBarCCBins.size();
00982 if (!size){
00983 MSG("NuCrossSectionFitter",Msg::kWarning)
00984 << "ND reconstructed energy binning not supplied."
00985 << endl;
00986 return false;
00987 }
00988
00989 Double_t* recoEBinEdges = new Double_t[size];
00990
00991 Int_t i=0;
00992 for (vector<Double_t>::const_iterator it =
00993 fvNDRecoENuMuBarCCBins.begin();
00994 it != fvNDRecoENuMuBarCCBins.end();
00995 ++it, ++i){
00996 recoEBinEdges[i] = *it;
00997 }
00998
00999 fhNDMCRecoENuMuBarCC = new TH1D("fhNDMCRecoENuMuBarCC",
01000 "",
01001 size-1,
01002 recoEBinEdges);
01003
01004 if (!fhNDMCRecoENuMuBarCC){return false;}
01005 return true;
01006 }
01007
01008
01009 const Bool_t NuCrossSectionFitter::CreateNDNuMuCCDataHisto()
01010 {
01011 if (fhNDDataRecoENuMuCC) {
01012 delete fhNDDataRecoENuMuCC; fhNDDataRecoENuMuCC = 0;
01013 }
01014
01015 Int_t size = fvNDRecoENuMuCCBins.size();
01016 if (!size){
01017 MSG("NuCrossSectionFitter",Msg::kWarning)
01018 << "ND reconstructed energy binning not supplied."
01019 << endl;
01020 return false;
01021 }
01022
01023 Double_t* recoEBinEdges = new Double_t[size];
01024
01025 Int_t i=0;
01026 for (vector<Double_t>::const_iterator it =
01027 fvNDRecoENuMuCCBins.begin();
01028 it != fvNDRecoENuMuCCBins.end();
01029 ++it, ++i){
01030 recoEBinEdges[i] = *it;
01031 }
01032
01033 fhNDDataRecoENuMuCC = new TH1D("fhNDDataRecoENuMuCC",
01034 "",
01035 size-1,
01036 recoEBinEdges);
01037
01038 if (!fhNDDataRecoENuMuCC) return false;
01039 return true;
01040 }
01041
01042
01043 const Bool_t NuCrossSectionFitter::CreateNDNuMuBarCCDataHisto()
01044 {
01045 if (fhNDDataRecoENuMuBarCC){
01046 delete fhNDDataRecoENuMuBarCC; fhNDDataRecoENuMuBarCC = 0;
01047 }
01048
01049 Int_t size = fvNDRecoENuMuBarCCBins.size();
01050 if (!size){
01051 MSG("NuCrossSectionFitter",Msg::kWarning)
01052 << "ND reconstructed energy binning not supplied."
01053 << endl;
01054 return false;
01055 }
01056
01057 Double_t* recoEBinEdges = new Double_t[size];
01058
01059 Int_t i = 0;
01060 for (vector<Double_t>::const_iterator it =
01061 fvNDRecoENuMuBarCCBins.begin();
01062 it != fvNDRecoENuMuBarCCBins.end();
01063 ++it, ++i){
01064 recoEBinEdges[i] = *it;
01065 }
01066
01067 fhNDDataRecoENuMuBarCC = new TH1D("fhNDDataRecoENuMuBarCC",
01068 "",
01069 size-1,
01070 recoEBinEdges);
01071
01072 if (!fhNDDataRecoENuMuBarCC){return false;}
01073 return true;
01074 }
01075
01076
01077 void NuCrossSectionFitter::NDData(const string ndDataFileName)
01078 {
01079 if (ftNDDataTree){delete ftNDDataTree; ftNDDataTree = 0;}
01080 ftNDDataTree = new NuTreeWrapper(ndDataFileName);
01081
01082
01083 fndDataPoT = ftNDDataTree->GetPoT();
01084
01085 MSG("NuCrossSectionFitter",Msg::kInfo)
01086 << "ndDataPoT: " << fndDataPoT
01087 << endl;
01088 }
01089
01090
01091 void NuCrossSectionFitter::NDNuMuBarCCData(const TH1D& ndData)
01092 {
01093 if (fhNDNuMuBarCCDataFromFile){
01094 delete fhNDNuMuBarCCDataFromFile; fhNDNuMuBarCCDataFromFile = 0;
01095 }
01096 fhNDNuMuBarCCDataFromFile = new TH1D(ndData);
01097 fhNDNuMuBarCCDataFromFile->SetDirectory(0);
01098 }
01099
01100
01101 void NuCrossSectionFitter::NDNuMuCCData(const TH1D& ndData)
01102 {
01103 if (fhNDNuMuCCDataFromFile){
01104 delete fhNDNuMuCCDataFromFile; fhNDNuMuCCDataFromFile = 0;
01105 }
01106 fhNDNuMuCCDataFromFile = new TH1D(ndData);
01107 fhNDNuMuCCDataFromFile->SetDirectory(0);
01108 }
01109
01110
01111 void NuCrossSectionFitter::NDMC(const string ndMCFileName)
01112 {
01113 if (ftNDMCTree){delete ftNDMCTree; ftNDMCTree = 0;}
01114 ftNDMCTree = new NuTreeWrapper(ndMCFileName);
01115
01116
01117 fndMCPoT = ftNDMCTree->GetPoT();
01118
01119
01120 MSG("NuCrossSectionFitter",Msg::kInfo)
01121 << "ndMCPoT: " << fndMCPoT
01122 << endl;
01123 }
01124
01125
01126 const Bool_t NuCrossSectionFitter::CacheNDMCEvents()
01127 {
01128 if (!ftNDMCTree){
01129 MSG("NuCrossSectionFitter",Msg::kWarning)
01130 << "ND MC not supplied"
01131 << endl;
01132 return false;
01133 }
01134
01135 fvNDMCCCNuMuEvents.clear();
01136 fvNDMCCCNuMuBarEvents.clear();
01137
01138 MSG("NuCrossSectionFitter",Msg::kInfo)
01139 << "Looping over ND MC:"
01140 << endl;
01141 Int_t mcEntries = ftNDMCTree->GetEntries();
01142 for (Int_t counter = 0;
01143 counter < mcEntries;
01144 ++counter){
01145 if (!(counter%10000)){
01146 MSG("NuCrossSectionFitter",Msg::kInfo)
01147 << counter << " of " << mcEntries
01148 << endl;
01149 }
01150 NuEvent currentEvent = ftNDMCTree->GetInfoObject(counter);
01151 fnuSystematic->Shift(currentEvent);
01152 NuSelectionResult_t recoType = this->SelectedAs(currentEvent);
01153 Double_t eventWeight = currentEvent.rw;
01154 if (NuXSecFit::kCCNuMu==recoType){
01155 fvNDMCCCNuMuEvents.push_back(currentEvent);
01156 fhNDRawMCRecoECCNuMu->Fill(currentEvent.energy,eventWeight);
01157 fhNDRawMCTrueECCNuMu->Fill(currentEvent.neuEnMC,eventWeight);
01158 }
01159 if (NuXSecFit::kCCNuMuBar==recoType){
01160 fvNDMCCCNuMuBarEvents.push_back(currentEvent);
01161 fhNDRawMCRecoECCNuMuBar->Fill(currentEvent.energy,eventWeight);
01162 fhNDRawMCTrueECCNuMuBar->Fill(currentEvent.neuEnMC,eventWeight);
01163 }
01164 }
01165
01166 if (fndMCPoT){
01167 fhNDRawMCRecoECCNuMu->Scale(fndDataPoT/fndMCPoT);
01168 fhNDRawMCRecoECCNuMuBar->Scale(fndDataPoT/fndMCPoT);
01169 fhNDRawMCTrueECCNuMu->Scale(fndDataPoT/fndMCPoT);
01170 fhNDRawMCTrueECCNuMuBar->Scale(fndDataPoT/fndMCPoT);
01171 }
01172
01173 fOutputFile->cd();
01174 fhNDRawMCRecoECCNuMu->Write("NDRawMCRecoECCNuMu");
01175 fhNDRawMCTrueECCNuMu->Write("NDRawMCTrueECCNuMu");
01176 fhNDRawMCRecoECCNuMuBar->Write("NDRawMCRecoECCNuMuBar");
01177 fhNDRawMCTrueECCNuMuBar->Write("NDRawMCTrueECCNuMuBar");
01178
01179 return true;
01180 }
01181
01182
01183 const Bool_t NuCrossSectionFitter::FillNDDataHistograms()
01184 {
01185
01186 if (fhNDNuMuCCDataFromFile && fhNDNuMuBarCCDataFromFile){
01187 if (fhNDDataRecoENuMuCC){
01188 delete fhNDDataRecoENuMuCC; fhNDDataRecoENuMuCC = 0;
01189 }
01190 if (fhNDDataRecoENuMuBarCC){
01191 delete fhNDDataRecoENuMuBarCC; fhNDDataRecoENuMuBarCC = 0;;
01192 }
01193 fhNDDataRecoENuMuCC = new TH1D(*fhNDNuMuCCDataFromFile);
01194 fhNDDataRecoENuMuBarCC = new TH1D(*fhNDNuMuBarCCDataFromFile);
01195
01196 fOutputFile->cd();
01197 fhNDDataRecoENuMuCC->Write("InputNDNuMuCCData");
01198 fhNDDataRecoENuMuBarCC->Write("InputNDNuMuBarCCData");
01199 return true;
01200 }
01201
01202 if (!fhNDDataRecoENuMuCC){
01203 MSG("NuCrossSectionFitter",Msg::kWarning)
01204 << "ND numu data histogram not created"
01205 << endl;
01206 return false;
01207 }
01208 if (!fhNDDataRecoENuMuBarCC){
01209 MSG("NuCrossSectionFitter",Msg::kWarning)
01210 << "ND numubar data histogram not created"
01211 << endl;
01212 return false;
01213 }
01214 if (!ftNDDataTree){
01215 MSG("NuCrossSectionFitter",Msg::kWarning)
01216 << "ND data not supplied"
01217 << endl;
01218 return false;
01219 }
01220
01221 fhNDDataRecoENuMuCC->Reset();
01222 fhNDDataRecoENuMuBarCC->Reset();
01223
01224 MSG("NuCrossSectionFitter",Msg::kInfo)
01225 << "Looping over ND data:"
01226 << endl;
01227 Int_t dataEntries = ftNDDataTree->GetEntries();
01228 for (Int_t counter = 0;
01229 counter < dataEntries;
01230 ++counter){
01231 if (!(counter%10000)){
01232 MSG("NuCrossSectionFitter",Msg::kInfo)
01233 << counter << " of " << dataEntries
01234 << endl;
01235 }
01236 NuEvent currentEvent = ftNDDataTree->GetInfoObject(counter);
01237 NuSelectionResult_t recoType = this->SelectedAs(currentEvent);
01238 Double_t recoEnergy = currentEvent.energy;
01239
01240 Int_t truthpar = this->FakeTruthIndex(currentEvent);
01241 Double_t nuweight = 1.0;
01242 nuweight *= currentEvent.rw;
01243 if (truthpar>=0){
01244 nuweight *= fvfakepars[truthpar];
01245 }
01246
01247 if (recoType==NuXSecFit::kCCNuMu){
01248 fhNDDataRecoENuMuCC->Fill(recoEnergy,nuweight);
01249 }
01250 if (recoType==NuXSecFit::kCCNuMuBar){
01251 fhNDDataRecoENuMuBarCC->Fill(recoEnergy,nuweight);
01252 }
01253 }
01254
01255 fOutputFile->cd();
01256 fhNDDataRecoENuMuCC->Write("InputNDNuMuCCData");
01257 fhNDDataRecoENuMuBarCC->Write("InputNDNuMuBarCCData");
01258
01259 return true;
01260 }
01261
01262
01263 const NuSelectionResult_t
01264 NuCrossSectionFitter::SelectedAs(NuEvent& nuEvent) const
01265 {
01266 NuCuts nuCuts;
01267 nuEvent.anaVersion = this->SelectionScheme();
01268
01269
01270 if (nuCuts.IsLI(nuEvent)) return NuXSecFit::kUnknown;
01271
01272 if (!nuCuts.IsGoodDataQuality(nuEvent)) return NuXSecFit::kUnknown;
01273
01274 if (!nuCuts.IsGoodTimeToNearestSpill(nuEvent)) return NuXSecFit::kUnknown;
01275
01276 if (!nuCuts.IsGoodBeam(nuEvent)) return NuXSecFit::kUnknown;
01277
01278
01279
01280
01281 if (!nuCuts.IsGoodNumberOfTracks(nuEvent)) return NuXSecFit::kUnknown;
01282
01283 if (!nuCuts.IsInFidVolTrk(nuEvent)) return NuXSecFit::kUnknown;
01284
01285
01286 if (!nuCuts.IsGoodTrackFitPass(nuEvent)) return NuXSecFit::kUnknown;
01287
01288 if (!nuCuts.IsGoodDirCos(nuEvent)) return NuXSecFit::kUnknown;
01289
01290
01291 if (!nuCuts.IsGoodPID(nuEvent)) {
01292 return NuXSecFit::kUnknown;
01293 }
01294
01295 if (!nuCuts.IsGoodSigmaQP_QP(nuEvent)) {
01296 return NuXSecFit::kUnknown;
01297 }
01298
01299 if (!nuCuts.IsGoodFitProb(nuEvent)) {
01300 return NuXSecFit::kUnknown;
01301 }
01302 if (!nuCuts.IsGoodMajorityCurvature(nuEvent)){
01303 return NuXSecFit::kUnknown;
01304 }
01305
01306 if (-1==nuEvent.charge){return NuXSecFit::kCCNuMu;}
01307 if (1==nuEvent.charge){return NuXSecFit::kCCNuMuBar;}
01308 return NuXSecFit::kUnknown;
01309 }