All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PrimaryHadronSWCentralSplineVariationWeightCalc.cxx
Go to the documentation of this file.
1 //Built from PrimaryHadronSWCentralSplineVariation.cxx in ubcode/EventWeight/Calculator/Flux/BNBPrimaryHadron directory
2 
3 #include "FluxCalcPrep.h"
4 #include "TSpline.h"
5 
6 
7 namespace sbn {
8  namespace evwgh {
9 
10  std::pair<bool, double> FluxWeightCalc::PHSWCSVWeightCalc(simb::MCFlux flux, std::vector<float> rand){
11 
12  //
13  // Largely built off the MiniBooNE code
14  // but this is intended to expand beyond it
15  //
16  // Edits from MiniBooNE code:
17  //
18  // JZ (6/2017) : Remove max weight, set to max_limit of a double
19  // JZ (6/2017) : Changed guards on c9 to be double point precision
20  //
21 
22  bool parameters_pass = true;
23 
24  double c1 = SWParam[0];
25  double c2 = SWParam[1];
26  double c3 = SWParam[2];
27  double c4 = SWParam[3];
28  double c5 = SWParam[4];
29  double c6 = SWParam[5];
30  double c7 = SWParam[6];
31  double c8 = SWParam[7];
32  double c9 = 1.0; // This isn't in the table but it is described in the text
33 
34  // Lay out the event kinimatics
35  double HadronMass = 0.13957010;
36 
37  // if(fabs(fprimaryHad) == 211) HadronMass = 0.13957010; //Charged Pion
38  // else{
39  // throw art::Exception(art::errors::StdException)
40  // << "sanford-wang is only configured for charged pions ";
41  // }
42 
43  TLorentzVector HadronVec;
44  double HadronPx = flux.ftpx;
45  double HadronPy = flux.ftpy;
46  double HadronPz = flux.ftpz;
47  double HadronE = sqrt(HadronPx*HadronPx +
48  HadronPy*HadronPy +
49  HadronPz*HadronPz +
50  HadronMass*HadronMass);
51  HadronVec.SetPxPyPzE(HadronPx,HadronPy,HadronPz,HadronE);
52 
53  ////////
54  //
55  // Based on MiniBooNE code to evaluate the theta value within below the maximum
56  // HARP theta coverage. This helps keep the splines well formed and constrains
57  // the uncertainties at very low neutrino energy
58  //
59  ////////
60 
61  double ThetaOfInterest;
62  if(HadronVec.Theta() > 0.195){
63  ThetaOfInterest = 0.195;
64  }
65  else{
66  ThetaOfInterest = HadronVec.Theta();
67  }
68 
69 
70  // Get Initial Proton Kinitmatics
71  // CURRENTLY GSimple flux files drop information about
72  // the initial state proton, but that this
73  TLorentzVector ProtonVec;
74  double ProtonMass = 0.9382720;
75  double ProtonPx = 0;
76  double ProtonPy = 0;
77  double ProtonPz = 8.89; //GeV
78  double ProtonE = sqrt(ProtonPx*ProtonPx +
79  ProtonPy*ProtonPy +
80  ProtonPz*ProtonPz +
81  ProtonMass*ProtonMass);
82  ProtonVec.SetPxPyPzE(ProtonPx,ProtonPy,ProtonPz,ProtonE);
83 
84  //Sanford-Wang Parameterization
85  // Eq 11 from PhysRevD.79.072002
86 
87  double CV = c1 * pow(HadronVec.P(), c2) *
88  (1. - HadronVec.P()/(ProtonVec.P() - c9)) *
89  exp(-1. * c3 * pow(HadronVec.P(), c4) / pow(ProtonVec.P(), c5)) *
90  exp(-1. * c6 * ThetaOfInterest *(HadronVec.P() - c7 * ProtonVec.P() * pow(cos(ThetaOfInterest), c8)));
91 
92  // Check taken from MiniBooNE code
93  if((HadronVec.P()) > ((ProtonVec.P()) - (c9))){
94  CV = 0;}
95 
96  //////
97  //
98  // Now that we have our central value based on the Sanford-Wang parameterization we
99  // need to create variations around this value. MiniBooNE did this by performing
100  // spline fits to the HARP data. This is a reproduction of that code:
101  //
102  ////
103 
104  double* HARPmomentumBins = HARPmomentumBounds.data(); // Convert std::vector to array
105  double* HARPthetaBins = HARPthetaBounds.data(); // Convert std::vector to array
106 
107  int Ntbins = int(HARPthetaBounds.size()) - 1;
108  int Npbins = int(HARPmomentumBounds.size()) - 1;
109 
110  //
111  // Using the HARP cross section and covariance matrices
112  // we will now create variations around the measured HARP
113  // meson production cross sections.
114  //
115 
116  // Important notes of the HARP data:
117  // The cross section matrix has 13 momentum bins and 6 theta bins
118  // The covariance matrix contains the correlated uncertainties across
119  // all 78 cross section measurements.
120  //
121  // The covariance matrix encodes the uncertainty on a given HARP
122  // ANALYSIS BIN instead of being a 3D matrix.
123  //
124  // A HARP analysis bin is defined as
125  // bin = momentum[theta[]] meaning that:
126  // analysis bin 0 is the zeroth theta and zeroth momentum bin
127  // but analysis bin 27 is the 3rd theta and 5th momentum bin
128  //
129  // The first thing to do is convert our cross section matrix into
130  // an std::vector for the analysis bins
131  //
132  std::vector< double > HARPCrossSectionAnalysisBins;
133  HARPCrossSectionAnalysisBins.resize(int(Ntbins*Npbins));
134 
135  int anaBin = 0;
136  for(int pbin = 0; pbin < Npbins; pbin++){
137  for(int tbin = 0; tbin < Ntbins; tbin++){
138  HARPCrossSectionAnalysisBins[anaBin] = HARPXSec[0][pbin][tbin];
139  anaBin++;
140  }
141  }
142 
143  //
144  // Now using this we can vary the cross section based on the HARP covariance matrix
145  // this will allow us to reweigh each cross section measurement based on
146  // the multigaussian smearing of this matrix.
147  //
148 
149  std::vector< double > smearedHARPCrossSectionAnalysisBins =
150  MultiGaussianSmearing(HARPCrossSectionAnalysisBins, FitCov, fIsDecomposed,rand);
151  HARPCrossSectionAnalysisBins.clear();
152 
153  //
154  // Check all the smeared cross sections, if any come out to be negative then
155  // we will not pass this given parameter set.
156  //
157 
158  for(int check = 0; check < int(smearedHARPCrossSectionAnalysisBins.size()); check++){
159  if(smearedHARPCrossSectionAnalysisBins[check] < 0){ parameters_pass = false;}
160  }
161 
162  //
163  // With a checked set of smeared cross sections we can convert our analysis bin
164  // std::vector back into a TMatrixD, though this is a bit annoying since TMatrices
165  // are an annoying format.
166  //
167  TMatrixD* smearedHARPXSec = new TMatrixD(Npbins,Ntbins);
168 
169  anaBin = 0;
170  for(int pbin = 0; pbin < Npbins; pbin++){
171  for(int tbin = 0; tbin < Ntbins; tbin++){
172  smearedHARPXSec[0][pbin][tbin] = smearedHARPCrossSectionAnalysisBins[anaBin];
173  anaBin++;
174  }
175  }
176 
177  //
178  // We want to now make a vector of histograms that are
179  // projections across the cross section matrix,
180  // this means we want to have vectors where one histogram
181  // is made for each bin on variable X where the histogram
182  // then contains bins for variable Y.
183  //
184  // This will allow us to do a 2D interpolation across the
185  // full parameter space using cubic spline fits
186  //
187 
188  std::vector< TH1F > MomentumBins;
189  MomentumBins.resize(Ntbins);
190  for(int bin = 0; bin < Ntbins; bin++){
191  MomentumBins[bin] = TH1F("HARPp",";;;", Npbins, HARPmomentumBins);
192  MomentumBins[bin].SetBit(kCanDelete);
193  }
194 
195  //Setup vectors of splines for fitting
196  std::vector< TSpline3 > SplinesVsMomentum;
197  SplinesVsMomentum.resize(Ntbins);
198 
199  for(int tbin = 0; tbin < Ntbins; tbin++){
200  for(int pbin = 0; pbin < Npbins; pbin++){
201 
202  //
203  // We want to create spline at fixed theta values, that way we can
204  // study the cross section at the given meson momentum
205  MomentumBins[tbin].SetBinContent(pbin+1, smearedHARPXSec[0][pbin][tbin]);
206  // This will give us the cross section in discreet slices of theta (tbin)
207  // but each histogram in the vector will be the cross section in bins of
208  // momentum that can then be cublic splined
209  //
210  }
211 
212  //
213  // in a given theta slice we can now spline over the cross section entries
214  // in bins of momentum
215  //
216  // Important note about Splines, MiniBooNE used constraints on the
217  // second derivative of the first and final knot point and required
218  // that they both equal to zero, this is not naturally the case in
219  // in TSpline3 but it is default in DCSPLC (the Fortran CERN library spline function)
220  // this helps to control the smoothness of the spline and minimizes the variation bin to bin
221  // For TSpine3 this is controlled by:
222  //
223  // b1 = constrain first knot 1st derivative
224  // b2 = constrain first knot 2nd derivative
225  // e1 = constrain final knot 1st derivative
226  // e2 = constrain final knot 2nd derivative
227  //
228  // the numbers that follow are the values you constrain those conditions to
229  //
230  SplinesVsMomentum[tbin] = TSpline3(&(MomentumBins[tbin]),"b2e2",0,0);
231 
232  }
233  MomentumBins.clear();
234  delete smearedHARPXSec;
235  //
236  // Now that we have the 1D Splines over momentum we want to know
237  // what the cross section is for the meson's momentum in bins of
238  // theta that way we can extract the cross section at the meson's
239  // theta.
240  //
241  TH1F* ThetaBins = new TH1F("HARPt",";;;", Ntbins, HARPthetaBins);
242  ThetaBins->SetBit(kCanDelete);
243  for(int tbin = 0; tbin < Ntbins; tbin++){
244  ThetaBins->SetBinContent(tbin+1, SplinesVsMomentum[tbin].Eval(HadronVec.P()));
245  }
246 
247  ////
248  // Now we can spline across the theta bins and we can extract the exact value of the
249  // cross section for the meson's theta value
250  //
251  // Options described above.
252  /////
253 
254  TSpline3* FinalSpline = new TSpline3(ThetaBins,"b2e2",0,0);
255 
256  double RW = FinalSpline->Eval(ThetaOfInterest);
257 
258  SplinesVsMomentum.clear();
259  delete ThetaBins;
260  delete FinalSpline;
261 
262  //
263  // These guards are inherited from MiniBooNE code
264  //
265  // These were defined here:
266  //
267  // cdcvs0.fnal.gov/cgi-bin/public-cvs/cvsweb-public.cgi/~checkout~/ ...
268  // miniboone/AnalysisFramework/MultisimMatrix/src/MultisimMatrix.inc
269  //
270  // This forces any negative spline fit to be 1
271 
272  ////////
273  // Possible Bug.
274  ////////
275  // This seems to be a feature in the MiniBooNE code
276  // It looks like the intension is to set this to zero
277  // but it is set to 1 before it is set to zero
278 
279  double weight = 1;
280 
281  if(RW < 0 || CV < 0){
282  weight = 1;
283  }
284  else if(fabs(CV) < 1.e-12){
285  weight = 1;
286  }
287  else{
288  weight *= RW/CV;
289  }
290 
291  if(weight < 0) weight = 0;
292  if(weight > 30) weight = 30;
293  if(!(std::isfinite(weight))){
294  std::cout << "SW+Splines : Failed to get a finite weight" << std::endl;
295  weight = 30;
296  }
297 
298  std::pair<bool, double> output(parameters_pass, weight);
299  return output;
300 
301  }// Done with the WeigthCalc function
302 
303  } // namespace evwgh
304 } // namespace sbn
305 
306 
307 
std::vector< double > HARPmomentumBounds
Definition: FluxCalcPrep.h:76
std::pair< bool, double > PHSWCSVWeightCalc(simb::MCFlux flux, std::vector< float > rand)
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
bool isfinite(Vector const &v)
Returns whether all components of the vector are finite.
BEGIN_PROLOG must be more than must be less than pi ThetaBins
Definition: GaisserParam.fcl:8
process_name tightIsolTest check
std::vector< double > SWParam
Definition: FluxCalcPrep.h:78
std::vector< double > HARPthetaBounds
Definition: FluxCalcPrep.h:77
BEGIN_PROLOG sequence::SlidingWindowTriggerPatternsOppositeWindows END_PROLOG simSlidingORM6O6 effSlidingORW output
std::vector< std::vector< double > > MultiGaussianSmearing(std::vector< double > const &centralValue, std::vector< std::vector< double > > const &inputCovarianceMatrix, int n_multisims, CLHEP::RandGaussQ &GaussRandom)
do i e
BEGIN_PROLOG could also be cout