All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Chi2Sensitivity.cxx
Go to the documentation of this file.
1 #include "Covariance.h"
2 #include "Chi2Sensitivity.h"
3 
4 #include <TMatrixD.h>
5 #include <TDecompLU.h>
6 #include <TMatrixDSym.h>
7 
8 #include <TF1.h>
9 #include <TGraph.h>
10 #include <TCanvas.h>
11 #include <TGraph2D.h>
12 
13 #include <TFile.h>
14 #include <TVector3.h>
15 #include <TH1D.h>
16 #include <TH2D.h>
17 #include <TH3D.h>
18 #include <THStack.h>
19 #include <TROOT.h>
20 #include <TTree.h>
21 #include <TCanvas.h>
22 #include <TMath.h>
23 #include <Math/Integrator.h>
24 #include <TCanvas.h>
25 #include <core/Event.hh>
26 
27 namespace ana {
28 namespace SBNOsc {
29 
30 double osc_factor_L_integrated(double energy, double l_min, double l_max, double dm2) {
31  double f = 1.27 * dm2;
32  return (energy / (4 * f)) * (TMath::Sin(2 * f * l_min / energy) - TMath::Sin(2 * f * l_max / energy));
33 }
34 
35 // Oscillation function
36 double numu_to_numu(double x, double sin, double dm2) {
37 
38  // x is L/E, sin is sin^2(2theta) and dm2 is delta m^2
39  return 1 - sin * TMath::Power(TMath::Sin(1.27 * dm2 * x), 2);
40 }
41 
42 double numu_to_nue(double x, double sin, double dm2) {
43 
44  // x is L/E, sin is sin^2(2theta) and dm2 is delta m^2
45  return sin * TMath::Power(TMath::Sin(1.27 * dm2 * x), 2);
46 }
47 
48 double NumuOscillate(ROOT::Math::IntegratorOneDim &integrator, double l_min, double l_max, double e_min, double e_max, double dm2, double sinth) {
49  auto integrand = [l_min, l_max, dm2](double energy) { return osc_factor_L_integrated(energy, l_min, l_max, dm2); };
50  double integral = integrator.Integral(integrand, e_min, e_max);
51  double factor = (1. / 2. ) + integral / ( (l_max - l_min)*(e_max - e_min));
52  return 1 - sinth * factor;
53 }
54 
55 
56 // Oscillate Event counts
57 std::vector<double> Chi2Sensitivity::EventSample::Oscillate(double sinth, double dm2) const {
58  ROOT::Math::IntegratorOneDim integrator;
59  // return histogram binned by reco energy
60  std::vector<double> ret(fBkgCounts->GetNbinsX(), 0);
61  // iterate over signal bins
62  for (unsigned Ebin = 0; Ebin < fSignalCounts->GetNbinsY(); Ebin++) {
63  double energy = (fTrueEBins[Ebin] + fTrueEBins[Ebin+1]) / 2.;
64  for (unsigned Dbin = 0; Dbin < fSignalCounts->GetNbinsZ(); Dbin++) {
65  double distance = (fDistBins[Dbin] + fDistBins[Dbin+1]) / 2.;
66  for (unsigned bin = 0; bin < fSignalCounts->GetNbinsX(); bin++) {
67  double counts = fSignalCounts->GetBinContent(bin+1, Ebin+1, Dbin+1);
68 
69  if (fOscType == 1) {
70  counts *= numu_to_nue(distance/energy, sinth, dm2);
71  }
72  else if (fOscType == 2) {
73  counts *= NumuOscillate(integrator, fDistBins[Dbin], fDistBins[Dbin+1], fTrueEBins[Ebin], fTrueEBins[Ebin+1], dm2, sinth);
74  }
75 
76  ret[bin] += counts;
77  }
78  }
79  }
80 
81  return ret;
82 }
83 // Signal Event counts
84 std::vector<double> Chi2Sensitivity::EventSample::Signal() const {
85  // return histogram binned by reco energy
86  std::vector<double> ret(fBkgCounts->GetNbinsX(), 0);
87  // iterate over signal bins
88  for (unsigned Ebin = 0; Ebin < fSignalCounts->GetNbinsY(); Ebin++) {
89  for (unsigned Dbin = 0; Dbin < fSignalCounts->GetNbinsZ(); Dbin++) {
90  for (unsigned bin = 0; bin < fSignalCounts->GetNbinsX(); bin++) {
91  double counts = fSignalCounts->GetBinContent(bin+1, Ebin+1, Dbin+1);
92  ret[bin] += counts;
93  }
94  }
95  }
96 
97  return ret;
98 }
99 
100 // return vector of background counts
101 std::vector<double> Chi2Sensitivity::EventSample::Background() const {
102  std::vector<double> ret(fBkgCounts->GetNbinsX(), 0);
103  for (unsigned bin = 0; bin < fBkgCounts->GetNbinsX(); bin++) {
104  ret[bin] = fBkgCounts->GetBinContent(bin+1);
105  }
106  return ret;
107 }
108 
109 // Initialize
110 void Chi2Sensitivity::Initialize(fhicl::ParameterSet* config) {
111  //// Get parameters from config file
112  //// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
113 
114  // must have config
115  assert(config != NULL);
116 
117  // initialize covariance
118  fCovariance.Initialize(config);
119 
120  // Output directory
121  fhicl::ParameterSet pconfig = config->get<fhicl::ParameterSet>("Sensitivity");
122  fOutputFile = pconfig.get<std::string>("OutputFile", "output.root");
123 
124  // Get energy from covariance
125  fEnergyType = pconfig.get<std::string>("EnergyType", "Reco");
126 
127  // Further selection and rejection 'efficiencies'
128  fSelectionEfficiency = pconfig.get<double>("SelectionEfficiency", 1.0);
129  fBackgroundRejection = pconfig.get<double>("BackgroundRejection", 0.0);
130 
131  // Event Samples
132  std::vector<fhicl::ParameterSet> samples = \
133  config->get<std::vector<fhicl::ParameterSet> >("EventSamples");
134  for (const fhicl::ParameterSet& sample: samples) {
135  fEventSamples.emplace_back(sample);
136  }
137 
138  // Phase space parameters
139  fNumDm2 = pconfig.get<int>("NumDm2", 50);
140  fLogDm2Lims = pconfig.get<std::vector<double> >("LogDm2Lims");
141  fNumSin = pconfig.get<int>("NumSin", 50);
142  fLogSinLims = pconfig.get<std::vector<double> >("LogSinLims");
143 
144  // Whether to save stuff
145  fSavePDFs = pconfig.get<bool>("SavePDFs", true);
146  fSaveSignal = pconfig.get<bool>("SaveSignal", true);
147  fSaveBackground = pconfig.get<bool>("SaveBackground", true);
148 
149  if (pconfig.is_key_to_sequence("SaveOscillations")) {
150  std::vector<std::vector<double> > pairs = \
151  pconfig.get<std::vector<std::vector<double> > >("SaveOscillations");
152  for (size_t i=0; i<pairs.size(); i++) {
153  fSaveOscillations.push_back({ pairs[i].at(0), pairs[i].at(1) });
154  }
155  }
156 
157  // start at 0th event sample
158  fSampleIndex = 0;
159 }
160 
161 Chi2Sensitivity::EventSample::EventSample(const fhicl::ParameterSet& config) {
162  // scaling stuff
163  fName = config.get<std::string>("name", "");
164  fScalePOT = config.get<double>("ScalePOT", 0.);
165  fPOT = 0.;
166 
167  // setup detector stuff
168  std::vector<double> xlim = config.get<std::vector<double> >("DetX");
169  std::vector<double> ylim = config.get<std::vector<double> >("DetY");
170  std::vector<double> zlim = config.get<std::vector<double> >("DetZ");
171  fXlim[0] = xlim[0];
172  fXlim[1] = xlim[1];
173  fYlim[0] = ylim[0];
174  fYlim[1] = ylim[1];
175  fZlim[0] = zlim[0];
176  fZlim[1] = zlim[1];
177 
178  // oscillation type
179  fOscType = config.get<int>("OscType", 0);
180 
181  // bins of things
182  //
183  // Reco energy
184  std::vector<double> bins = config.get<std::vector<double> >("binlims");
185  for (auto const& bin: bins) {
186  fBins.push_back(bin);
187  }
188 
189  // True energy
190  std::vector<double> truee = config.get<std::vector<double> >("TrueELims");
191  double minTrueE = truee.at(0);
192  double maxTrueE = truee.at(1);
193  int numTrueEBinLimits = config.get<int>("NumTrueEBins", 1) + 1;
194  double trueE_binwidth = (maxTrueE - minTrueE) / numTrueEBinLimits;
195  for (int i = 0; i < numTrueEBinLimits; i ++) {
196  fTrueEBins.push_back(minTrueE + i * trueE_binwidth);
197  }
198 
199  // distance
200  //
201  // Take distance along z-axis as limits
202  int numBinsPerMeter = config.get<int>("NumDistanceBinsPerMeter", 1);
203  double numBinsPerCM = numBinsPerMeter * 0.01; // unit conversion
204 
205  // get beam center and baseline in cm
206  fBaseline = config.get<double>("Baseline");
207  fBeamCenterX = config.get<double>("BeamCenterX", 0.);
208  fBeamCenterY = config.get<double>("BeamCenterY", 0.);
209  fBeamFrontZ = config.get<double>("BeamFrontZ", 0.);
210 
211  // get full range of distances across detector
212  double detector_distance = sqrt((fZlim[1] - fZlim[0]) * (fZlim[1] - fZlim[0]) \
213  + (fXlim[1] - fXlim[0]) * (fXlim[1] - fXlim[0]) \
214  + (fYlim[1] - fYlim[0]) * (fYlim[1] - fYlim[0]));
215  // get full range of beam
216  // taken approximately from eyeballing MCFlux information
217  double beam_width = sqrt( 125. * 125. /* x */ + 125. * 125. /* y */ + 5500. * 5500. /* z */);
218  unsigned n_bins = (unsigned) ((detector_distance + beam_width) * numBinsPerCM) + 1;
219  unsigned n_limits = n_bins + 1;
220  double dist_binwidth = 1./numBinsPerCM;
221 
222  // minimum distance from decayed vertex to detector
223  // taken approximately from MCFlux info
224  double min_baseline = fBaseline - 5500.;
225 
226  for (unsigned i = 0; i < n_limits; i++) {
227  fDistBins.push_back((min_baseline + (i * dist_binwidth)) / 100000. /* cm -> km */);
228  }
229 
230  // scaling in reco energy bins
231  fEnergyBinScale = config.get<std::vector<double>>("energy_bin_scale", {});
232  if (fEnergyBinScale.size() == 0) {
233  fEnergyBinScale = std::vector<double>(fBins.size() - 1, 1.0);
234  }
235  else assert(fEnergyBinScale.size() == fBins.size() - 1);
236 
237  // setup histograms
238  fBkgCounts = new TH1D((fName + " Background").c_str(), (fName + " Background").c_str(), fBins.size() - 1, &fBins[0]);
239  fSignalCounts = new TH3D((fName + " Signal").c_str(), (fName + " Signal").c_str(),
240  fBins.size() - 1, &fBins[0], fTrueEBins.size() - 1, &fTrueEBins[0], fDistBins.size() - 1, &fDistBins[0]);
241 
242 }
243 
244 void Chi2Sensitivity::FileCleanup(TTree *eventTree) {
245  // cleanup for Covariance
246  fCovariance.FileCleanup(eventTree);
247 
248  // onto the next sample
249  fSampleIndex ++;
250 }
251 
253  fCovariance.ProcessSubRun(subrun);
254  fEventSamples[fSampleIndex].fPOT += subrun->totgoodpot;
255 }
256 
258  // have the covariance process the event
259  fCovariance.ProcessEvent(event);
260 
261  // Iterate over each interaction in the event
262  for (int n = 0; n < event->reco.size(); n++) {
263  unsigned truth_ind = event->reco[n].truth_index;
264 
265  // Get energy
266  int idx = event->reco[n].truth_index;
267  if (idx < 0 || idx > event->truth.size()) {
268  continue;
269  }
270  double true_nuE = event->truth[idx].neutrino.energy;
271  double nuE = 0;
272  if (fEnergyType == "CCQE") {
273  nuE = event->truth[truth_ind].neutrino.eccqe;
274  } else if (fEnergyType == "True") {
275  nuE = true_nuE;
276  } else if (fEnergyType == "Reco") {
277  nuE = event->reco[n].reco_energy;
278  }
279 
280  // get distance travelled from decay vertex
281  // parent decay vertex
282  TVector3 p_decay_vtx = event->truth[truth_ind].neutrino.parentDecayVtx;
283  TVector3 neutrino_vtx = event->truth[truth_ind].neutrino.position;
284 
285  double dz = fEventSamples[fSampleIndex].fBaseline - p_decay_vtx.Z() + neutrino_vtx.Z() - fEventSamples[fSampleIndex].fBeamFrontZ;
286  double dy = p_decay_vtx.Y() - neutrino_vtx.Y() + fEventSamples[fSampleIndex].fBeamCenterY;
287  double dx = p_decay_vtx.X() - neutrino_vtx.X() + fEventSamples[fSampleIndex].fBeamCenterX;
288  double dist = sqrt(dx*dx + dy*dy + dz*dz) / 100000. /* cm -> km */;
289 
290  // check if energy is within bounds
292  continue;
293  }
294  else if (nuE < fEventSamples[fSampleIndex].fTrueEBins[0] ||
295  nuE > fEventSamples[fSampleIndex].fTrueEBins[fEventSamples[fSampleIndex].fTrueEBins.size()-1]) {
296  std::cout << std::endl << "NUE IN RANGE, TRUE E NOT!!! nuE = " << nuE << " and true_nuE = " << true_nuE << std::endl;
297  continue;
298  }
299  else if (dist < fEventSamples[fSampleIndex].fDistBins[0] ||
300  dist > fEventSamples[fSampleIndex].fDistBins[fEventSamples[fSampleIndex].fDistBins.size() -1]) {
301  std::cout << std::endl << "NUE IN RANGE, DISTANCE NOT!! nuE = " << nuE << " and distance = " << dist << std::endl;
302  std::cout << "DIST MIN: " << fEventSamples[fSampleIndex].fDistBins[0] << std::endl;
303  std::cout << "DIST MAX: " << fEventSamples[fSampleIndex].fDistBins[fEventSamples[fSampleIndex].fDistBins.size() -1] << std::endl;
304  continue;
305  }
306 
307  // Apply selection (or rejection) efficiencies
308  int isCC = event->truth[truth_ind].neutrino.iscc;
309  // double wgt = isCC*(fSelectionEfficiency) + (1-isCC)*(1 - fBackgroundRejection);
310  // and scale weight
311  // wgt *= fEventSamples[fSampleIndex].fScaleFactor;
312  // apply uniform weights
313  // for (auto const &key: fUniformWeights) {
314  // wgt *= event->truth[truth_ind].weights.at(key)[0];
315  // }
316  double wgt = event->reco[n].weight;
317  if (fEventSamples[fSampleIndex].fScalePOT > 0) {
318  wgt *= fEventSamples[fSampleIndex].fScalePOT / fEventSamples[fSampleIndex].fPOT;
319  }
320 
321  // fill in hitograms
322  //
323  // Signal
324  if (isCC) {
325  fEventSamples[fSampleIndex].fSignalCounts->Fill(nuE, true_nuE, dist, wgt);
326  }
327  // background
328  else {
329  fEventSamples[fSampleIndex].fBkgCounts->Fill(nuE, wgt);
330  }
331  }
332 }
333 
334 // apply reco energy bin scaling
336  for (int sample = 0; sample < fEventSamples.size(); sample++) {
337  for (int i = 1; i < fEventSamples[sample].fSignalCounts->GetNbinsX()+1; i++) {
338  double scale = fEventSamples[sample].fEnergyBinScale[i-1];
339  for (int j = 1; j < fEventSamples[sample].fSignalCounts->GetNbinsY()+1; j++) {
340  for (int k = 1; k < fEventSamples[sample].fSignalCounts->GetNbinsZ()+1; k++) {
341  double content = fEventSamples[sample].fSignalCounts->GetBinContent(i, j, k);
342  //std::cout << "pre sample: " << sample << " bin content: " << fEventSamples[sample].fSignalCounts->GetBinContent(i);
343  fEventSamples[sample].fSignalCounts->SetBinContent(i, j, k, content * scale);
344  //std::cout << "post sample: " << sample << " bin content: " << fEventSamples[sample].fSignalCounts->GetBinContent(i);
345  }
346  }
347  }
348 
349  for (int i = 1; i < fEventSamples[sample].fBkgCounts->GetNbinsX()+1; i++) {
350  double scale = fEventSamples[sample].fEnergyBinScale[i-1];
351  double content = fEventSamples[sample].fBkgCounts->GetBinContent(i);
352  fEventSamples[sample].fBkgCounts->SetBinContent(i, content * scale);
353  }
354  }
355 }
356 
357 
359 
360  //// Invert Error Matrix
361  //// ~~~~~~~~~~~~~~~~~~~
362 
363  std::cout << std::endl << "Inverting full error matrix, E_{ij}..." << std::endl;
364 
365  // Create error (statistical and systematic) matrix
366  //
367  // Take covariance matrix from Covariance calculator
368  TMatrixDSym E_mat = fCovariance.CovarianceMatrix();
369  // Invert it
370  TMatrixD E_inv = E_mat.Invert();
371  // Find a way to stop code if the matrix doesn't invert!
372  // Check error message? See if E_inv exists?
373 
374  std::cout << " Inverted." << std::endl;
375 
376 
377  //// Get chi squareds
378  //// ~~~~~~~~~~~~~~~~
379 
380  // Phase space of oscillation parameters
381  for (int i = 0; i < fNumSin; i++) {
382  sin2theta.push_back(TMath::Power(10, fLogSinLims[0] + i*(fLogSinLims[1] - fLogSinLims[0])/(fNumSin-1)));
383  }
384  for (int j = 0; j < fNumDm2; j++) {
385  dm2.push_back(TMath::Power(10, fLogDm2Lims[0] + j*(fLogDm2Lims[1] - fLogDm2Lims[0])/(fNumDm2-1)));
386  }
387 
388  // Loop over phase space calculating Chisq
389  clock_t startchi = clock();
390  std::cout << std::endl << "Calculating chi squareds..." << std::endl;
391 
392  double minchisq = 1e99;
393  std::vector <double> chisq_dm2(fNumDm2, 0);
394  std::vector <std::vector <double> > chisq(fNumSin, chisq_dm2);
395 
396  std::vector<double> signal; // non-oscillated signal
397  // push all event samples into the vector
398  for (auto const &sample: fEventSamples) {
399  // flatten the signal
400  std::vector<double> this_signal = sample.Signal();
401  signal.insert(signal.end(), this_signal.begin(), this_signal.end());
402  }
403 
404  for (int j = 0; j < fNumDm2; j++) {
405  std::vector<std::vector<double>> oscillated; // oscilalted signal at sin2==1
406 
407  // push all event samples into the vector
408  for (auto const &sample: fEventSamples) {
409  // oscillate each event sample w/ sin == 1
410  oscillated.push_back(sample.Oscillate(1., dm2[j]));
411  }
412 
413  // oscillated signal for general sin2 (set in loop below)
414  std::vector<double> sin2_oscillated(signal.size(), 0);
415 
416  for (int i = 0; i < fNumSin; i++) {
417  // Scale the oscillated samples based on the sin2 value and flatten them
418  unsigned count_ind = 0;
419  for (unsigned sample_ind = 0; sample_ind < oscillated.size(); sample_ind++) {
420  for (unsigned bin_ind = 0; bin_ind < oscillated[sample_ind].size(); bin_ind++) {
421  // No oscillation
422  if (fEventSamples[sample_ind].fOscType == 0) {
423  sin2_oscillated[count_ind] = signal[count_ind];
424  }
425  // numu -> nue
426  else if (fEventSamples[sample_ind].fOscType == 1) {
427  sin2_oscillated[count_ind] = sin2theta[i] * oscillated[sample_ind][bin_ind];
428  }
429  // numu -> numu
430  else if (fEventSamples[sample_ind].fOscType == 2) {
431  // These two formulas are equivalent:
432  // 1.
433  // sin2_oscillated[count_ind] = signal[count_ind] -
434  // sin2theta[i] * (signal[count_ind] - oscillated[sample_ind][bin_ind]);
435  // 2.
436  // sin2_oscillated[count_ind] = signal[count_ind] * (1 - sin2theta[i]) +
437  // sin2theta[i] * oscillated[sample_ind][bin_ind];
438  //
439  // Use the second one b.c. it reduces possible floating point error
440 
441  sin2_oscillated[count_ind] = signal[count_ind] * (1 - sin2theta[i]) +
442  sin2theta[i] * oscillated[sample_ind][bin_ind];
443 
444  }
445 
446  // update count ind
447  count_ind ++;
448  }
449  }
450  assert(count_ind == signal.size());
451 
452  // Calculate chisq for sin2th = 1
453  for (int k = 0; k < signal.size(); k++) {
454  for (int l = 0; l < signal.size(); l++) {
455  chisq[i][j] += (signal[k] - sin2_oscillated[k]) * (signal[l] - sin2_oscillated[l]) * E_inv[k][l];
456  }
457  }
458 
459  // Check if min chisq
460  if (chisq[i][j] < minchisq) {
461  minchisq = chisq[i][j];
462  }
463 
464  }
465  }
466 
467  clock_t endchi = clock();
468  clock_t tickschi = endchi - startchi; // in n of ticks
469  double timechi = tickschi / (double) CLOCKS_PER_SEC; // make into secs
470 
471  std::cout << " Done in " << timechi << "s. " << std::endl;
472 
473 
474  // Gen TGraph2D for output
475  chisqplot = new TGraph2D();
476  for (int i = 0; i < fNumSin; i++) {
477  for (int j = 0; j < fNumDm2; j++) {
478  chisqplot->SetPoint(i*fNumSin + j, TMath::Log10(sin2theta[i]), TMath::Log10(dm2[j]), chisq[i][j]);
479  }
480  }
481 
482  // Get differences
483  chisq_diffs = chisq;
484  for (int i = 0; i < fNumSin; i++) {
485  for (int j = 0; j < fNumDm2; j++) {
486  chisq_diffs[i][j] -= minchisq;
487  }
488  }
489 
490 }
491 
493 
494  //// Get contours
495  //// ~~~~~~~~~~~~
496 
497  /*
498  Note: I'm just copying my own code I'd written to get contours. I've heard that there is some
499  function on TH2Ds that does it automatically but haven't used it. This one is pretty fast so
500  I'm leaving it in, at least for now.
501  */
502 
503  clock_t startcont = clock();
504  std::cout << std::endl << "Getting contours..." << std::endl;
505 
506  // Get contours
507  double target;
508  std::vector <double> target_dchisq = {1.64, 7.75, 23.40}, corners(4, 0), twozeros(2, 0);
509  std::vector <std::vector <double> > contour, sin_contour(target_dchisq.size()), dm2_contour(target_dchisq.size()), vecof2vecs(fNumDm2, twozeros);
510  std::vector <std::vector <std::vector <double> > > box_minmax(fNumSin, vecof2vecs);
511  for (int k = 0; k < target_dchisq.size(); k++){
512 
513  target = target_dchisq[k];
514 
515  // Initialise box_minmax
516  for (int i = 0; i < fNumSin-1; i++) {
517  for (int j = 0; j < fNumDm2-1; j++) {
518  box_minmax[i][j] = {0, 0};
519  }
520  }
521 
522  // Fill box_minmax out
523  for (int i = 0; i < fNumSin-1; i++) {
524  for (int j = 0; j < fNumDm2-1; j++) {
525 
526  corners = {chisq_diffs[i][j], chisq_diffs[i+1][j], chisq_diffs[i][j+1], chisq_diffs[i+1][j+1]};
527  box_minmax[i][j] = {corners[0], corners[0]};
528  for (int l = 1; l < 4; l++) {
529  if (corners[l] > box_minmax[i][j][1]) {
530  box_minmax[i][j][1] = corners[l];
531  } else if (corners[l] < box_minmax[i][j][0]) {
532  box_minmax[i][j][0] = corners[l];
533  }
534  }
535 
536  }
537  }
538 
539  // Get the contour
540  contour.clear();
541  for (int i = 0; i < fNumSin-1; i++) {
542  for (int j = 0; j < fNumDm2-1; j++) {
543 
544  if ((target >= box_minmax[i][j][0]) && (target <= box_minmax[i][j][1])) {
545  contour.push_back({(sin2theta[i] + sin2theta[i+1])/2, (dm2[j] + dm2[j+1])/2});
546  }
547 
548  }
549  }
550 
551  // Save the contour
552  for (int j = 0; j < contour.size(); j++) {
553  sin_contour[k].push_back(contour[j][0]);
554  dm2_contour[k].push_back(contour[j][1]);
555  }
556 
557  }
558 
559  clock_t endcont = clock();
560  clock_t tickscont = endcont - startcont; // in n of ticks
561  double timecont = tickscont / (double) CLOCKS_PER_SEC; // make into secs
562 
563  std::cout << " Done in " << timecont << "s." << std::endl;
564 
565  // Create TGraphs
566  std::vector <TGraph*> graphs;
567  for (int i = 0; i < sin_contour.size(); i++) {
568 
569  graphs.push_back(new TGraph());
570 
571  for (int j = 0; j < sin_contour[i].size(); j++) {
572  graphs[i]->SetPoint(j, sin_contour[i][j], dm2_contour[i][j]);
573  }
574 
575  }
576 
577 
578  //// Output stuff
579  //// ~~~~~~~~~~~~
580 
581  contour_90pct = graphs[0];
582  contour_3sigma = graphs[1];
583  contour_5sigma = graphs[2];
584 
585 }
586 
588 
589  // Wite to file
590  TFile* chi2file = TFile::Open(fOutputFile.c_str(), "recreate");
591  assert(chi2file && chi2file->IsOpen());
592 
593  if (fSavePDFs) {
594  contour_90pct->SetName("90pct"); contour_90pct->Write();
595  contour_3sigma->SetName("3sigma"); contour_3sigma->Write();
596  contour_5sigma->SetName("5sigma"); contour_5sigma->Write();
597 
598  chisqplot->SetName("chisq"); chisqplot->Write();
599  }
600 
601  // save histos
602  if (fSaveBackground) {
603  for (auto const &sample: fEventSamples) {
604  sample.fBkgCounts->Write();
605  }
606  }
607 
608  if (fSaveSignal) {
609  for (auto const &sample: fEventSamples) {
610  sample.fSignalCounts->Write();
611  }
612  }
613 
614  for (auto const &osc_vals: fSaveOscillations) {
615  for (auto const &sample: fEventSamples) {
616  std::string name = sample.fName + " sin2th: " + std::to_string(osc_vals[0]) + " dm2: " + std::to_string(osc_vals[1]);
617  TH1D *hist = new TH1D(name.c_str(), name.c_str(), sample.fBins.size()-1, &sample.fBins[0]);
618  std::vector<double> oscillated = sample.Oscillate(osc_vals[0], osc_vals[1]);
619  for (unsigned i = 0; i < oscillated.size(); i++) {
620  hist->SetBinContent(i+1, oscillated[i]);
621  }
622  hist->Write();
623  }
624  }
625 
626  chi2file->Close();
627 
628 }
629 
630 } // namespace SBNOsc
631 } // namespace ana
632 
634 
TH1D * fBkgCounts
Background count Histogram.
process_name opflash particleana ie x
std::vector< double > Background() const
std::vector< std::vector< double > > chisq_diffs
Container for chi2 values.
void Initialize(fhicl::ParameterSet *config)
TMatrixDSym CovarianceMatrix()
Definition: Covariance.cxx:407
void Initialize(fhicl::ParameterSet *config)
Definition: Covariance.cxx:76
void FileCleanup(TTree *eventTree)
std::vector< double > fDistBins
Distance bin limits.
process_name opflashCryoW ana
EventSample(const fhicl::ParameterSet &config)
std::vector< double > Signal() const
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
std::vector< double > sin2theta
std::vector< double > dm2
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
std::vector< std::array< double, 2 > > fSaveOscillations
std::vector< double > fLogDm2Lims
double numu_to_nue(double x, double sin, double dm2)
#define DECLARE_SBN_POSTPROCESSOR(classname)
counts_as<> counts
Number of ADC counts, represented by signed short int.
Definition: electronics.h:116
std::vector< double > fLogSinLims
float totgoodpot
Definition: SubRun.hh:40
double NumuOscillate(ROOT::Math::IntegratorOneDim &integrator, double l_min, double l_max, double e_min, double e_max, double dm2, double sinth)
The standard subrun data definition.
Definition: SubRun.hh:23
fBins({binsX, binsY})
void ProcessSubRun(const SubRun *subrun)
Definition: Covariance.cxx:147
The standard event data definition.
Definition: Event.hh:228
std::vector< double > fTrueEBins
True energy bin limits.
std::vector< EventSample > fEventSamples
int fOscType
Oscilaltion type: 0 == None, 1 == numu -&gt; nue, 2 == numu -&gt; numu.
void ProcessEvent(const event::Event *event)
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
std::string to_string(WindowPattern const &pattern)
double osc_factor_L_integrated(double energy, double l_min, double l_max, double dm2)
then echo fcl name
Sample_t fBaseline
Waveform baseline [ADC counts].
void ProcessSubRun(const SubRun *subrun)
TH3D * fSignalCounts
Signal Count Histogram.
pdgs k
Definition: selectors.fcl:22
void FileCleanup(TTree *eventTree)
Definition: Covariance.cxx:257
std::vector< double > Oscillate(double sinth, double dm2) const
void ProcessEvent(const event::Event *event)
Definition: Covariance.cxx:151
BEGIN_PROLOG could also be cout
std::vector< Interaction > truth
All truth interactions.
Definition: Event.hh:232
double numu_to_numu(double x, double sin, double dm2)