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

NuFluxHelper.cxx

Go to the documentation of this file.
00001 
00002 // $Id: NuFluxHelper.cxx,v 1.39 2010/02/08 22:52:39 ahimmel Exp $
00003 //
00004 // Makes fluka-related helper files for Matrix Method extrapolation.
00005 //
00006 // Justin Evans
00007 // j.evans2@physics.ox.ac.uk
00008 // Adapted from code by Chris Smith
00009 //
00010 //
00011 // $Log: NuFluxHelper.cxx,v $
00012 // Revision 1.39  2010/02/08 22:52:39  ahimmel
00013 //
00014 // Use the new kDogwood1_Daikon07_v2 weights.
00015 //
00016 // Revision 1.38  2010/01/15 00:11:35  ahimmel
00017 //
00018 //
00019 // Set reproducible random seeds based on run number of the first file.  If that number cannot be determined, default to using the root-based unique seed.
00020 //
00021 // Revision 1.37  2010/01/13 21:27:10  ahimmel
00022 //
00023 // Now set up for parallelized production of flux files.
00024 //
00025 // Revision 1.36  2009/12/19 19:14:57  ahimmel
00026 //
00027 // Fixed how filenames are determined for choosing whether you have a Flugg or Gnumi tree. Now globs rather than using the wildcarded path.
00028 //
00029 // Revision 1.35  2009/11/18 00:43:58  evansj
00030 // Creating a beam matrix which converts from an ND numu+numubar flux X
00031 // cross section to a FD nutau+nutaubar flux X cross section.
00032 //
00033 // Revision 1.34  2009/10/26 22:50:02  ahimmel
00034 //
00035 // Upgrades for using new Dogwood1_Daikon07 SKZP weights added.  Now automatically uses kDetXs for Daikon04 and earlier and kDogwood1_Daikon07 for Daikon07+
00036 //
00037 // Added a new unified way to print out the release type that prints: Name (hex #, decimal #).
00038 //
00039 // Revision 1.33  2009/10/02 22:04:33  ahimmel
00040 //
00041 //
00042 // Added a way to define the particles to extrapolate that doesn't use std::vector so it can play nice with CINT.
00043 //
00044 // Revision 1.32  2009/09/29 19:40:27  ahimmel
00045 //
00046 //
00047 // Was picking up the beam weights but not using them.
00048 //
00049 // Revision 1.31  2009/09/13 16:37:14  nickd
00050 // Added missing <cassert> include to fix compile
00051 //
00052 // Alex' last check in does not compile without it on Mac platform
00053 //
00054 // Revision 1.30  2009/09/12 22:58:37  ahimmel
00055 //
00056 //
00057 // The beam matrix making code is now up-to-date to handle the new Flugg fluxes.  It does intelligent things when run periods/beam types are specified or not, double checking where possible and complaining about errors.  It should make sure that only the right files are used to make the desired beam matrix.
00058 //
00059 // Revision 1.29  2009/08/25 15:10:05  evansj
00060 // Updating the beam matrix implementation of NUWEIGHT to recognise the
00061 // omega and k0short.
00062 //
00063 // Revision 1.28  2009/08/25 14:28:20  evansj
00064 // The new Flugg files store data members as Double_t, whereas the old
00065 // Gnumi files stored them as Float_t. This means all the
00066 // SetBranchAddress commends in NuFluxChain no longer work. So
00067 // NuFluxChain is now a virtual base class. NuFluggChain and NuGnumiChain
00068 // inherit from it (using doubles and floats respectively). The beam
00069 // matrix code looks at the flux file name to see which of these classes
00070 // it should instantiate.
00071 //
00072 // Revision 1.27  2008/03/21 14:56:59  evans
00073 // Adding some printout to reassure the user the reweighting is being
00074 // done for the correct run and beam type.
00075 //
00076 // Revision 1.26  2008/03/21 12:59:13  evans
00077 // NuFluxHelper is now configured from the xml file to perform SKZP and
00078 // scraping systematics shifts.
00079 //
00080 // Revision 1.25  2008/03/03 17:51:41  evans
00081 // Commenting out the line of code that makes the non MM-reweighted beam
00082 // matrices, as these are never needed. This speeds the code up.
00083 //
00084 // Revision 1.24  2008/02/22 11:12:01  evans
00085 // Updating the positions of the near and far detectors in the beam
00086 // matrix code to agree with Robert Hatcher's Daikon_04 numbers.
00087 //
00088 // Revision 1.23  2008/02/20 19:15:31  evans
00089 // Changing the ND position for the pHE beam. Adding some useful kInfo
00090 // printout.
00091 //
00092 // Revision 1.22  2008/02/19 16:10:21  evans
00093 // Changing the name of the new function in NuZBeamReweight from
00094 // GetZBeamReweight to GetBeamWeightsOnly.
00095 //
00096 // Revision 1.21  2008/02/19 15:21:40  evans
00097 // A new function in NuZBeamReweight to get beam-only SKZP weights for
00098 // the beam matrix.
00099 //
00100 // Revision 1.20  2008/02/19 12:15:50  evans
00101 // The beam matrix binning is now configured from the .xml file. Default
00102 // is 0.5 GeV bins up to 200 GeV.
00103 //
00104 // Revision 1.19  2008/02/19 11:50:55  evans
00105 // Updating the SKZP reweighting code so it now uses the NuZBeamReweight
00106 // interface.
00107 //
00108 // Revision 1.18  2008/02/08 21:49:21  evans
00109 // Updating the position of the near detector.
00110 //
00111 // Revision 1.17  2008/01/23 22:40:56  evans
00112 // A new constructor taking an xml filename (as a TString) that
00113 // configures whether or not to SKZP, and which run period to use.
00114 //
00115 // Revision 1.16  2008/01/22 21:04:25  hartnell
00116 //
00117 // Used to use:
00118 //
00119 // nuCuts.IsInFidVolNDCC0325Std(...)
00120 //
00121 // but now use:
00122 //
00123 // nuCuts.IsInFidVol(...)
00124 //
00125 // Revision 1.15  2008/01/21 01:16:13  evans
00126 // Changing to the new CC0325 ND fiducial volume.
00127 //
00128 // Revision 1.14  2008/01/15 01:47:10  evans
00129 // Bug fix: was subtracting 1 from SKZP errors.
00130 //
00131 // Revision 1.13  2008/01/14 07:00:37  evans
00132 // Beam matrices can now be made with a decay-pipe scraping systematic
00133 // shift. Also allowing the SKZP systematic to be used event if the beam
00134 // matrix isn't bein SKZP-reweighted (not entirely sure if that's what we
00135 // want or not).
00136 //
00137 // Revision 1.12  2008/01/14 06:39:22  evans
00138 // The beam matrix can now be made systematically shifted by the SKZP
00139 // flux errors.
00140 //
00141 // Revision 1.11  2008/01/08 20:33:13  evans
00142 // Setting the pointer 'fzarko' to 0 at the start of the constructor, so
00143 // that when the function DoSKZP(Bool_t) tries to construct it the test
00144 // 'if (!fzarko)' confirms the pointer is not yet pointing to
00145 // anything. This prevents a seg fault on a compiler in which pointers
00146 // aren't, by default, set to 0.
00147 //
00148 // Revision 1.10  2007/12/14 23:51:27  ahimmel
00149 //
00150 //
00151 // Made some modifications so that when run w/o skzp reweighting, the skzp object is not constructed (fixed some crashes when running with questionable db access that caused producing the skzp object to crash).
00152 //
00153 // Revision 1.9  2007/11/11 06:42:06  rhatcher
00154 // Part of the ongoing purge of "DetectorType" in favor of "Detector"
00155 // (the former is a synonym of the latter ...)
00156 //
00157 // Revision 1.8  2007/09/22 17:09:33  evans
00158 // *** empty log message ***
00159 //
00160 // Revision 1.7  2007/09/22 16:55:45  evans
00161 // Adding the ability to do SKZP reweighting for run I & run II combined.
00162 //
00163 // Revision 1.6  2007/08/07 16:42:19  evans
00164 // Beam matrices can now be made for any ND fiducial volume (needn't be
00165 // cylindrical).
00166 //
00167 // This involved altering the ND co-ordinate to be the real ND co-ordinate
00168 // system (no longer centered on the beam spot), and making the ND fiducial
00169 // volume and position of the beam spot centre more easily configurable. At
00170 // present the old beam spot center is still hard coded in, but can easily be
00171 // changed.
00172 //
00173 // Revision 1.5  2007/08/06 16:15:13  evans
00174 // Allowing more than one type of neutrino to be extrapolated at once. Only
00175 // CC numus and CC numubars are supported at the moment.
00176 //
00177 // The macro MakeMMFluxHelpers.C must now be compiled as the use of the
00178 // NuParticle enum doesn't work in interpreted mode.
00179 //
00180 // Revision 1.4  2007/08/03 10:16:11  evans
00181 // Fixing a bug in the setting of branch addresses in NuFluxChain.
00182 //
00183 // Fixing a bug in how one of the matrices was normalised in NuFluxHelper.
00184 //
00185 // Fixing the units where NuFluxChain (which uses Munits) interacts with the
00186 // matrix method code in NuFluxHelper (which doesn't use Munits).
00187 //
00188 // Now making only one TRandom3 object as a member variable of NuFluxHelper so
00189 // that the random neutrino interaction point in the near detector really is
00190 // random.
00191 //
00192 // Revision 1.3  2007/08/02 15:19:49  evans
00193 // In NuHistos: filling the data histograms (RecoEnergy_ND & _FD) for both
00194 // data and MC, so that mock data can be used.
00195 //
00196 // Improving the memory management in NuFluxHelper: primarily removing the
00197 // memory leak whereby ten new TRandom3 objects were created for each fluka
00198 // entry and never deleted.
00199 //
00200 // Revision 1.2  2007/08/01 04:43:23  rhatcher
00201 // need #include <cmath> for fabs() on gcc 4.0.1.
00202 //
00203 // Revision 1.1  2007/07/26 10:32:14  evans
00204 // Adding an implementation of code to make a beam matrix for extrapolation.
00205 //
00206 // NuFluxHelper makes the beam matrix. It's configurable to make the matrix
00207 // for either numus or numubars, and even to make a non-square beam matrix if
00208 // the mood takes you.
00209 //
00210 // NuFluxChain is a wrapper around a fluka file to give the interface required
00211 // by NuFluxHelper.
00212 //
00213 // macros/MakeMMFluxHelpers.C is an example macro of how to make the beam
00214 // matrix.
00215 //
00216 //
00217 //
00219 
00220 #include <cmath>
00221 #include <vector>
00222 #include <cassert>
00223 
00224 #include "TFile.h"
00225 #include "TGraph.h"
00226 #include "TH1D.h"
00227 #include "TH2D.h"
00228 #include "TH1F.h"
00229 #include "TMath.h"
00230 #include "TRandom3.h"
00231 #include "TString.h"
00232 
00233 #include "Conventions/Detector.h"
00234 #include "Conventions/Munits.h"
00235 #include "MessageService/MsgService.h"
00236 #include "NtupleUtils/NuCuts.h"
00237 #include "NtupleUtils/NuEvent.h"
00238 #include "NtupleUtils/NuFluggChain.h"
00239 #include "NtupleUtils/NuFluxChain.h"
00240 #include "NtupleUtils/NuFluxHelper.h"
00241 #include "NtupleUtils/NuGnumiChain.h"
00242 #include "NtupleUtils/NuXMLConfig.h"
00243 #include "NtupleUtils/NuZBeamReweight.h"
00244 #include "NtupleUtils/NuUtilities.h"
00245 #include "Conventions/SimFlag.h"
00246 
00247 using std::string;
00248 using std::vector;
00249 
00250 using NuParticle::NuParticleType_t;
00251 
00252 ClassImp(NuFluxHelper)
00253 
00254 CVSID("$Id: NuFluxHelper.cxx,v 1.39 2010/02/08 22:52:39 ahimmel Exp $");
00255 
00256 
00257 //____________________________________________________________________72
00258 NuFluxHelper::NuFluxHelper(SKZPWeightCalculator::ERunPeriod rp, Bool_t _doRW)
00259 {
00260   batchRunning = false;
00261   fzarko = 0;
00262   DoSKZP(_doRW);
00263   frunPeriod = rp;
00264   //fbeamType = BeamType::kL010z185i;
00265   fbeamType = BeamType::kUnknown; // Now pulled from file by default
00266   freweightVersion = SKZPWeightCalculator::kUnknown; // Set when determining file version
00267 
00268   fdoBeamShift = false;
00269   fdoScrapingShift = false;
00270   fbeamShiftAsSigma = 0.0;
00271   fscrapingScaleFactor = 0.0;
00272 
00273   fbinningScheme = NuBinningScheme::kUnknown;
00274   const NuUtilities utils;  
00275   const vector<Double_t> trueBins = utils.TrueBins(fbinningScheme);
00276   fNNDTrueEBins = trueBins.size()-1;
00277   fNDTrueEBinEdges=new Double_t[fNNDTrueEBins+1];
00278   {
00279     Int_t i=0;
00280     for (vector<Double_t>::const_iterator itBin = trueBins.begin();
00281          itBin != trueBins.end();
00282          ++itBin, ++i){
00283       fNDTrueEBinEdges[i] = *itBin;
00284     }
00285   }
00286   fNFDTrueEBins = fNNDTrueEBins;
00287   fFDTrueEBinEdges = fNDTrueEBinEdges;
00288 
00289   foutFile = "";
00290   fxSecFile = "";
00291 
00292   fxSecGraphNuMuCC = 0;
00293   fxSecGraphNuMuBarCC = 0;
00294   fxSecGraphNuTauCC = 0;
00295   fxSecGraphNuTauBarCC = 0;
00296 
00297   fFDVsNDMatrix = 0;        
00298   fFDVsNDMatrixRW = 0;                              
00299   fFDVsNDMatrixXSec = 0;    
00300   fFDVsNDMatrixXSecRW = 0;  
00301   fFDVsNDMatrixTauXSecRW = 0;
00302                         
00303   fTrueEnergyNuFlux_ND = 0;
00304   fTrueEnergyNuFluxRW_ND = 0;
00305   fTrueEnergyNuFlux_FD = 0;
00306   fTrueEnergyNuFluxRW_FD = 0;
00307   fTrueEnergyCCFlux_ND = 0;
00308   fTrueEnergyCCFluxRW_ND = 0;
00309   fTrueEnergyCCFlux_FD = 0;
00310   fTrueEnergyCCFluxRW_FD = 0;
00311 
00312   frandom3 = new TRandom3();
00313 }
00314 
00315 //____________________________________________________________________72
00316 NuFluxHelper::NuFluxHelper(const TString& xmlFile)
00317 {
00318   cout << "Beginning to construct NuFluxHelper(" << xmlFile << ")" << endl;
00319   fzarko = 0;
00320   batchRunning = false;
00321 
00322   NuXMLConfig xmlConfig(xmlFile);
00323   if (-1==xmlConfig.RunPeriod()){
00324     frunPeriod = SKZPWeightCalculator::kNone;
00325     this->DoSKZP(false);
00326     cout << "NOT doing SKZP." << endl;
00327   }
00328   else if (0==xmlConfig.RunPeriod()){
00329     frunPeriod = SKZPWeightCalculator::kNone;
00330     this->DoSKZP(true);
00331   }
00332   else if (1==xmlConfig.RunPeriod()){
00333     frunPeriod = SKZPWeightCalculator::kRunI;
00334     this->DoSKZP(true);
00335   }
00336   else if (2==xmlConfig.RunPeriod()){
00337     frunPeriod = SKZPWeightCalculator::kRunII;
00338     this->DoSKZP(true);
00339   }
00340   else {
00341     frunPeriod = SKZPWeightCalculator::kNone;
00342     this->DoSKZP(false);
00343   }
00344   cout << "Picked a run period (" << xmlConfig.RunPeriod() << ")" << endl;
00345   
00346   //fbeamType = BeamType::kL010z185i;
00347   fbeamType = BeamType::kUnknown; // Now pulled from file by default
00348   freweightVersion = SKZPWeightCalculator::kUnknown; // Set when determining file version
00349   
00350   if (xmlConfig.Name().Contains("Beam",TString::kIgnoreCase) ||
00351       xmlConfig.Name().Contains("SKZP",TString::kIgnoreCase) ||
00352       xmlConfig.Name().Contains("Flux",TString::kIgnoreCase)){
00353     this->SystematicBeamShift(true,xmlConfig.Shift());
00354   }
00355   else{
00356     this->SystematicBeamShift(false, 0.0);
00357   }
00358   if (xmlConfig.Name().Contains("Scraping",TString::kIgnoreCase) ||
00359       xmlConfig.Name().Contains("DecayPipe",TString::kIgnoreCase)){
00360     this->SystematicScrapingShift(true,xmlConfig.Shift());
00361   }
00362   else{
00363     this->SystematicScrapingShift(false, 0.0);
00364   }
00365   cout << "Read other things from the xml file" << endl;
00366   
00367   fbinningScheme = static_cast<NuBinningScheme::NuBinningScheme_t>(xmlConfig.BinningScheme());
00368   const NuUtilities utils;
00369   
00370   const vector<Double_t> trueBins = utils.TrueBins(fbinningScheme);
00371   fNNDTrueEBins = trueBins.size()-1;
00372   fNDTrueEBinEdges=new Double_t[fNNDTrueEBins+1];
00373   {
00374     Int_t i=0;
00375     for (vector<Double_t>::const_iterator itBin = trueBins.begin();
00376          itBin != trueBins.end();
00377          ++itBin, ++i){
00378       fNDTrueEBinEdges[i] = *itBin;
00379     }
00380   }
00381   fNFDTrueEBins = fNNDTrueEBins;
00382   fFDTrueEBinEdges = fNDTrueEBinEdges;
00383   
00384   cout << "Constructed bins" << endl;
00385   
00386   foutFile = "";
00387   fxSecFile = "";
00388 
00389   fxSecGraphNuMuCC = 0;
00390   fxSecGraphNuMuBarCC = 0;
00391   fxSecGraphNuTauCC = 0;
00392   fxSecGraphNuTauBarCC = 0;
00393 
00394   fFDVsNDMatrix = 0;        
00395   fFDVsNDMatrixRW = 0;                              
00396   fFDVsNDMatrixXSec = 0;    
00397   fFDVsNDMatrixXSecRW = 0;  
00398   fFDVsNDMatrixTauXSecRW = 0;
00399                         
00400   fTrueEnergyNuFlux_ND = 0;
00401   fTrueEnergyNuFluxRW_ND = 0;
00402   fTrueEnergyNuFlux_FD = 0;
00403   fTrueEnergyNuFluxRW_FD = 0;
00404   fTrueEnergyCCFlux_ND = 0;
00405   fTrueEnergyCCFluxRW_ND = 0;
00406   fTrueEnergyCCFlux_FD = 0;
00407   fTrueEnergyCCFluxRW_FD = 0;
00408 
00409   frandom3 = new TRandom3();
00410   
00411   cout << "Initialized objects" << endl;
00412 }
00413 
00414 //____________________________________________________________________72
00415 void NuFluxHelper::DoSKZP(const Bool_t doSKZP)
00416 {
00417   fdoSKZP=doSKZP;
00418   if (fdoSKZP && !fzarko) {
00419     fzarko = new NuZBeamReweight();
00420   }
00421 }
00422 
00423 //____________________________________________________________________72
00424 NuFluxHelper::~NuFluxHelper()
00425 {
00426   if (fFDVsNDMatrix)
00427     {delete fFDVsNDMatrix; fFDVsNDMatrix = 0;}
00428   if (fFDVsNDMatrixRW)
00429     {delete fFDVsNDMatrixRW; fFDVsNDMatrixRW = 0;}
00430   if (fFDVsNDMatrixXSec)
00431     {delete fFDVsNDMatrixXSec; fFDVsNDMatrixXSec = 0;}
00432   if (fFDVsNDMatrixXSecRW)
00433     {delete fFDVsNDMatrixXSecRW; fFDVsNDMatrixXSecRW = 0;}
00434   if (fFDVsNDMatrixTauXSecRW)
00435     {delete fFDVsNDMatrixTauXSecRW; fFDVsNDMatrixTauXSecRW = 0;}
00436   
00437   if (fTrueEnergyNuFlux_ND)
00438     {delete fTrueEnergyNuFlux_ND; fTrueEnergyNuFlux_ND = 0;}
00439   if (fTrueEnergyNuFluxRW_ND)
00440     {delete fTrueEnergyNuFluxRW_ND; fTrueEnergyNuFluxRW_ND = 0;}
00441   if (fTrueEnergyNuFlux_FD)
00442     {delete fTrueEnergyNuFlux_FD; fTrueEnergyNuFlux_FD = 0;}
00443   if (fTrueEnergyNuFluxRW_FD)
00444     {delete fTrueEnergyNuFluxRW_FD; fTrueEnergyNuFluxRW_FD = 0;}
00445   if (fTrueEnergyCCFlux_ND)
00446     {delete fTrueEnergyCCFlux_ND; fTrueEnergyCCFlux_ND = 0;}
00447   if (fTrueEnergyCCFluxRW_ND)
00448     {delete fTrueEnergyCCFluxRW_ND; fTrueEnergyCCFluxRW_ND = 0;}
00449   if (fTrueEnergyCCFlux_FD)
00450     {delete fTrueEnergyCCFlux_FD; fTrueEnergyCCFlux_FD = 0;}
00451   if (fTrueEnergyCCFluxRW_FD)
00452     {delete fTrueEnergyCCFluxRW_FD; fTrueEnergyCCFluxRW_FD = 0;}
00453 
00454   if (fFDTrueEBinEdges) {delete[] fFDTrueEBinEdges; fFDTrueEBinEdges=0;}
00455   if (fNDTrueEBinEdges) {delete[] fNDTrueEBinEdges; fNDTrueEBinEdges=0;}
00456 
00457   if (fzarko) {delete fzarko; fzarko = 0;}
00458 
00459   if (fxSecGraphNuMuCC) {delete fxSecGraphNuMuCC; fxSecGraphNuMuCC = 0;}
00460   if (fxSecGraphNuMuBarCC) {delete fxSecGraphNuMuBarCC; fxSecGraphNuMuBarCC = 0;}
00461   if (fxSecGraphNuTauCC) {delete fxSecGraphNuTauCC; fxSecGraphNuTauCC = 0;}
00462   if (fxSecGraphNuTauBarCC) {delete fxSecGraphNuTauBarCC; fxSecGraphNuTauBarCC = 0;}
00463 
00464   if (frandom3) {delete frandom3; frandom3 = 0;}
00465 }
00466 
00467 //____________________________________________________________________72
00468 void NuFluxHelper::FDTrueEBins(const vector<Double_t> fdtruebins)
00469 {
00470   Int_t size = fdtruebins.size();
00471   fNFDTrueEBins = size - 1;
00472   if (fFDTrueEBinEdges) {delete[] fFDTrueEBinEdges; fFDTrueEBinEdges=0;}
00473   fFDTrueEBinEdges = new Double_t[size];
00474   Int_t i = 0;
00475   for (vector<Double_t>::const_iterator it = fdtruebins.begin();
00476        it != fdtruebins.end();
00477        ++it, ++i){
00478     fFDTrueEBinEdges[i] = *it;
00479   }
00480 }
00481 
00482 //____________________________________________________________________72
00483 void NuFluxHelper::NDTrueEBins(const vector<Double_t> ndtruebins)
00484 {
00485   Int_t size = ndtruebins.size();
00486   fNNDTrueEBins = size - 1;
00487   if (fNDTrueEBinEdges) {delete[] fNDTrueEBinEdges; fNDTrueEBinEdges=0;}
00488   fNDTrueEBinEdges = new Double_t[size];
00489   Int_t i = 0;
00490   for (vector<Double_t>::const_iterator it = ndtruebins.begin();
00491        it != ndtruebins.end();
00492        ++it, ++i){
00493     fNDTrueEBinEdges[i] = *it;
00494   }
00495 }
00496 
00497 //____________________________________________________________________72
00498 const Bool_t NuFluxHelper::CreateHistos()
00499 {
00500   if (fFDVsNDMatrix)
00501     {delete fFDVsNDMatrix; fFDVsNDMatrix = 0;}
00502   if (fFDVsNDMatrixRW)
00503     {delete fFDVsNDMatrixRW; fFDVsNDMatrixRW = 0;}
00504   if (fFDVsNDMatrixXSec)
00505     {delete fFDVsNDMatrixXSec; fFDVsNDMatrixXSec = 0;}
00506   if (fFDVsNDMatrixXSecRW)
00507     {delete fFDVsNDMatrixXSecRW; fFDVsNDMatrixXSecRW = 0;}
00508   if (fFDVsNDMatrixTauXSecRW)
00509     {delete fFDVsNDMatrixTauXSecRW; fFDVsNDMatrixTauXSecRW = 0;}
00510   
00511   if (fTrueEnergyNuFlux_ND)
00512     {delete fTrueEnergyNuFlux_ND; fTrueEnergyNuFlux_ND = 0;}
00513   if (fTrueEnergyNuFluxRW_ND)
00514     {delete fTrueEnergyNuFluxRW_ND; fTrueEnergyNuFluxRW_ND = 0;}
00515   if (fTrueEnergyNuFlux_FD)
00516     {delete fTrueEnergyNuFlux_FD; fTrueEnergyNuFlux_FD = 0;}
00517   if (fTrueEnergyNuFluxRW_FD)
00518     {delete fTrueEnergyNuFluxRW_FD; fTrueEnergyNuFluxRW_FD = 0;}
00519   if (fTrueEnergyCCFlux_ND)
00520     {delete fTrueEnergyCCFlux_ND; fTrueEnergyCCFlux_ND = 0;}
00521   if (fTrueEnergyCCFluxRW_ND)
00522     {delete fTrueEnergyCCFluxRW_ND; fTrueEnergyCCFluxRW_ND = 0;}
00523   if (fTrueEnergyCCFlux_FD)
00524     {delete fTrueEnergyCCFlux_FD; fTrueEnergyCCFlux_FD = 0;}
00525   if (fTrueEnergyCCFluxRW_FD)
00526     {delete fTrueEnergyCCFluxRW_FD; fTrueEnergyCCFluxRW_FD = 0;}
00527   
00528   if (!fNNDTrueEBins){
00529     MSG("NuFluxHelper",Msg::kError)
00530       <<"Number of ND true energy bins not set " <<endl;
00531     return false;
00532   }
00533   if (!fNFDTrueEBins){
00534     MSG("NuFluxHelper",Msg::kError)
00535       <<"Number of FD true energy bins not set " <<endl;
00536     return false;
00537   }
00538   if (!fNDTrueEBinEdges){
00539     MSG("NuFluxHelper",Msg::kError)
00540       <<"ND true energy bin edges not set " <<endl;
00541     return false;
00542   }
00543   if (!fFDTrueEBinEdges){
00544     MSG("NuFluxHelper",Msg::kError)
00545       <<"FD true energy bin edges not set " <<endl;
00546     return false;
00547   }
00548   
00549   fFDVsNDMatrix = new 
00550     TH2D("FDVsNDMatrix",
00551          "Number of FD Vs ND Events with True Energy",
00552          fNNDTrueEBins,fNDTrueEBinEdges,
00553          fNFDTrueEBins,fFDTrueEBinEdges);
00554   fFDVsNDMatrix->Sumw2();
00555   fFDVsNDMatrixRW = new 
00556     TH2D("FDVsNDMatrixRW",
00557          "Number of FD Vs ND Events with True Energy (with Near Reweight)",
00558          fNNDTrueEBins,fNDTrueEBinEdges,
00559          fNFDTrueEBins,fFDTrueEBinEdges);
00560   fFDVsNDMatrixRW->Sumw2();
00561   fFDVsNDMatrixXSec = new 
00562     TH2D("FDVsNDMatrixXSec",
00563          "Number of FD Vs ND Events with True Energy (with XSec)",
00564          fNNDTrueEBins,fNDTrueEBinEdges,
00565          fNFDTrueEBins,fFDTrueEBinEdges);
00566   fFDVsNDMatrixXSec->Sumw2();
00567   fFDVsNDMatrixXSecRW = new 
00568     TH2D("FDVsNDMatrixXSecRW",
00569          "Number of FD Vs ND Events with True Energy (with XSec + Near Reweight)",
00570          fNNDTrueEBins,fNDTrueEBinEdges,
00571          fNFDTrueEBins,fFDTrueEBinEdges);
00572   fFDVsNDMatrixXSecRW->Sumw2();
00573   fFDVsNDMatrixTauXSecRW = new
00574     TH2D("FDVsNDMatrixTauXSecRW",
00575          "Number of FD Vs ND Events with True Energy (with FD Tau XSec + Near Reweight)",
00576          fNNDTrueEBins,fNDTrueEBinEdges,
00577          fNFDTrueEBins,fFDTrueEBinEdges);
00578   
00579   fTrueEnergyNuFlux_ND = new 
00580     TH1D("TrueEnergyNuFlux_ND",
00581          "Neutrino Flux with True Energy (NearDet)",
00582          fNNDTrueEBins,fNDTrueEBinEdges);
00583   fTrueEnergyNuFlux_ND->Sumw2();
00584   fTrueEnergyNuFluxRW_ND = new 
00585     TH1D("TrueEnergyNuFluxRW_ND",
00586          "Neutrino Flux with True Energy (NearDet with Reweighting)",
00587          fNNDTrueEBins,fNDTrueEBinEdges);
00588   fTrueEnergyNuFlux_FD = new 
00589     TH1D("TrueEnergyNuFlux_FD",
00590          "Neutrino Flux with True Energy (FarDet)",
00591          fNFDTrueEBins,fFDTrueEBinEdges);
00592   fTrueEnergyNuFlux_FD->Sumw2();
00593   fTrueEnergyNuFluxRW_FD = new 
00594     TH1D("TrueEnergyNuFluxRW_FD",
00595          "Neutrino Flux with True Energy (FarDet with Reweighting)",
00596          fNFDTrueEBins,fFDTrueEBinEdges);
00597   fTrueEnergyNuFluxRW_FD->Sumw2();
00598   fTrueEnergyCCFlux_ND = new 
00599     TH1D("TrueEnergyCCFlux_ND",
00600          "NuMu CC Flux with True Energy (NearDet)",
00601          fNNDTrueEBins,fNDTrueEBinEdges);
00602   fTrueEnergyCCFlux_ND->Sumw2();
00603   fTrueEnergyCCFluxRW_ND = new
00604     TH1D("TrueEnergyCCFluxRW_ND",
00605          "NuMu CC Flux with True Energy with (NearDet with Reweighting)",
00606          fNNDTrueEBins,fNDTrueEBinEdges);
00607   fTrueEnergyCCFluxRW_ND->Sumw2();  
00608   fTrueEnergyCCFlux_FD = new
00609     TH1D("TrueEnergyCCFlux_FD",
00610          "NuMu CC Flux with True Energy (FarDet)",
00611          fNFDTrueEBins,fFDTrueEBinEdges);
00612   fTrueEnergyCCFlux_FD->Sumw2();
00613   fTrueEnergyCCFluxRW_FD = new
00614     TH1D("TrueEnergyCCFluxRW_FD",
00615          "NuMu CC Flux with True Energy (FarDet with Reweighing)",
00616          fNFDTrueEBins,fFDTrueEBinEdges);
00617   fTrueEnergyCCFluxRW_FD->Sumw2();
00618   
00619   return true;
00620 }
00621 
00622 //____________________________________________________________________72
00623 void NuFluxHelper::CrossSectionFile(const char * xSecFile)
00624 {
00625   fxSecFile = xSecFile;
00626 
00627   if (fxSecGraphNuMuCC){
00628     delete fxSecGraphNuMuCC;
00629     fxSecGraphNuMuCC = 0;
00630   }
00631   if (fxSecGraphNuMuBarCC){
00632     delete fxSecGraphNuMuBarCC;
00633     fxSecGraphNuMuBarCC = 0;
00634   }
00635   if (fxSecGraphNuTauCC){
00636     delete fxSecGraphNuTauCC;
00637     fxSecGraphNuTauCC = 0;
00638   }
00639   if (fxSecGraphNuTauBarCC){
00640     delete fxSecGraphNuTauBarCC;
00641     fxSecGraphNuTauBarCC = 0;
00642   }
00643   
00644   //Get the cross-section information from the histogram in the file.
00645   //Put it into an array.
00646   TFile *mikeFile=new TFile(fxSecFile.c_str(),"READ");
00647 
00648   //Put the numu CC cross sections into an array
00649   TH1F* XSec_NuMuCC = (TH1F*) mikeFile->Get("h_numu_cc_tot");
00650   XSec_NuMuCC->SetDirectory(0);
00651   Float_t* x = new Float_t[XSec_NuMuCC->GetNbinsX()];
00652   Float_t* y = new Float_t[XSec_NuMuCC->GetNbinsX()];
00653   for(int i=0;i<XSec_NuMuCC->GetNbinsX();i++) {
00654     x[i] = XSec_NuMuCC->GetBinCenter(i+1);
00655     y[i] = XSec_NuMuCC->GetBinContent(i+1);
00656   }
00657   //Turn the array into a graph.
00658   fxSecGraphNuMuCC = new TGraph(XSec_NuMuCC->GetNbinsX(),x,y);
00659 
00660   //Clean up ready for the next set of cross sections
00661   if (x) {delete x; x=0;}
00662   if (y) {delete y; y=0;}
00663 
00664   //Put the numubar CC cross sections into an array
00665   TH1F* XSec_NuMuBarCC = (TH1F*) mikeFile->Get("h_numubar_cc_tot");
00666   XSec_NuMuBarCC->SetDirectory(0);
00667   x = new Float_t[XSec_NuMuBarCC->GetNbinsX()];
00668   y = new Float_t[XSec_NuMuBarCC->GetNbinsX()];
00669   for(int i=0;i<XSec_NuMuBarCC->GetNbinsX();i++) {
00670     x[i] = XSec_NuMuBarCC->GetBinCenter(i+1);
00671     y[i] = XSec_NuMuBarCC->GetBinContent(i+1);
00672   }
00673   //Turn the array into a graph.
00674   fxSecGraphNuMuBarCC = new TGraph(XSec_NuMuBarCC->GetNbinsX(),x,y);
00675 
00676   //Clean up ready for the next set of cross sections:
00677   if (x) {delete x; x=0;}
00678   if (y) {delete y; y=0;}
00679 
00680   //Put the nutau CC cross sections into an array
00681   TH1F* XSec_NuTauCC = (TH1F*) mikeFile->Get("h_nutau_cc_tot");
00682   XSec_NuTauCC->SetDirectory(0);
00683   x = new Float_t[XSec_NuTauCC->GetNbinsX()];
00684   y = new Float_t[XSec_NuTauCC->GetNbinsX()];
00685   for(int i=0;i<XSec_NuTauCC->GetNbinsX();i++) {
00686     x[i] = XSec_NuTauCC->GetBinCenter(i+1);
00687     y[i] = XSec_NuTauCC->GetBinContent(i+1);
00688   }
00689   //Turn the array into a graph.
00690   fxSecGraphNuTauCC = new TGraph(XSec_NuTauCC->GetNbinsX(),x,y);
00691 
00692   //Clean up ready for the next set of cross sections
00693   if (x) {delete x; x=0;}
00694   if (y) {delete y; y=0;}
00695 
00696   //Put the nutaubar CC cross sections into an array
00697   TH1F* XSec_NuTauBarCC = (TH1F*) mikeFile->Get("h_nutaubar_cc_tot");
00698   XSec_NuTauBarCC->SetDirectory(0);
00699   x = new Float_t[XSec_NuTauBarCC->GetNbinsX()];
00700   y = new Float_t[XSec_NuTauBarCC->GetNbinsX()];
00701   for(int i=0;i<XSec_NuTauBarCC->GetNbinsX();i++) {
00702     x[i] = XSec_NuTauBarCC->GetBinCenter(i+1);
00703     y[i] = XSec_NuTauBarCC->GetBinContent(i+1);
00704   }
00705   //Turn the array into a graph.
00706   fxSecGraphNuTauBarCC = new TGraph(XSec_NuTauBarCC->GetNbinsX(),x,y);
00707 
00708   //Clean up memory:
00709   if (x) {delete x; x=0;}
00710   if (y) {delete y; y=0;}
00711 
00712   mikeFile->Close();
00713   if (mikeFile) {delete mikeFile; mikeFile = 0;}
00714 }
00715 
00716 //____________________________________________________________________72
00717 void NuFluxHelper::
00718 ParticlesToExtrapolate(int flavour)
00719 {
00720   //Configure the particles to extrapolate
00721   vector<NuParticle::NuParticleType_t> particles;
00722   if (0==flavour){
00723     particles.push_back(NuParticle::kNuMu);
00724     particles.push_back(NuParticle::kNuMuBar);
00725   }
00726   if (1==flavour){
00727     particles.push_back(NuParticle::kNuMu);
00728   }
00729   if (2==flavour){
00730     particles.push_back(NuParticle::kNuMuBar);
00731   }
00732 
00733   this->ParticlesToExtrapolate(particles);
00734 }
00735 
00736 
00737 //____________________________________________________________________72
00738 void NuFluxHelper::
00739 ParticleToExtrapolate(const NuParticleType_t particle)
00740 {
00741   fparticlesToExtrapolate.clear();
00742   fparticlesToExtrapolate.push_back(particle);
00743 }
00744 
00745 //____________________________________________________________________72
00746 void NuFluxHelper::
00747 ParticlesToExtrapolate(const vector<NuParticleType_t> particleList)
00748 {
00749   fparticlesToExtrapolate.clear();
00750   fparticlesToExtrapolate = particleList;
00751 }
00752 
00753 //____________________________________________________________________72
00754 const Bool_t NuFluxHelper::
00755 IsParticleToExtrapolate(const NuParticleType_t particle) const
00756 {
00757   for (vector<NuParticleType_t>::const_iterator it
00758          = fparticlesToExtrapolate.begin();
00759        it != fparticlesToExtrapolate.end();
00760        ++it){
00761     if (particle == *it){return true;}
00762   }
00763   return false;
00764 }
00765 
00766 //____________________________________________________________________72
00767 void NuFluxHelper::MakeHelperHistos(const char * fileList)
00768 {
00769   const NuFluxChain* fluxChain = 0;
00770   vector<TString> vFiles = NuUtilities::GetListOfFilesInDir(fileList);
00771   TString tmp = vFiles[0];
00772   if (tmp.Contains("flugg")){
00773     MSG("NuFluxHelper",Msg::kInfo)  << "USING FLUGG CHAIN" << endl;
00774     fluxChain = new NuFluggChain(fileList);
00775     // Reset the reweight version only for Flugg
00776     freweightVersion = SKZPWeightCalculator::kDogwood1_Daikon07_v2;
00777   }
00778   else{
00779     MSG("NuFluxHelper",Msg::kInfo) << "USING GNUMI CHAIN" << endl;
00780     fluxChain = new NuGnumiChain(fileList);
00781     freweightVersion = SKZPWeightCalculator::kDetXs;
00782   }
00783 
00784   TString num = tmp(tmp.Last('_')+1, 3);
00785   if (!num.IsDigit()) {
00786     MSG("NuFluxHelper",Msg::kInfo) << "Cannot determine run number for file: " << tmp
00787     << " (got " << num << ") so random seed will not be reproducible." << endl;
00788     frandom3->SetSeed(0);
00789   }
00790   else {
00791     MSG("NuFluxHelper",Msg::kInfo) << "Setting random seed to " << num << "." << endl;
00792     frandom3->SetSeed(num.Atoi());
00793   }
00794     
00795   
00796   
00797   // Double check the beam type
00798   // If our beam type is not yet known, fill it with type from fluxChain
00799   // If fluxChain type is not known, trust our beam type
00800   // If we have both types, check that they match
00801   if (fluxChain->GetBeamType() != BeamType::kUnknown) {
00802     if (BeamType() == BeamType::kUnknown) BeamType(fluxChain->GetBeamType());
00803     if (BeamType() != fluxChain->GetBeamType()) {
00804       MSG("NuFluxHelper",Msg::kError) << "Beam types do not match.  "
00805       << "Type from fluxFiles: " << BeamType::AsString(fluxChain->GetBeamType())
00806       << ", Type from FluxHelper: " << BeamType::AsString(BeamType()) << endl;
00807       return;
00808     }
00809   }
00810   
00811   
00812 
00813   // Double check the Run Period
00814   // If our run period is not yet known, fill it with type from fluxChain
00815   // If fluxChain run period is not known, trust our run period
00816   // If we have both types, check that they match
00817   if (fluxChain->GetRunPeriod() != SKZPWeightCalculator::kNone) {
00818     if (RunPeriod() == SKZPWeightCalculator::kNone) RunPeriod(fluxChain->GetRunPeriod());
00819     if (RunPeriod() != fluxChain->GetRunPeriod()) {
00820       MSG("NuFluxHelper",Msg::kError) << "Run Periods do not match.  "
00821       << "Period from fluxFiles: " << static_cast<int>(fluxChain->GetRunPeriod())
00822       << ", Period from FluxHelper: " << static_cast<int>(RunPeriod()) << endl;
00823       return;
00824     }
00825   }
00826   
00827   MSG("NuFluxHelper",Msg::kInfo) << "Make flux helpers with " << BeamType::AsString(BeamType())
00828                                  << " and run period " << static_cast<int>(RunPeriod()) << endl;
00829   
00830   //Make the histograms if possible:
00831   Bool_t histosReady = this->CreateHistos();
00832   if (!histosReady){return;}
00833 
00834   if (!fxSecGraphNuMuCC){
00835     MSG("NuFluxHelper",Msg::kError)
00836       <<"No numu CC cross-section graph supplied." <<endl;
00837     return;
00838   }
00839   if (!fxSecGraphNuMuBarCC){
00840     MSG("NuFluxHelper",Msg::kError)
00841       <<"No numubar CC cross-section graph supplied." <<endl;
00842     return;
00843   }
00844   if (!fxSecGraphNuTauCC){
00845     MSG("NuFluxHelper",Msg::kError)
00846       <<"No nutau CC cross-section graph supplied." <<endl;
00847     return;
00848   }
00849   if (!fxSecGraphNuTauBarCC){
00850     MSG("NuFluxHelper",Msg::kError)
00851       <<"No nutaubar CC cross-section graph supplied." <<endl;
00852     return;
00853   }
00854 
00855   //Loop over the entries in the fluka files.
00856   Int_t numFlukaEntries = fluxChain->GetEntries();
00857   for(int flukaEntry=0;flukaEntry<numFlukaEntries;++flukaEntry){
00858     if(flukaEntry%10000==0){
00859       MSG("NuFluxHelper",Msg::kInfo)
00860         <<"Processing fluka entry " << flukaEntry
00861         << " of " << numFlukaEntries <<endl;
00862     }
00863 
00864     //Is this the correct particle?
00865     if (!this->IsParticleToExtrapolate(fluxChain->NuType(flukaEntry))){
00866       continue;
00867     }
00868     /*
00869     this->FillNonMMHelpers(fluxChain,
00870                            flukaEntry);
00871     */
00872     this->FillMMHelpers(fluxChain,
00873                         flukaEntry);
00874 
00875   } //End loop over flukaChain
00876 
00877   if (!batchRunning) {
00878     this->NormaliseHistos();
00879   }
00880   this->WriteHistos();
00881 
00882   if (fluxChain){delete fluxChain; fluxChain=0;}
00883 
00884   return;
00885 }
00886 
00887 
00888 //____________________________________________________________________72
00889 void NuFluxHelper::ConcatenateHelpers(const char * fileList)
00890 {
00891   vector<TString> vFiles = NuUtilities::GetListOfFilesInDir(fileList);
00892   if (vFiles.size() <= 0) {
00893     MSG("NuFluxHelper",Msg::kInfo) << "Cannot find any files in " << fileList << endl;
00894   }
00895   
00896   MSG("NuFluxHelper",Msg::kInfo) << "Concatenating " << vFiles.size()
00897   << " flux helper files." << endl;
00898   
00899   TFile *f;
00900   
00901   MSG("NuFluxHelper",Msg::kInfo) << "Reading from " << vFiles[0] << endl;
00902   f = new TFile(vFiles[0]);
00903   if (!f->IsOpen()) {
00904     MSG("NuFluxHelper",Msg::kError) << "File not opened.  Bailing" << endl;
00905     assert(false);
00906   }
00907   f->ls();
00908   
00909   fFDVsNDMatrix = (TH2D*)f->Get("FDVsNDMatrix"); 
00910   fFDVsNDMatrixRW = (TH2D*)f->Get("FDVsNDMatrixRW"); 
00911   fFDVsNDMatrixXSec = (TH2D*)f->Get("FDVsNDMatrixXSec"); 
00912   fFDVsNDMatrixXSecRW = (TH2D*)f->Get("FDVsNDMatrixXSecRW"); 
00913   fFDVsNDMatrixTauXSecRW = (TH2D*)f->Get("FDVsNDMatrixTauXSecRW"); 
00914   
00915   fTrueEnergyNuFlux_ND = (TH1D*)f->Get("TrueEnergyNuFlux_ND"); 
00916   fTrueEnergyNuFluxRW_ND = (TH1D*)f->Get("TrueEnergyNuFluxRW_ND"); 
00917   fTrueEnergyNuFlux_FD = (TH1D*)f->Get("TrueEnergyNuFlux_FD"); 
00918   fTrueEnergyNuFluxRW_FD = (TH1D*)f->Get("TrueEnergyNuFluxRW_FD"); 
00919   fTrueEnergyCCFlux_ND = (TH1D*)f->Get("TrueEnergyCCFlux_ND"); 
00920   fTrueEnergyCCFluxRW_ND = (TH1D*)f->Get("TrueEnergyCCFluxRW_ND"); 
00921   fTrueEnergyCCFlux_FD = (TH1D*)f->Get("TrueEnergyCCFlux_FD"); 
00922   fTrueEnergyCCFluxRW_FD = (TH1D*)f->Get("TrueEnergyCCFluxRW_FD"); 
00923 
00924   fFDVsNDMatrix->SetDirectory(0);
00925   fFDVsNDMatrixRW->SetDirectory(0);
00926   fFDVsNDMatrixXSec->SetDirectory(0);
00927   fFDVsNDMatrixXSecRW->SetDirectory(0);
00928   fFDVsNDMatrixTauXSecRW->SetDirectory(0);
00929   
00930   fTrueEnergyNuFlux_ND->SetDirectory(0);
00931   fTrueEnergyNuFluxRW_ND->SetDirectory(0);
00932   fTrueEnergyNuFlux_FD->SetDirectory(0);
00933   fTrueEnergyNuFluxRW_FD->SetDirectory(0);
00934   fTrueEnergyCCFlux_ND->SetDirectory(0);
00935   fTrueEnergyCCFluxRW_ND->SetDirectory(0);
00936   fTrueEnergyCCFlux_FD->SetDirectory(0);
00937   fTrueEnergyCCFluxRW_FD->SetDirectory(0);
00938   f->Close();
00939   
00940   
00941   for (unsigned int i = 1; i < vFiles.size(); i++) {
00942     MSG("NuFluxHelper",Msg::kInfo) << "Reading from " << vFiles[i] << endl;
00943     f = new TFile(vFiles[i]);
00944     if (!f->IsOpen()) {
00945       MSG("NuFluxHelper",Msg::kError) << "File not opened.  Bailing" << endl;
00946       assert(false);
00947     }
00948     
00949     TH2D* tmp_fFDVsNDMatrix = (TH2D*)f->Get("FDVsNDMatrix");
00950     TH2D* tmp_fFDVsNDMatrixRW = (TH2D*)f->Get("FDVsNDMatrixRW");
00951     TH2D* tmp_fFDVsNDMatrixXSec = (TH2D*)f->Get("FDVsNDMatrixXSec");
00952     TH2D* tmp_fFDVsNDMatrixXSecRW = (TH2D*)f->Get("FDVsNDMatrixXSecRW");
00953     TH2D* tmp_fFDVsNDMatrixTauXSecRW = (TH2D*)f->Get("FDVsNDMatrixTauXSecRW");
00954     
00955     TH1D* tmp_fTrueEnergyNuFlux_ND = (TH1D*)f->Get("TrueEnergyNuFlux_ND");
00956     TH1D* tmp_fTrueEnergyNuFluxRW_ND = (TH1D*)f->Get("TrueEnergyNuFluxRW_ND");
00957     TH1D* tmp_fTrueEnergyNuFlux_FD = (TH1D*)f->Get("TrueEnergyNuFlux_FD");
00958     TH1D* tmp_fTrueEnergyNuFluxRW_FD = (TH1D*)f->Get("TrueEnergyNuFluxRW_FD");
00959     TH1D* tmp_fTrueEnergyCCFlux_ND = (TH1D*)f->Get("TrueEnergyCCFlux_ND");
00960     TH1D* tmp_fTrueEnergyCCFluxRW_ND = (TH1D*)f->Get("TrueEnergyCCFluxRW_ND");
00961     TH1D* tmp_fTrueEnergyCCFlux_FD = (TH1D*)f->Get("TrueEnergyCCFlux_FD");
00962     TH1D* tmp_fTrueEnergyCCFluxRW_FD = (TH1D*)f->Get("TrueEnergyCCFluxRW_FD");
00963 
00964     fFDVsNDMatrix->Add(tmp_fFDVsNDMatrix);
00965     fFDVsNDMatrixRW->Add(tmp_fFDVsNDMatrixRW);
00966     fFDVsNDMatrixXSec->Add(tmp_fFDVsNDMatrixXSec);
00967     fFDVsNDMatrixXSecRW->Add(tmp_fFDVsNDMatrixXSecRW);
00968     fFDVsNDMatrixTauXSecRW->Add(tmp_fFDVsNDMatrixTauXSecRW);
00969     
00970     fTrueEnergyNuFlux_ND->Add(tmp_fTrueEnergyNuFlux_ND);
00971     fTrueEnergyNuFluxRW_ND->Add(tmp_fTrueEnergyNuFluxRW_ND);
00972     fTrueEnergyNuFlux_FD->Add(tmp_fTrueEnergyNuFlux_FD);
00973     fTrueEnergyNuFluxRW_FD->Add(tmp_fTrueEnergyNuFluxRW_FD);
00974     fTrueEnergyCCFlux_ND->Add(tmp_fTrueEnergyCCFlux_ND);
00975     fTrueEnergyCCFluxRW_ND->Add(tmp_fTrueEnergyCCFluxRW_ND);
00976     fTrueEnergyCCFlux_FD->Add(tmp_fTrueEnergyCCFlux_FD);
00977     fTrueEnergyCCFluxRW_FD->Add(tmp_fTrueEnergyCCFluxRW_FD);
00978 
00979     f->Close();
00980   }
00981   
00982   this->NormaliseHistos();
00983   this->WriteHistos();
00984   
00985   return;
00986 }
00987 
00988 //____________________________________________________________________72
00989 void NuFluxHelper::WriteHistos() const
00990 {
00991   MSG("NuFluxHelper",Msg::kInfo)
00992     <<"Writing helper histograms to " << foutFile << endl;
00993   
00994   TFile *savefile = new TFile(foutFile.c_str(),"RECREATE");
00995   savefile->cd();
00996   fFDVsNDMatrix->Write();
00997   fFDVsNDMatrixRW->Write();
00998   fFDVsNDMatrixXSec->Write();
00999   fFDVsNDMatrixXSecRW->Write();
01000   fFDVsNDMatrixTauXSecRW->Write();
01001                         
01002   fTrueEnergyNuFlux_ND->Write();
01003   fTrueEnergyNuFluxRW_ND->Write();
01004   fTrueEnergyNuFlux_FD->Write();
01005   fTrueEnergyNuFluxRW_FD->Write();
01006   fTrueEnergyCCFlux_ND->Write();
01007   fTrueEnergyCCFluxRW_ND->Write();
01008   fTrueEnergyCCFlux_FD->Write();
01009   fTrueEnergyCCFluxRW_FD->Write();
01010   savefile->Close();
01011   if (savefile) {delete savefile; savefile = 0;}
01012 }
01013 
01014 //____________________________________________________________________72
01015 void NuFluxHelper::FillNonMMHelpers(const NuFluxChain* fluxChain,
01016                                     const Int_t flukaEntry) const
01017 {
01018   //Get the fluka variables I'm going to need
01019   NuParticleType_t Ntype = fluxChain->NuType(flukaEntry);
01020   Int_t tptype = fluxChain->ParentParticleType(flukaEntry);
01021   Double_t tpx = fluxChain->TargetParentPX(flukaEntry);
01022   Double_t tpy = fluxChain->TargetParentPY(flukaEntry);
01023   Double_t tpz = fluxChain->TargetParentPZ(flukaEntry);
01024   Double_t Nenergyn = fluxChain->NeutrinoNDEnergy(flukaEntry);
01025   Double_t Nenergyf = fluxChain->NeutrinoFDEnergy(flukaEntry);
01026   Double_t Nimpwt = fluxChain->NuImportanceWeight(flukaEntry);
01027   Double_t Nwtnear = fluxChain->NuNDWeight(flukaEntry);
01028   Double_t Nwtfar = fluxChain->NuFDWeight(flukaEntry);
01029   
01030   //Higher-level fluka variables
01031   Double_t pt = 0;
01032   Double_t pt2 = tpx*tpx + tpy*tpy;
01033   if (0 < pt2){pt = sqrt(pt2);}
01034 
01035   //Make NuEvents to get the beam weights into.  
01036   NuEvent nearEvent;
01037   nearEvent.reweightVersion = this->ReweightVersion();
01038   nearEvent.simFlag = SimFlag::kMC;
01039   nearEvent.beamType = this->BeamType();
01040   nearEvent.runPeriod = this->RunPeriod();
01041   nearEvent.neuEnMC = Nenergyn;
01042   nearEvent.inu=fluxChain->NuParticleAsPDGCode(Ntype);
01043   nearEvent.tptype = tptype;
01044   nearEvent.tpz = tpz;
01045   nearEvent.tpy = tpy;
01046   nearEvent.tpx = tpx;
01047   nearEvent.detector = Detector::kNear;
01048   nearEvent.beamWeightRunI = 1.0;
01049   nearEvent.beamWeightRunII = 1.0;
01050   nearEvent.beamWeight = 1.0;
01051   nearEvent.fluxErr = 1.0;
01052   nearEvent.fluxErrTotalErrorAfterTuneRunI = 1.0;
01053   nearEvent.fluxErrTotalErrorAfterTuneRunII = 1.0;
01054   nearEvent.fluxErrTotalErrorAfterTune = 1.0;
01055 
01056   NuEvent farEvent;
01057   farEvent.reweightVersion = this->ReweightVersion();
01058   farEvent.simFlag = SimFlag::kMC;
01059   farEvent.beamType = this->BeamType();
01060   farEvent.runPeriod = this->RunPeriod();
01061   farEvent.neuEnMC = Nenergyf;
01062   farEvent.inu=fluxChain->NuParticleAsPDGCode(Ntype);
01063   farEvent.tptype = tptype;
01064   farEvent.tpz = tpz;
01065   farEvent.tpy = tpy;
01066   farEvent.tpx = tpx;
01067   farEvent.detector = Detector::kFar;
01068   farEvent.beamWeightRunI = 1.0;
01069   farEvent.beamWeightRunII = 1.0;
01070   farEvent.beamWeight = 1.0;
01071   farEvent.fluxErr = 1.0;
01072   farEvent.fluxErrTotalErrorAfterTuneRunI = 1.0;
01073   farEvent.fluxErrTotalErrorAfterTuneRunII = 1.0;
01074   farEvent.fluxErrTotalErrorAfterTune = 1.0;
01075 
01076   //Get the SKZP weights
01077   Double_t flux_weight_near = 1.0;
01078   Double_t flux_weight_far = 1.0;
01079 
01080   if (fdoSKZP){
01081     //Reweight the NuEvents
01082     fzarko->GetBeamWeightsOnly(nearEvent);
01083     fzarko->GetBeamWeightsOnly(farEvent);
01084 //    Not needed now that run period is specified in the event
01085 //    if (SKZPWeightCalculator::kRunI == frunPeriod){
01086 //      {
01087 //      static Int_t messageCounter = 0;
01088 //      if (messageCounter < 5){
01089 //        MSG("NuFluxHelper",Msg::kInfo)
01090 //          << "Reweighting for run 1, beam type " 
01091 //          << BeamType::AsString(this->BeamType()) << endl;
01092 //        ++messageCounter;
01093 //      }
01094 //      }
01095 //      flux_weight_near = nearEvent.beamWeightRunI;
01096 //      flux_weight_far = farEvent.beamWeightRunI;
01097 //      nearEvent.fluxErr = nearEvent.fluxErrTotalErrorAfterTuneRunI;
01098 //      farEvent.fluxErr = farEvent.fluxErrTotalErrorAfterTuneRunI;
01099 //    }
01100 //    else if (SKZPWeightCalculator::kRunII == frunPeriod){
01101 //      {
01102 //      static Int_t messageCounter = 0;
01103 //      if (messageCounter < 5){
01104 //        MSG("NuFluxHelper",Msg::kInfo)
01105 //          << "Reweighting for run 2, beam type " 
01106 //          << BeamType::AsString(this->BeamType()) << endl;
01107 //        ++messageCounter;
01108 //      }
01109 //      }
01110 //      flux_weight_near = nearEvent.beamWeightRunII;
01111 //      flux_weight_far = farEvent.beamWeightRunII;
01112 //      nearEvent.fluxErr = nearEvent.fluxErrTotalErrorAfterTuneRunII;
01113 //      farEvent.fluxErr = farEvent.fluxErrTotalErrorAfterTuneRunII;
01114 //    }
01115 //    else{
01116 //      {
01117 //      static Int_t messageCounter = 0;
01118 //      if (messageCounter < 5){
01119 //        MSG("NuFluxHelper",Msg::kInfo)
01120 //          << "Reweighting for PoT averaged runs 1 & 2, beam type " 
01121 //          << BeamType::AsString(this->BeamType()) << endl;
01122 //        ++messageCounter;
01123 //      }
01124 //      }
01125 //      flux_weight_near = nearEvent.beamWeight;
01126 //      flux_weight_far = farEvent.beamWeight;
01127 //      nearEvent.fluxErr = nearEvent.fluxErrTotalErrorAfterTune;
01128 //      farEvent.fluxErr = farEvent.fluxErrTotalErrorAfterTune;
01129 //    }
01130   }
01131   else{
01132     static Int_t messageCounter = 0;
01133     if (messageCounter < 5){
01134       MSG("NuFluxHelper",Msg::kInfo)
01135         << "No SKZP reweighting" << endl;
01136       ++messageCounter;
01137     }
01138   }
01139   if (fdoBeamShift){
01140     {
01141       static Int_t messageCounter = 0;
01142       if (messageCounter < 5){
01143         MSG("NuFluxHelper",Msg::kInfo)
01144           << "Performing beam shift "
01145           << fbeamShiftAsSigma << " sigma"
01146           << endl;
01147         ++messageCounter;
01148       }
01149     }
01150     flux_weight_near *= 1.0 + fbeamShiftAsSigma*(nearEvent.fluxErr - 1.0);
01151     flux_weight_far *= 1.0 + fbeamShiftAsSigma*(farEvent.fluxErr - 1.0);
01152   }
01153   if (fdoScrapingShift){
01154     Double_t ppvx = fluxChain->ParentProdVtxX(flukaEntry);
01155     Double_t ppvy = fluxChain->ParentProdVtxY(flukaEntry);
01156     Double_t ppvz = fluxChain->ParentProdVtxZ(flukaEntry);
01157     Float_t ppvr = sqrt(ppvx*ppvx + ppvy*ppvy);
01158     Float_t Znom = 52.06; // -187.06 for HE
01159     if (BeamType::kL250z200i == this->BeamType()){
01160       Znom = -187.06;
01161     }
01162     else if (BeamType::kL010z185i == this->BeamType()){
01163       Znom = 52.06;
01164     }
01165     else{
01166       Znom = 52.06;
01167     }
01168     
01169     Bool_t shouldIShift = true; 
01170     if (ppvr < 1.65 && TMath::Abs(ppvz - Znom) < 0.1){
01171       shouldIShift = false;
01172     }
01173     if (TMath::Abs(ppvr - 1.51) < 0.11 && ppvz < Znom){
01174       shouldIShift = false; // Target Side
01175     }
01176     // Chase (z < 4500) or Decay Pipe (z > 4500)
01177     if (shouldIShift){
01178       flux_weight_near *= fscrapingScaleFactor;
01179       flux_weight_far *= fscrapingScaleFactor;
01180     }
01181   }
01182   
01183   //What's the cross-section of my neutrino?
01184   //Only needed for filling XSec-reweighted plots
01185   Double_t xsec_nd = this->CrossSection(Ntype,Nenergyn);
01186   Double_t xsec_fd = this->CrossSection(Ntype,Nenergyf);
01187   if(xsec_nd<=0.0) xsec_nd = 0.0;
01188   if(xsec_fd<=0.0) xsec_fd = 0.0;
01189   
01190   //Fill the beam matrix without MM reweighting or cross-sections:
01191   //(Does this reduce down to the N/F method?)
01192   fFDVsNDMatrix->Fill(Nenergyn,
01193                       Nenergyf,
01194                       Nimpwt*Nwtfar*flux_weight_far);
01195   
01196   //Fill the beam matrix without MM reweighting but with cross-sections:
01197   fFDVsNDMatrixXSec->Fill(Nenergyn,
01198                           Nenergyf,
01199                           Nimpwt*Nwtfar*xsec_fd*flux_weight_far);
01200   
01201   //Needed to normalise fFDVsNDMatrix:
01202   fTrueEnergyNuFlux_ND->Fill(Nenergyn,
01203                              Nimpwt*Nwtnear*flux_weight_near);
01204   
01205   //Not needed:
01206   fTrueEnergyNuFlux_FD->Fill(Nenergyf,
01207                              Nimpwt*Nwtfar*flux_weight_far);   
01208   
01209   //Needed to normalise fFDVsNDMatrixXSec:
01210   fTrueEnergyCCFlux_ND->Fill(Nenergyn,
01211                              Nimpwt*Nwtnear*xsec_nd*flux_weight_near);
01212   
01213   //Not needed:
01214   fTrueEnergyCCFlux_FD->Fill(Nenergyf,
01215                              Nimpwt*Nwtfar*xsec_fd*flux_weight_far);
01216 
01217   return;
01218 }
01219 
01220 //____________________________________________________________________72
01221 const Double_t
01222 NuFluxHelper::CrossSection(const NuParticleType_t particle,
01223                            const Double_t energy) const
01224 {
01225   if (NuParticle::kNuMu == particle){
01226     return (Double_t) fxSecGraphNuMuCC->Eval(energy,0,"");
01227   }
01228   if (NuParticle::kNuMuBar == particle){
01229     return (Double_t) fxSecGraphNuMuBarCC->Eval(energy,0,"");
01230   }
01231   return 0.0;
01232 }
01233 
01234 //____________________________________________________________________72
01235 const Double_t
01236 NuFluxHelper::TauCrossSection(const NuParticleType_t particle,
01237                               const Double_t energy) const
01238 {
01239   //The cross section if the mus change to taus en route
01240   if (NuParticle::kNuMu == particle){
01241     return (Double_t) fxSecGraphNuTauCC->Eval(energy,0,"");
01242   }
01243   if (NuParticle::kNuMuBar == particle){
01244     return (Double_t) fxSecGraphNuTauBarCC->Eval(energy,0,"");
01245   }
01246   return 0.0;
01247 }
01248 
01249 //____________________________________________________________________72
01250 const TVector3 NuFluxHelper::
01251 ConvertNDToBeamCoOrdinates(const TVector3& ndCoordinates) const
01252 {
01253   //Give it a point in ND co-ordinates.
01254   //Returns the same point in beam co-ordinates.
01255   
01256   // beam center (0,0) in detector coord system:
01257   // (148.844,13.97)
01258   // z offset is 104000
01259   // beamdydz = -0.0581
01260   Double_t beamCenterXDet = 148.28*Munits::cm;
01261   Double_t beamCenterYDet = 23.84*Munits::cm;
01262   Double_t beamAngle = 3.323155*TMath::DegToRad();
01263   Double_t detZ0InBeamCoOrds = 103648.837*Munits::cm;
01264   
01265   Double_t beamX = ndCoordinates.X() - beamCenterXDet;
01266   Double_t beamY =
01267     (ndCoordinates.Y()-beamCenterYDet)
01268     *TMath::Cos(beamAngle) +
01269     ndCoordinates.Z()*TMath::Sin(beamAngle);
01270   Double_t beamZ =
01271     detZ0InBeamCoOrds +
01272     (ndCoordinates.Z()*TMath::Cos(beamAngle) - 
01273      ndCoordinates.Y()*TMath::Sin(beamAngle));
01274   //N.B. beamz should have a term beamCenterYDet*TMath::Sin(3.23155)
01275   //assuming the 104000 cm is measured along the beam axis.
01276   //But this term's small.
01277 
01278   TVector3 beamCoordinates(beamX,
01279                            beamY,
01280                            beamZ);
01281   return beamCoordinates;
01282 }
01283 
01284 //____________________________________________________________________72
01285 const Bool_t NuFluxHelper::IsNDFiducial(const TVector3& ndPoint) const
01286 {
01287   //create a NuCuts object
01288   static NuCuts nuCuts;
01289   
01290   //give fake values for u,v,plane,r,releaseType
01291   //since they are not needed for kCC0325Std
01292   return nuCuts.IsInFidVol(ndPoint.X(),ndPoint.Y(),ndPoint.Z(),
01293                            0,0,
01294                            0,0,
01295                            Detector::kNear,NuCuts::kCC0325Std,
01296                            0,SimFlag::kMC);
01297   
01298   //Bool_t NuCuts::IsInFidVol(Float_t x,Float_t y,Float_t z,
01299   //              Float_t u,Float_t v,
01300   //              Int_t planeTrkVtx,Float_t rTrkVtx,
01301   //              Int_t detector,Int_t anaVersion,
01302   //              Int_t releaseType,Int_t simFlag)
01303   
01304   //return nuCuts.IsInFidVolNDCC0325Std(ndPoint.X(),
01305   //                        ndPoint.Y(),
01306   //                        ndPoint.Z());
01307 }
01308 
01309 //____________________________________________________________________72
01310 void NuFluxHelper::FillMMHelpers(const NuFluxChain* fluxChain,
01311                                  const Int_t flukaEntry) const
01312 {
01313   //Get the fluka variables I'm going to need
01314   NuParticleType_t Ntype = fluxChain->NuType(flukaEntry);
01315   Int_t tptype = fluxChain->ParentParticleType(flukaEntry);
01316   Double_t tpx = fluxChain->TargetParentPX(flukaEntry);
01317   Double_t tpy = fluxChain->TargetParentPY(flukaEntry);
01318   Double_t tpz = fluxChain->TargetParentPZ(flukaEntry);
01319   Double_t Nimpwt = fluxChain->NuImportanceWeight(flukaEntry);
01320   
01321   //Higher-level fluka variables
01322   Double_t pt = 0;
01323   Double_t pt2 = tpx*tpx + tpy*tpy;
01324   if (0 < pt2){pt = sqrt(pt2);}
01325   
01326   //Loop over the neutrinos 10 times to spread out importance weights
01327   for(int subLoop=0;subLoop<10;subLoop++){
01328     
01329     //Make a vector ready to hold random detector points
01330     TVector3 vDetPoint(0,0,0);
01331     
01332     //Keep creating random points until one falls within the
01333     //fiducial volume.
01334     do {
01335       vDetPoint.SetX(frandom3->Uniform(-300,300)*Munits::cm);
01336       vDetPoint.SetY(frandom3->Uniform(-300,300)*Munits::cm);
01337       vDetPoint.SetZ(frandom3->Uniform(0,600)*Munits::cm);
01338     } while (!this->IsNDFiducial(vDetPoint));
01339     
01340     TVector3 vBeamPoint = this->ConvertNDToBeamCoOrdinates(vDetPoint);
01341     
01342     Double_t X = vBeamPoint.X()/Munits::cm;
01343     Double_t Y = vBeamPoint.Y()/Munits::cm;
01344     Double_t Z = vBeamPoint.Z()/Munits::cm;
01345     
01346     //Get the ND weight and energy:
01347     ArrAy newvals_nd = this->NuWte(X,Y,Z,fluxChain,flukaEntry);
01348     //get new fd weight and energy:
01349     ArrAy newvals_fd = this->NuWte(0,0,73534000.,fluxChain,flukaEntry);
01350     
01351     //Calculate SKZP parameters for the new neutrino energies
01352     //Make NuEvents to get the beam weights into.  
01353     NuEvent nearEvent;
01354     nearEvent.reweightVersion = this->ReweightVersion();
01355     nearEvent.simFlag = SimFlag::kMC;
01356     nearEvent.beamType = this->BeamType();
01357     nearEvent.runPeriod = this->RunPeriod();
01358     nearEvent.neuEnMC = newvals_nd.new_ene;
01359     nearEvent.inu=fluxChain->NuParticleAsPDGCode(Ntype);
01360     nearEvent.tptype = tptype;
01361     nearEvent.tpz = tpz;
01362     nearEvent.tpy = tpy;
01363     nearEvent.tpx = tpx;
01364     nearEvent.detector = Detector::kNear;
01365     nearEvent.beamWeightRunI = 1.0;
01366     nearEvent.beamWeightRunII = 1.0;
01367     nearEvent.beamWeight = 1.0;
01368     nearEvent.fluxErr = 1.0;
01369     nearEvent.fluxErrTotalErrorAfterTuneRunI = 1.0;
01370     nearEvent.fluxErrTotalErrorAfterTuneRunII = 1.0;
01371     nearEvent.fluxErrTotalErrorAfterTune = 1.0;
01372     
01373     NuEvent farEvent;
01374     farEvent.reweightVersion = this->ReweightVersion();
01375     farEvent.simFlag = SimFlag::kMC;
01376     farEvent.beamType = this->BeamType();
01377     farEvent.runPeriod = this->RunPeriod();
01378     farEvent.neuEnMC = newvals_fd.new_ene;
01379     farEvent.inu=fluxChain->NuParticleAsPDGCode(Ntype);
01380     farEvent.iaction=1;//CC
01381     farEvent.tptype = tptype;
01382     farEvent.tpz = tpz;
01383     farEvent.tpy = tpy;
01384     farEvent.tpx = tpx;
01385     farEvent.detector = Detector::kFar;
01386     farEvent.beamWeightRunI = 1.0;
01387     farEvent.beamWeightRunII = 1.0;
01388     farEvent.beamWeight = 1.0;
01389     farEvent.fluxErr = 1.0;
01390     farEvent.fluxErrTotalErrorAfterTuneRunI = 1.0;
01391     farEvent.fluxErrTotalErrorAfterTuneRunII = 1.0;
01392     farEvent.fluxErrTotalErrorAfterTune = 1.0;
01393     
01394     //Get the SKZP weights
01395     Double_t flux_weight_near = 1.0;
01396     Double_t flux_weight_far = 1.0;
01397     
01398     if (fdoSKZP){
01399       //Reweight the NuEvents
01400       fzarko->GetBeamWeightsOnly(nearEvent);
01401       fzarko->GetBeamWeightsOnly(farEvent);
01402       
01403       // Debugging code -- you shouldn't see this!
01404       if (farEvent.beamWeightRunI != 1.0) {
01405         cerr << "Beam weights are wrong -- beware!!!" << endl;
01406         assert(false);
01407       }
01408       
01409       flux_weight_near = nearEvent.beamWeight;
01410       flux_weight_far = farEvent.beamWeight;
01411       nearEvent.fluxErr = nearEvent.fluxErrTotalErrorAfterTune;
01412       farEvent.fluxErr = farEvent.fluxErrTotalErrorAfterTune;
01413     }
01414     if (fdoBeamShift){
01415       {
01416         static Int_t messageCounter = 0;
01417         if (messageCounter < 5){
01418           MSG("NuFluxHelper",Msg::kInfo)
01419             << "Performing beam shift "
01420             << fbeamShiftAsSigma << " sigma"
01421             << endl;
01422           ++messageCounter;
01423         }
01424       }
01425       flux_weight_near *= 1.0 + fbeamShiftAsSigma*(nearEvent.fluxErr - 1.0);
01426       flux_weight_far *= 1.0 + fbeamShiftAsSigma*(farEvent.fluxErr - 1.0);
01427     }
01428     if (fdoScrapingShift){
01429       Double_t ppvx = fluxChain->ParentProdVtxX(flukaEntry);
01430       Double_t ppvy = fluxChain->ParentProdVtxY(flukaEntry);
01431       Double_t ppvz = fluxChain->ParentProdVtxZ(flukaEntry);
01432       Float_t ppvr = sqrt(ppvx*ppvx + ppvy*ppvy);
01433       Float_t Znom = 52.06; // -187.06 for HE
01434       if (BeamType::kL250z200i == this->BeamType()){
01435         Znom = -187.06;
01436       }
01437       else if (BeamType::kL010z185i == this->BeamType()){
01438         Znom = 52.06;
01439       }
01440       else{
01441         Znom = 52.06;
01442       }
01443       
01444       Bool_t shouldIShift = true; 
01445       if (ppvr < 1.65 && TMath::Abs(ppvz - Znom) < 0.1){
01446         shouldIShift = false;
01447       }
01448       if (TMath::Abs(ppvr - 1.51) < 0.11 && ppvz < Znom){
01449         shouldIShift = false; // Target Side
01450       }
01451       // Chase (z < 4500) or Decay Pipe (z > 4500)
01452       if (shouldIShift){
01453         flux_weight_near *= fscrapingScaleFactor;
01454         flux_weight_far *= fscrapingScaleFactor;
01455       }
01456     }
01457     
01458     //Calculate cross-sections for the new neutrino energies
01459     Double_t xsec_nd = this->CrossSection(Ntype,newvals_nd.new_ene);
01460     if(xsec_nd<=0.0) xsec_nd = 0.0; 
01461     Double_t xsec_fd = this->CrossSection(Ntype,newvals_fd.new_ene);
01462     if(xsec_fd<=0.0) xsec_fd = 0.0; 
01463     //Tau cross section:
01464     Double_t tauXsec_fd = this->TauCrossSection(Ntype,newvals_fd.new_ene);
01465     if (tauXsec_fd<=0.0) tauXsec_fd = 0.0;
01466     
01467     //Fill the beam matrix:
01468     fFDVsNDMatrixXSecRW->Fill(newvals_nd.new_ene,
01469                               newvals_fd.new_ene,
01470                               Nimpwt*newvals_fd.new_weight*
01471                               xsec_fd*flux_weight_far);
01472 
01473     //Fill the numu->nutau beam matrix:
01474     fFDVsNDMatrixTauXSecRW->Fill(newvals_nd.new_ene,
01475                                  newvals_fd.new_ene,
01476                                  Nimpwt*newvals_fd.new_weight*
01477                                  tauXsec_fd*flux_weight_far);
01478     
01479     
01480     //Fill the beam matrix without cross-sections:
01481     fFDVsNDMatrixRW->Fill(newvals_nd.new_ene,
01482                           newvals_fd.new_ene,
01483                           Nimpwt*newvals_fd.new_weight*
01484                           flux_weight_far);
01485     
01486     //Needed to normalise fFDVsNDMatrixRW:
01487     fTrueEnergyNuFluxRW_ND->Fill(newvals_nd.new_ene,
01488                                  Nimpwt*newvals_nd.new_weight*
01489                                  flux_weight_near);
01490     //Not needed:
01491     fTrueEnergyNuFluxRW_FD->Fill(newvals_fd.new_ene,
01492                                  Nimpwt*newvals_fd.new_weight*
01493                                  flux_weight_far);
01494     
01495     //Needed to normalise fFDVsNDMatrixXSecRW and fFDVsNDMatrixTauXSecRW:
01496     fTrueEnergyCCFluxRW_ND->Fill(newvals_nd.new_ene,
01497                                  Nimpwt*newvals_nd.new_weight*
01498                                  xsec_nd*flux_weight_near);
01499     //Not needed:
01500     fTrueEnergyCCFluxRW_FD->Fill(newvals_fd.new_ene,
01501                                  Nimpwt*newvals_fd.new_weight*
01502                                  xsec_fd*flux_weight_far);
01503        
01504   } //End x10 loop over fluka neutrinos
01505 }
01506 
01507 //____________________________________________________________________72
01508 void NuFluxHelper::NormaliseHistos() const
01509 {
01510   MSG("NuFluxHelper",Msg::kInfo)
01511     <<"Normalising histograms" << endl;
01512 
01513   //Loop over the bins of the beam matrices:
01514   for(int i=1;i<=fNNDTrueEBins;i++){
01515     for(int j=1;j<=fNFDTrueEBins;j++){
01516       //Renormalise the un-MM-reweighted, un-XSec-reweighted beam matrix
01517       if(fTrueEnergyNuFlux_ND->GetBinContent(i)>0 && 
01518          fFDVsNDMatrix->GetBinContent(i,j)>0 ) {
01519         Float_t error = TMath::Power(fFDVsNDMatrix->GetBinError(i,j) / 
01520                                      fFDVsNDMatrix->GetBinContent(i,j),2);
01521         error = TMath::Sqrt(error);
01522         fFDVsNDMatrix->SetBinContent(i,j,
01523                                      fFDVsNDMatrix->GetBinContent(i,j)/
01524                                      fTrueEnergyNuFlux_ND->GetBinContent(i));
01525         fFDVsNDMatrix->SetBinError(i,j,error * 
01526                                    fFDVsNDMatrix->GetBinContent(i,j));
01527       }
01528       else {
01529         fFDVsNDMatrix->SetBinContent(i,j,0.);
01530         fFDVsNDMatrix->SetBinError(i,j,0.);
01531       }
01532       
01533       //Renormalise the MM-reweighted, un-XSec-reweighted beam matrix
01534       if( fTrueEnergyNuFluxRW_ND->GetBinContent(i)>0 && 
01535           fFDVsNDMatrixRW->GetBinContent(i,j)>0 ) {
01536         Float_t error = TMath::Power(fFDVsNDMatrixRW->GetBinError(i,j) / 
01537                                      fFDVsNDMatrixRW->GetBinContent(i,j),2);
01538         error = TMath::Sqrt(error);
01539         fFDVsNDMatrixRW->SetBinContent(i,j,
01540                                        fFDVsNDMatrixRW->GetBinContent(i,j)/
01541                                        fTrueEnergyNuFluxRW_ND->GetBinContent(i));
01542         fFDVsNDMatrixRW->SetBinError(i,j,error * 
01543                                      fFDVsNDMatrixRW->GetBinContent(i,j));
01544       }
01545       else {
01546         fFDVsNDMatrixRW->SetBinContent(i,j,0.);
01547         fFDVsNDMatrixRW->SetBinError(i,j,0.);
01548       }
01549 
01550       //Renormalise the un-MM-reweighted, XSec-reweighted beam matrix
01551       if( fTrueEnergyCCFlux_ND->GetBinContent(i)>0 &&
01552           fFDVsNDMatrixXSec->GetBinContent(i,j)>0 ) {
01553         Float_t error = TMath::Power(fFDVsNDMatrixXSec->GetBinError(i,j) / 
01554                                      fFDVsNDMatrixXSec->GetBinContent(i,j),2);
01555         error = TMath::Sqrt(error);
01556         fFDVsNDMatrixXSec->SetBinContent(i,j,
01557                                          fFDVsNDMatrixXSec->GetBinContent(i,j)/
01558                                          fTrueEnergyCCFlux_ND->GetBinContent(i));
01559         fFDVsNDMatrixXSec->SetBinError(i,j,error * 
01560                                        fFDVsNDMatrixXSec->GetBinContent(i,j));
01561       }
01562       else {
01563         fFDVsNDMatrixXSec->SetBinContent(i,j,0.);
01564         fFDVsNDMatrixXSec->SetBinError(i,j,0.);
01565       }
01566 
01567       //Renormalise the MM-reweighted, XSec-reweighted beam matrix
01568       if( fTrueEnergyCCFluxRW_ND->GetBinContent(i)>0 &&
01569           fFDVsNDMatrixXSecRW->GetBinContent(i,j)>0 ) {
01570         Float_t error = TMath::Power(fFDVsNDMatrixXSecRW->GetBinError(i,j) / 
01571                                      fFDVsNDMatrixXSecRW->GetBinContent(i,j),2);
01572         error = TMath::Sqrt(error);
01573         fFDVsNDMatrixXSecRW->SetBinContent(i,j,
01574                                            fFDVsNDMatrixXSecRW->GetBinContent(i,j)/
01575                                            fTrueEnergyCCFluxRW_ND->GetBinContent(i));
01576         fFDVsNDMatrixXSecRW->SetBinError(i,j,error *
01577                                          fFDVsNDMatrixXSecRW->GetBinContent(i,j));
01578       }
01579       else {
01580         fFDVsNDMatrixXSecRW->SetBinContent(i,j,0.);
01581         fFDVsNDMatrixXSecRW->SetBinError(i,j,0.);
01582       }
01584 
01585       //Renormalise the MM-reweighted, tauXSec-reweighted beam matrix
01586       if( fTrueEnergyCCFluxRW_ND->GetBinContent(i)>0 &&
01587           fFDVsNDMatrixTauXSecRW->GetBinContent(i,j)>0 ) {
01588         Float_t error = TMath::Power(fFDVsNDMatrixTauXSecRW->GetBinError(i,j) / 
01589                                      fFDVsNDMatrixTauXSecRW->GetBinContent(i,j),2);
01590         error = TMath::Sqrt(error);
01591         fFDVsNDMatrixTauXSecRW->SetBinContent(i,j,
01592                                               fFDVsNDMatrixTauXSecRW->GetBinContent(i,j)/
01593                                               fTrueEnergyCCFluxRW_ND->GetBinContent(i));
01594         fFDVsNDMatrixTauXSecRW->SetBinError(i,j,error *
01595                                             fFDVsNDMatrixTauXSecRW->GetBinContent(i,j));
01596       }
01597       else {
01598         fFDVsNDMatrixTauXSecRW->SetBinContent(i,j,0.);
01599         fFDVsNDMatrixTauXSecRW->SetBinError(i,j,0.);
01600       }
01602 
01603     } //End loop over matrix columns
01604   } //End loop over matrix rows
01605   return;
01606 }
01607 
01608 //____________________________________________________________________72
01609 const ArrAy NuFluxHelper::NuWte(const Double_t XDET,
01610                                 const Double_t YDET,
01611                                 const Double_t ZDET,
01612                                 const NuFluxChain* fluxChain,
01613                                 const Int_t flukaEntry) const
01614 {
01615   ArrAy   newvars,empty;
01616   empty.new_ene   =-1;
01617   empty.new_weight=-1.;
01618   
01619   Int_t Ntype = fluxChain->NuType(flukaEntry);
01620   Double_t Vx = fluxChain->ParentDecayVtxX(flukaEntry)/Munits::cm;
01621   Float_t Vy = fluxChain->ParentDecayVtxY(flukaEntry)/Munits::cm;
01622   Float_t Vz = fluxChain->ParentDecayVtxZ(flukaEntry)/Munits::cm;
01623   Float_t pdpx = fluxChain->ParentPX(flukaEntry);
01624   Float_t pdpy = fluxChain->ParentPY(flukaEntry);
01625   Float_t pdpz = fluxChain->ParentPZ(flukaEntry);
01626   Float_t ppdxdz = fluxChain->ParentProdDXDZ(flukaEntry);
01627   Float_t ppdydz = fluxChain->ParentProdDYDZ(flukaEntry);
01628   Float_t pppz = fluxChain->ParentProdPZ(flukaEntry);
01629   Float_t ppenergy = fluxChain->ParentProdEnergy(flukaEntry);
01630   Int_t ptype = fluxChain->ParentType(flukaEntry);
01631   Float_t muparpx = fluxChain->MuonParentPX(flukaEntry);
01632   Float_t muparpy = fluxChain->MuonParentPY(flukaEntry);
01633   Float_t muparpz = fluxChain->MuonParentPZ(flukaEntry);
01634   Float_t mupare = fluxChain->MuonParentEnergy(flukaEntry);
01635   Float_t Necm = fluxChain->NuECofM(flukaEntry);
01636   
01637   //    -----------------fixed parameters
01638   Double_t pimass, kmass, k0mass, mumass, omegamass;
01639   pimass=0.13957; kmass=0.49368;
01640   k0mass=0.49767; mumass=0.105658389;
01641   omegamass=1.67245;
01642   Int_t nue, nuebar, numu, numubar, muplus, muminus;
01643   nue=53; nuebar=52; numu=56; numubar=55;
01644   muplus=5;  muminus=6;
01645   //      set to flux per 1 meter radius 
01646   Double_t RDET =100.;
01647   //   
01648   
01649   
01650 //    -----------------ADAMO style variables
01651       Double_t Neutrino_type;
01652       Double_t Vertex_x,           Vertex_y,          Vertex_z;
01653       Double_t Neutrino_parentpx,  Neutrino_parentpy, Neutrino_parentpz;
01654       Double_t Particle_dxdz,      Particle_dydz,     Particle_pz;
01655       Double_t Particle_energy,    Particle_type;
01656       Double_t Muparent_px,        Muparent_py,       Muparent_pz;
01657       Double_t Muparent_energy;
01658       Double_t Neutrino_ecm;
01659 
01660 //    -----------------rest of local variables
01661       Double_t eneu, WGT;
01662       double ENUZR, gamma, beta[3], SANGDET, RAD, EMRAT;
01663       double beta_mag, gamma_sqr;
01664       double parent_energy, parent_mass, parentp, partial;
01665       double costh_pardet, THETA_pardet,costh;
01666       Double_t P_dcm_nu[4], P_nu[3], P_pcm_mp[3];
01667       Double_t P_pcm, wt_ratio, xnu;
01668 //======================================================================
01669 
01670 //    switch to ADAMO variables to maintain compatibility with internal GNUMI
01671       Neutrino_type = Ntype;
01672       Vertex_x = Vx;
01673       Vertex_y = Vy;
01674       Vertex_z = Vz;
01675       Neutrino_parentpx = pdpx;
01676       Neutrino_parentpy = pdpy;
01677       Neutrino_parentpz = pdpz;
01678       Particle_dxdz   = ppdxdz;
01679       Particle_dydz   = ppdydz;
01680       Particle_pz     = pppz;
01681       Particle_energy = ppenergy;
01682       Particle_type   = ptype;
01683       Muparent_px = muparpx;
01684       Muparent_py = muparpy;
01685       Muparent_pz = muparpz;
01686       Muparent_energy = mupare;
01687       Neutrino_ecm = Necm;
01688 
01689 //    >=t gamma of muon parent particle at point of decay to neutrino
01690 
01691       if(Particle_type==8||Particle_type==9)        parent_mass = pimass;
01692       else if(Particle_type==11||Particle_type==12) parent_mass = kmass;
01693       else if(Particle_type==10||Particle_type==16) parent_mass = k0mass;
01694       else if(Particle_type==5||Particle_type==6)   parent_mass = mumass;
01695       else if(Particle_type==24||Particle_type==32) parent_mass = omegamass;
01696       else{
01697         cout << "NUWEIGHT unknown particle type STOP" << endl;
01698         return empty;
01699       }
01700       parent_energy = sqrt(double(Neutrino_parentpx)*double(Neutrino_parentpx)
01701        + double(Neutrino_parentpy)*double(Neutrino_parentpy)
01702        + double(Neutrino_parentpz)*double(Neutrino_parentpz) + parent_mass*parent_mass);
01703       gamma = parent_energy / parent_mass;
01704       gamma_sqr = gamma*gamma;
01705       beta_mag  = sqrt( (gamma_sqr-1.)/gamma_sqr );
01706 
01707 //    >=t the neutrino energy in the parent decay cm
01708 
01709 //    :::ARBITRARY LORENTZ TRANSFORM
01710 //    :::     EtP = PCX * BGX + PCY * BGY + PCZ * BGZ
01711 //    :::     E  = GA * E//+ EtP
01712 //    :::     PtE = EtP / (GA + 1e0) + EC
01713 //    :::     PX = PCX + BGX * PtE
01714 //    :::     PY = PCY + BGY * PtE
01715 //    :::     PZ = PCZ + BGZ * PtE
01716 //    :::     P  = SQRT (PX * PX + PY * PY + PZ * PZ)
01717       ENUZR = Neutrino_ecm;
01718 
01719 //    >=t angle from parent line of flight to detector in lab frame
01720 
01721       RAD =pow((double(XDET)-double(Vertex_x)),2)+pow((double(YDET)-double(Vertex_y)),2)
01722         +pow((double(ZDET)-double(Vertex_z)),2);
01723       RAD = sqrt(RAD);
01724       parentp =  double(Neutrino_parentpx)*double(Neutrino_parentpx) +
01725        double(Neutrino_parentpy)*double(Neutrino_parentpy) + double(Neutrino_parentpz)* double(Neutrino_parentpz);
01726       parentp = sqrt(parentp);
01727       costh_pardet = ( Neutrino_parentpx*(double(XDET)-Vertex_x)
01728        + Neutrino_parentpy*(double(YDET)-Vertex_y)
01729        + Neutrino_parentpz*(double(ZDET)-Vertex_z) )
01730        / ( parentp * RAD );
01731       if(fabs(costh_pardet)>1.){
01732         if(costh_pardet<0) costh_pardet = -1.; 
01733         if(costh_pardet>0) costh_pardet =  1;
01734       }
01735       THETA_pardet = acos(costh_pardet);
01736 
01737 //    weighted neutrino energy in lab, approx, good for small theta
01738 //I'VE WORKED THIS OUT AND I DON'T THINK IT'S APPROXIMATE:
01739 //I THINK IT'S EXACT --JE
01740       EMRAT = 1. / (gamma * (1. - beta_mag * cos(THETA_pardet)));
01741       eneu=EMRAT*ENUZR;
01742 
01743 //    >=t solid angle/4pi for detector element
01744       SANGDET = (   RDET*RDET/((ZDET-Vertex_z)*(ZDET-Vertex_z)))/(4.0   );
01745 
01746 //    weight for solid angle and lorentz boost
01747       WGT = SANGDET * (EMRAT*EMRAT);
01748 //    weight weighted by approx neutrino cross section
01749 //    WGTE=0.67*ENEU*WGT
01750       
01751 //    done for all except polarized muon decay, ==================
01752 //    in which case need to modify weight
01753 //    (Warning: This section may need more double precision)
01754       if(Particle_type==muplus||Particle_type==muminus) {
01755 
01756 //      boost new neutrino to mu decay cm
01757 //      boost new neutrino to mu decay cm
01758         beta[0] = Neutrino_parentpx / parent_energy;
01759         beta[1] = Neutrino_parentpy / parent_energy;
01760         beta[2] = Neutrino_parentpz / parent_energy;
01761         P_nu[0] = (XDET-Vertex_x)*eneu/RAD;
01762         P_nu[1] = (YDET-Vertex_y)*eneu/RAD;
01763         P_nu[2] = (ZDET-Vertex_z)*eneu/RAD;
01764         partial =gamma*(beta[0]*P_nu[0]+beta[1]*P_nu[1]+beta[2]*P_nu[2]);
01765         partial = eneu - partial /(gamma+1.);
01766         P_dcm_nu[0] = P_nu[0] - beta[0]*gamma*partial;
01767         P_dcm_nu[1] = P_nu[1] - beta[1]*gamma*partial;
01768         P_dcm_nu[2] = P_nu[2] - beta[2]*gamma*partial;
01769         P_dcm_nu[3] = sqrt(P_dcm_nu[0]*P_dcm_nu[0]+P_dcm_nu[1]*+P_dcm_nu[1]+P_dcm_nu[2]*P_dcm_nu[2]);
01770 
01771 //      boost parent of mu to mu production cm
01772         gamma = Particle_energy/parent_mass;
01773         beta[0] = Particle_dxdz*Particle_pz/Particle_energy;
01774         beta[1] = Particle_dydz*Particle_pz/Particle_energy;
01775         beta[2] =               Particle_pz/Particle_energy;
01776         partial = gamma * ( beta[0]*Muparent_px + 
01777          beta[1]*Muparent_py + beta[2]*Muparent_pz);
01778         partial = Muparent_energy - partial /(gamma+1.);
01779         P_pcm_mp[0] = Muparent_px - beta[0]*gamma*partial;
01780         P_pcm_mp[1] = Muparent_py - beta[1]*gamma*partial;
01781         P_pcm_mp[2] = Muparent_pz - beta[2]*gamma*partial;
01782         P_pcm = sqrt(P_pcm_mp[0]*P_pcm_mp[0] + P_pcm_mp[1]* P_pcm_mp[1] + P_pcm_mp[2]* P_pcm_mp[2]);
01783 
01784 //      cal//new  decay angle w.r.t. (anti)spin direction
01785         if(P_dcm_nu[3]*P_pcm!=0) {
01786           costh  = ( P_dcm_nu[0]*P_pcm_mp[0] + P_dcm_nu[1]*P_pcm_mp[1]
01787                      + P_dcm_nu[2]*P_pcm_mp[2] ) / (P_dcm_nu[3]*P_pcm);
01788         }
01789         else costh = 0;
01790         if(fabs(costh)>=1.) {
01791          if(costh<0.) costh = -1. ; 
01792          if(costh>0.) costh=  1.  ;
01793         } 
01794 //      cal//relative weight due to angle difference
01795         if( Neutrino_type==nue || Neutrino_type==nuebar ) {
01796           wt_ratio = 1.-costh;
01797         }  
01798         else if( Neutrino_type==numu|| Neutrino_type==numubar) {
01799           xnu = 2. * ENUZR / mumass;
01800           wt_ratio = ( (3.-2.*xnu) - (1.-2.*xnu)*costh ) / (3.-2.*xnu);
01801          }
01802         else {
01803           cout << "NUWEIGHT bad neutrino type" << endl;
01804           return empty;
01805         }
01806 
01807         WGT = WGT * wt_ratio;
01808       }
01809       Double_t ene_wei[2];
01810       ene_wei[0]=eneu;
01811       ene_wei[1]=WGT;
01812       newvars.new_ene    = eneu;
01813       newvars.new_weight = WGT;
01814       return newvars;
01815 }

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