AbsCexDriver.cxx
Go to the documentation of this file.
1 #include "AbsCexDriver.h"
2 #include "TCanvas.h"
3 #include "THStack.h"
4 #include "TGraphAsymmErrors.h"
5 #include "TLegend.h"
6 #include "TRandom3.h"
7 #include "TMath.h"
8 #include "TProfile.h"
9 #include "Math/ProbFunc.h"
11 
12 #include <iomanip>
13 #include <iostream>
14 #include <numeric>
15 
16 #include "ThinSliceDriverFactory.h"
18 
20 
22  const fhicl::ParameterSet & extra_options)
23  : ThinSliceDriver(extra_options),
24  fEnergyFix(extra_options.get<double>("EnergyFix")),
25  fDoEnergyFix(extra_options.get<bool>("DoEnergyFix")),
26  fPitch(extra_options.get<double>("WirePitch")),
27  fZ0(extra_options.get<double>("Z0")),
28  fMultinomial(extra_options.get<bool>("Multinomial", true)),
29  fEndZCut(extra_options.get<double>("EndZCut")),
30  fSliceMethod(extra_options.get<std::string>("SliceMethod")) {
31  if (fSliceMethod == "Alt") {
32  fIn = new TFile("end_slices.root", "OPEN");
33  fEndSlices = (TH2D*)fIn->Get("h2D")->Clone();
34  for (int i = 1; i <= 735; ++i) {
35  fMeans[i] = fEndSlices->ProjectionY("", i, i)->GetMean();
36  }
37  }
38  else if (fSliceMethod == "Traj") {
39  fSliceCut = extra_options.get<int>("SliceCut");
40  fTrajZStart = extra_options.get<double>("TrajZStart");
41  }
42  else {
43  fSliceCut = std::floor((fEndZCut - (fZ0 - fPitch/2.))/fPitch);
44  }
45 
46  fSkipFirstLast = extra_options.get<bool>("SkipFirstLast", false);
47 }
48 
50  TTree * tree, std::vector<ThinSliceEvent> & events,
51  std::vector<ThinSliceEvent> & fake_data_events,
52  int & split_val, const bool & do_split) {
53  std::cout << "Filling MC Events" << std::endl;
54 
55  int sample_ID, selection_ID, event, run, subrun;
56  int true_beam_PDG;
57  double true_beam_interactingEnergy, reco_beam_interactingEnergy;
58  double true_beam_endP, true_beam_mass, true_beam_endZ;
59  double reco_beam_endZ, true_beam_startP;
60  double beam_inst_P;
61  std::vector<double> * reco_beam_incidentEnergies = 0x0,
62  * true_beam_incidentEnergies = 0x0,
63  * true_beam_traj_Z = 0x0,
64  * true_beam_traj_KE = 0x0,
65  * reco_daughter_track_thetas = 0x0,
66  * reco_daughter_track_scores = 0x0;
67  std::vector<int> * true_beam_slices = 0x0;
68  tree->SetBranchAddress("event", &event);
69  tree->SetBranchAddress("subrun", &subrun);
70  tree->SetBranchAddress("run", &run);
71 
72  tree->SetBranchAddress("true_beam_PDG", &true_beam_PDG);
73 
74  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
75  tree->SetBranchAddress("selection_ID", &selection_ID);
76  tree->SetBranchAddress("true_beam_interactingEnergy",
77  &true_beam_interactingEnergy);
78  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
79  tree->SetBranchAddress("true_beam_endZ", &true_beam_endZ);
80  tree->SetBranchAddress("true_beam_mass", &true_beam_mass);
81  tree->SetBranchAddress("reco_beam_interactingEnergy",
82  &reco_beam_interactingEnergy);
83  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
84  tree->SetBranchAddress("reco_beam_incidentEnergies",
85  &reco_beam_incidentEnergies);
86  tree->SetBranchAddress("true_beam_incidentEnergies",
87  &true_beam_incidentEnergies);
88  tree->SetBranchAddress("true_beam_slices",
89  &true_beam_slices);
90  tree->SetBranchAddress("true_beam_startP", &true_beam_startP);
91  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
92  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
93  std::vector<double> * calibrated_dQdX = 0x0, * beam_EField = 0x0,
94  * track_pitch = 0x0;
95  tree->SetBranchAddress("reco_beam_calibrated_dQdX_SCE", &calibrated_dQdX);
96  tree->SetBranchAddress("reco_beam_EField_SCE", &beam_EField);
97  tree->SetBranchAddress("reco_beam_TrkPitch_SCE", &track_pitch);
98  tree->SetBranchAddress("beam_inst_P", &beam_inst_P);
99  tree->SetBranchAddress("reco_daughter_allTrack_Theta", &reco_daughter_track_thetas);
100  tree->SetBranchAddress("reco_daughter_PFP_trackScore_collection",
101  &reco_daughter_track_scores);
102 
103  std::vector<double> * g4rw_alt_primary_plus_sigma_weight = 0x0,
104  * g4rw_alt_primary_minus_sigma_weight = 0x0,
105  * g4rw_full_primary_plus_sigma_weight = 0x0,
106  * g4rw_full_primary_minus_sigma_weight = 0x0;
107  std::vector<std::vector<double>> * g4rw_primary_grid_weights = 0x0,
108  * g4rw_full_grid_weights = 0x0,
109  * g4rw_full_grid_proton_weights = 0x0;
110  tree->SetBranchAddress("g4rw_alt_primary_plus_sigma_weight",
111  &g4rw_alt_primary_plus_sigma_weight);
112  tree->SetBranchAddress("g4rw_alt_primary_minus_sigma_weight",
113  &g4rw_alt_primary_minus_sigma_weight);
114  tree->SetBranchAddress("g4rw_full_primary_plus_sigma_weight",
115  &g4rw_full_primary_plus_sigma_weight);
116  tree->SetBranchAddress("g4rw_full_primary_minus_sigma_weight",
117  &g4rw_full_primary_minus_sigma_weight);
118  tree->SetBranchAddress("g4rw_full_grid_weights", &g4rw_full_grid_weights);
119  tree->SetBranchAddress("g4rw_full_grid_proton_weights", &g4rw_full_grid_proton_weights);
120 
121  tree->SetBranchAddress("g4rw_primary_grid_weights",
122  &g4rw_primary_grid_weights);
123 
124  std::vector<std::vector<double>> * daughter_dQdXs = 0x0,
125  * daughter_resRanges = 0x0,
126  * daughter_EFields = 0x0;
127  tree->SetBranchAddress(
128  "reco_daughter_allTrack_calibrated_dQdX_SCE", &daughter_dQdXs);
129  tree->SetBranchAddress(
130  "reco_daughter_allTrack_resRange_SCE", &daughter_resRanges);
131  tree->SetBranchAddress(
132  "reco_daughter_allTrack_EField_SCE", &daughter_EFields);
133  bool has_pi0_shower;
134  tree->SetBranchAddress("has_shower_dist_energy", &has_pi0_shower);
135 
136  int nentries = tree->GetEntries();
137  if (do_split) {
138  split_val = tree->GetEntries()/2;
139  std::cout << "Note: Splitting MC in half. " <<
140  split_val << "/" << tree->GetEntries() <<std::endl;
141  nentries = split_val;
142  }
143 
144  std::vector<double> xs;
145  for (size_t i = 0; i < 20; ++i) {xs.push_back(.1*(1 + i));}
146 
147  for (int i = 0; i < nentries; ++i) {
148  tree->GetEntry(i);
149 
150  events.push_back(ThinSliceEvent(event, subrun, run));
151  events.back().SetSampleID(sample_ID);
152  events.back().SetSelectionID(selection_ID);
153  events.back().SetTrueInteractingEnergy(true_beam_interactingEnergy);
154  events.back().SetRecoInteractingEnergy(reco_beam_interactingEnergy);
155  events.back().SetTrueEndP(true_beam_endP);
156  events.back().SetTrueEndZ(true_beam_endZ);
157  events.back().SetTrueStartP(true_beam_startP);
158  events.back().SetTrueMass(true_beam_mass);
159  events.back().SetRecoEndZ(reco_beam_endZ);
160 
161  events.back().SetRecoIncidentEnergies(*reco_beam_incidentEnergies);
162  events.back().SetTrueIncidentEnergies(*true_beam_incidentEnergies);
163  events.back().SetTrueTrajZ(*true_beam_traj_Z);
164  events.back().SetTrueTrajKE(*true_beam_traj_KE);
165  events.back().SetTrueSlices(*true_beam_slices);
166  events.back().SetdQdXCalibrated(*calibrated_dQdX);
167  events.back().SetEField(*beam_EField);
168  events.back().SetTrackPitch(*track_pitch);
169  events.back().SetBeamInstP(beam_inst_P);
170  events.back().SetPDG(true_beam_PDG);
171  events.back().SetRecoDaughterTrackThetas(*reco_daughter_track_thetas);
172  events.back().SetRecoDaughterTrackScores(*reco_daughter_track_scores);
173  events.back().SetHasPi0Shower(has_pi0_shower);
174  events.back().MakeG4RWBranch("g4rw_alt_primary_plus_sigma_weight",
175  *g4rw_alt_primary_plus_sigma_weight);
176  events.back().MakeG4RWBranch("g4rw_alt_primary_minus_sigma_weight",
177  *g4rw_alt_primary_minus_sigma_weight);
178  events.back().MakeG4RWBranch("g4rw_full_primary_plus_sigma_weight",
179  *g4rw_full_primary_plus_sigma_weight);
180  events.back().MakeG4RWBranch("g4rw_full_primary_minus_sigma_weight",
181  *g4rw_full_primary_minus_sigma_weight);
182  for (size_t j = 0; j < daughter_dQdXs->size(); ++j) {
183  events.back().AddRecoDaughterTrackdQdX((*daughter_dQdXs)[j]);
184  events.back().AddRecoDaughterTrackResRange((*daughter_resRanges)[j]);
185  events.back().AddRecoDaughterEField((*daughter_EFields)[j]);
186  }
187 
188  for (size_t j = 0; j < g4rw_primary_grid_weights->size(); ++j) {
189  std::string name_full = "g4rw_full_grid_weights_" + std::to_string(j);
190  //std::cout << "Adding " << name_full << std::endl;
191  //if (!(*g4rw_full_grid_weights)[j].size())
192  // std::cout << "Adding empty branch " << event << " " << run << " " << subrun << std::endl;
193  events.back().MakeG4RWBranch(name_full, (*g4rw_full_grid_weights)[j]);
194  //events.back().MakeG4RWSpline(name_full);
195 
196  std::string name_primary = "g4rw_primary_grid_weights_" +
197  std::to_string(j);
198  //std::cout << "Adding " << name_primary << std::endl;
199  //if (!(*g4rw_primary_grid_weights)[j].size())
200  // std::cout << "Adding empty branch " << event << " " << run << " " << subrun << std::endl;
201  events.back().MakeG4RWBranch(name_primary,
202  (*g4rw_primary_grid_weights)[j]);
203  }
204  events.back().MakeG4RWBranch("g4rw_full_grid_proton_weights",
205  (*g4rw_full_grid_proton_weights)[0]);
206  }
207 
208  //if (fSplitMC) {
209  for (int i = split_val; i < tree->GetEntries(); ++i) {
210  tree->GetEntry(i);
211 
212  fake_data_events.push_back(ThinSliceEvent(event, subrun, run));
213  fake_data_events.back().SetSampleID(sample_ID);
214  fake_data_events.back().SetSelectionID(selection_ID);
215  fake_data_events.back().SetTrueInteractingEnergy(true_beam_interactingEnergy);
216  fake_data_events.back().SetRecoInteractingEnergy(reco_beam_interactingEnergy);
217  fake_data_events.back().SetTrueEndP(true_beam_endP);
218  fake_data_events.back().SetTrueEndZ(true_beam_endZ);
219  fake_data_events.back().SetTrueStartP(true_beam_startP);
220  fake_data_events.back().SetTrueMass(true_beam_mass);
221  fake_data_events.back().SetRecoEndZ(reco_beam_endZ);
222 
223  fake_data_events.back().SetRecoIncidentEnergies(*reco_beam_incidentEnergies);
224  fake_data_events.back().SetTrueIncidentEnergies(*true_beam_incidentEnergies);
225  fake_data_events.back().SetTrueTrajZ(*true_beam_traj_Z);
226  fake_data_events.back().SetTrueTrajKE(*true_beam_traj_KE);
227  fake_data_events.back().SetTrueSlices(*true_beam_slices);
228  fake_data_events.back().SetdQdXCalibrated(*calibrated_dQdX);
229  fake_data_events.back().SetEField(*beam_EField);
230  fake_data_events.back().SetTrackPitch(*track_pitch);
231  fake_data_events.back().SetBeamInstP(beam_inst_P);
232  fake_data_events.back().SetPDG(true_beam_PDG);
233  fake_data_events.back().SetRecoDaughterTrackThetas(*reco_daughter_track_thetas);
234  fake_data_events.back().SetRecoDaughterTrackScores(*reco_daughter_track_scores);
235  fake_data_events.back().SetHasPi0Shower(has_pi0_shower);
236  fake_data_events.back().MakeG4RWBranch("g4rw_alt_primary_plus_sigma_weight",
237  *g4rw_alt_primary_plus_sigma_weight);
238  fake_data_events.back().MakeG4RWBranch("g4rw_alt_primary_minus_sigma_weight",
239  *g4rw_alt_primary_minus_sigma_weight);
240  fake_data_events.back().MakeG4RWBranch("g4rw_full_primary_plus_sigma_weight",
241  *g4rw_full_primary_plus_sigma_weight);
242  fake_data_events.back().MakeG4RWBranch("g4rw_full_primary_minus_sigma_weight",
243  *g4rw_full_primary_minus_sigma_weight);
244  for (size_t j = 0; j < daughter_dQdXs->size(); ++j) {
245  fake_data_events.back().AddRecoDaughterTrackdQdX((*daughter_dQdXs)[j]);
246  fake_data_events.back().AddRecoDaughterTrackResRange((*daughter_resRanges)[j]);
247  fake_data_events.back().AddRecoDaughterEField((*daughter_EFields)[j]);
248  }
249 
250  for (size_t j = 0; j < g4rw_primary_grid_weights->size(); ++j) {
251  std::string name_full = "g4rw_full_grid_weights_" + std::to_string(j);
252  //std::cout << "Adding " << name_full << std::endl;
253  //if (!(*g4rw_full_grid_weights)[j].size())
254  // std::cout << "Adding empty branch " << event << " " << run << " " << subrun << std::endl;
255  fake_data_events.back().MakeG4RWBranch(name_full, (*g4rw_full_grid_weights)[j]);
256 
257  std::string name_primary = "g4rw_primary_grid_weights_" +
258  std::to_string(j);
259  //std::cout << "Adding " << name_primary << std::endl;
260  //if (!(*g4rw_primary_grid_weights)[j].size())
261  // std::cout << "Adding empty branch " << event << " " << run << " " << subrun << std::endl;
262  fake_data_events.back().MakeG4RWBranch(name_primary,
263  (*g4rw_primary_grid_weights)[j]);
264  }
265  fake_data_events.back().MakeG4RWBranch("g4rw_full_grid_proton_weights",
266  (*g4rw_full_grid_proton_weights)[0]);
267  }
268  //}
269 
270  std::cout << "Filled MC Events" << std::endl;
271 
272 
273 }
274 
276  const std::vector<ThinSliceEvent> & events,
277  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
278  const std::map<int, bool> & signal_sample_checks,
279  std::map<int, double> & nominal_fluxes,
280  std::map<int, std::vector<std::vector<double>>> & fluxes_by_sample,
281  std::vector<double> & beam_energy_bins) {
282 
283  for (size_t i = 0; i < events.size(); ++i) {
284  const ThinSliceEvent & event = events.at(i);
285 
286  int sample_ID = event.GetSampleID();
287  int selection_ID = event.GetSelectionID();
288 
289  double true_beam_interactingEnergy = event.GetTrueInteractingEnergy();
290  double reco_beam_interactingEnergy = event.GetRecoInteractingEnergy();
291  double true_beam_endP = event.GetTrueEndP();
292  double reco_beam_endZ = event.GetRecoEndZ();
293  double true_beam_startP = event.GetTrueStartP();
294 
295  const std::vector<double> & reco_beam_incidentEnergies
296  = event.GetRecoIncidentEnergies();
297  const std::vector<double> & true_beam_incidentEnergies
298  = event.GetTrueIncidentEnergies();
299  const std::vector<double> & true_beam_traj_Z
300  = event.GetTrueTrajZ();
301  const std::vector<double> & true_beam_traj_KE
302  = event.GetTrueTrajKE();
303  const std::vector<int> & true_beam_slices
304  = event.GetTrueSlices();
305 
306  double end_energy = true_beam_interactingEnergy;
307  if (fSliceMethod == "Traj") {
308  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
309  }
310  else if (fSliceMethod == "E") {
311  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
312  }
313  else if (fSliceMethod == "Alt") {
314  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z./*->*/back());
315  if (bin > 0)
316  end_energy = fMeans.at(bin);
317  }
318 
319  if (samples.find(sample_ID) == samples.end()) {
320  std::cout << "Warning: skipping sample " << sample_ID << std::endl;
321  continue;
322  }
323 
324  //Build the true incident energy vector based on the slice cut
325  std::vector<double> good_true_incEnergies = MakeTrueIncidentEnergies(
326  true_beam_traj_Z, true_beam_traj_KE, true_beam_slices,
327  true_beam_incidentEnergies);
328  int bin = GetBeamBin(beam_energy_bins, true_beam_startP);
329 
330 
331  std::vector<ThinSliceSample> & samples_vec = samples.at(sample_ID)[bin];
332  bool is_signal = signal_sample_checks.at(sample_ID);
333 
334  ThinSliceSample * this_sample = 0x0;
335  if (!is_signal) {
336  this_sample = &samples_vec.at(0);
337 
338  fluxes_by_sample[sample_ID][bin][0] += 1.;
339  }
340  else {
341  //Iterate through the true bins and find the correct one
342  bool found = false;
343  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
344  ThinSliceSample & sample = samples_vec.at(j);
345  if (sample.CheckInSignalRange(end_energy)) {
346  this_sample = &sample;
347 
348  fluxes_by_sample[sample_ID][bin][j] += 1.;
349  found = true;
350  break;
351  }
352  }
353  if (!found) {
354  //over/underflow here
355  if (end_energy <= samples_vec[1].RangeLowEnd()) {
356  this_sample = &samples_vec[0];
357 
358  fluxes_by_sample[sample_ID][bin][0] += 1.;
359  }
360  else if (end_energy >
361  samples_vec[samples_vec.size()-2].RangeHighEnd()) {
362  this_sample = &samples_vec.back();
363  fluxes_by_sample[sample_ID][bin].back() += 1.;
364  }
365  else {
366  std::cout << "Warning: could not find true bin " <<
367  end_energy << std::endl;
368  }
369  }
370  }
371 
372  int flux_type = this_sample->GetFluxType();
373  nominal_fluxes[flux_type] += 1.;
374  this_sample->AddFlux();
375  double val[1] = {0};
376  if (selection_ID == 4) {
377  TH1D * selected_hist
378  = (TH1D*)this_sample->GetSelectionHists().at(selection_ID);
379  if (selected_hist->FindBin(reco_beam_endZ) == 0) {
380  val[0] = selected_hist->GetBinCenter(1);
381  }
382  else if (selected_hist->FindBin(reco_beam_endZ) >
383  selected_hist->GetNbinsX()) {
384  val[0] = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
385  }
386  else {
387  val[0] = reco_beam_endZ;
388  }
389  }
390  else if (selection_ID > 4) {
391  val[0] = .5;
392  }
393  else if (reco_beam_incidentEnergies./*->*/size()) {
394  double energy[1] = {reco_beam_interactingEnergy};
395  if (fDoEnergyFix) {
396  for (size_t k = 1; k < reco_beam_incidentEnergies.size(); ++k) {
397  double deltaE = ((reco_beam_incidentEnergies)[k-1] -
398  (reco_beam_incidentEnergies)[k]);
399  if (deltaE > fEnergyFix) {
400  energy[0] += deltaE;
401  }
402  }
403  }
404 
405  TH1D * selected_hist
406  = (TH1D*)this_sample->GetSelectionHists().at(selection_ID);
407  if (selected_hist->FindBin(energy[0]) == 0) {
408  val[0] = selected_hist->GetBinCenter(1);
409  }
410  else if (selected_hist->FindBin(energy[0]) >
411  selected_hist->GetNbinsX()) {
412  val[0] = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
413  }
414  else {
415  val[0] = energy[0];
416  }
417  }
418  else {
419  TH1D * selected_hist
420  = (TH1D*)this_sample->GetSelectionHists().at(selection_ID);
421  val[0] = selected_hist->GetBinCenter(1);
422  }
423  this_sample->FillSelectionHist(selection_ID, val);
424 
425  //Fill the total incident hist with truth info
426  this_sample->FillTrueIncidentHist(good_true_incEnergies);
427  this_sample->AddIncidentEnergies(good_true_incEnergies);
428  if (true_beam_incidentEnergies.size() > 0) {
429  this_sample->AddESliceEnergies(
430  {(true_beam_incidentEnergies)[0],
431  end_energy});
432  }
433 
434  }
435 
436 }
437 
439  const std::vector<ThinSliceEvent> & events,
440  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
441  const std::map<int, bool> & signal_sample_checks,
442  std::vector<double> & beam_energy_bins,
443  const std::map<int, std::vector<double>> & signal_pars,
444  const std::map<int, double> & flux_pars,
445  const std::map<std::string, ThinSliceSystematic> & syst_pars,
446  bool fit_under_over, bool fill_incident) {
447 
448  //Reset all samples
449  for (auto it = samples.begin(); it != samples.end(); ++it) {
450  for (size_t i = 0; i < it->second.size(); ++i) {
451  for (size_t j = 0; j < it->second[i].size(); ++j) {
452  it->second[i][j].Reset();
453  }
454  }
455  }
456 
457 
458  for (size_t i = 0; i < events.size(); ++i) {
459  const ThinSliceEvent & event = events.at(i);
460  int sample_ID = event.GetSampleID();
461  int selection_ID = event.GetSelectionID();
462 
463  double true_beam_interactingEnergy = event.GetTrueInteractingEnergy();
464  double reco_beam_interactingEnergy = event.GetRecoInteractingEnergy();
465  double true_beam_endP = event.GetTrueEndP();
466  double reco_beam_endZ = event.GetRecoEndZ();
467  double true_beam_startP = event.GetTrueStartP();
468 
469  const std::vector<double> & reco_beam_incidentEnergies
470  = event.GetRecoIncidentEnergies();
471  const std::vector<double> & true_beam_incidentEnergies
472  = event.GetTrueIncidentEnergies();
473  const std::vector<double> & true_beam_traj_Z
474  = event.GetTrueTrajZ();
475  const std::vector<double> & true_beam_traj_KE
476  = event.GetTrueTrajKE();
477  const std::vector<int> & true_beam_slices
478  = event.GetTrueSlices();
479  double beam_inst_P = event.GetBeamInstP();
480  const std::vector<double> calibrated_dQdX
481  = event.GetdQdXCalibrated();
482  const std::vector<double> beam_EField
483  = event.GetEField();
484  const std::vector<double> track_pitch
485  = event.GetTrackPitch();
486  const std::vector<double> daughter_thetas
487  = event.GetRecoDaughterTrackThetas();
488 // const std::vector<double> track_scores
489 // = event.GetRecoDaughterTrackScores();
490 
491  double end_energy = true_beam_interactingEnergy;
492  if (fSliceMethod == "Traj") {
493  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
494  }
495  else if (fSliceMethod == "E") {
496  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
497  }
498  else if (fSliceMethod == "Alt") {
499  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z.back());
500  if (bin > 0)
501  end_energy = fMeans.at(bin);
502  }
503 
504  if (samples.find(sample_ID) == samples.end()) {
505  std::cout << "Warning: skipping sample " << sample_ID << std::endl;
506  continue;
507  }
508 
509  //Build the true incident energy vector based on the slice cut
510  std::vector<double> good_true_incEnergies;
511  if (fill_incident) {
512  good_true_incEnergies = MakeTrueIncidentEnergies(
513  true_beam_traj_Z, true_beam_traj_KE, true_beam_slices,
514  true_beam_incidentEnergies);
515  }
516 
517  int bin = GetBeamBin(beam_energy_bins, true_beam_startP);
518 
519  //Weight for the event
520  //Possibly affected by signal, flux, and syst parameters
521  double weight = 1.;
522 
523  std::vector<ThinSliceSample> & samples_vec = samples.at(sample_ID)[bin];
524  bool is_signal = signal_sample_checks.at(sample_ID);
525 
526  ThinSliceSample * this_sample = 0x0;
527  if (!is_signal) {
528  this_sample = &samples_vec.at(0);
529  }
530  else {
531  //Iterate through the true bins and find the correct one
532  bool found = false;
533  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
534  ThinSliceSample & sample = samples_vec.at(j);
535  if (sample.CheckInSignalRange(end_energy)) {
536  this_sample = &sample;
537 
538  found = true;
539 
540  //If fitting under/overflow: Need to consider here
541  int index = j - 1 + (fit_under_over ? 1 : 0);
542  weight *= signal_pars.at(sample_ID)[index];
543 
544  break;
545  }
546  }
547  if (!found) {
548  //over/underflow here
549  if (end_energy <= samples_vec[1].RangeLowEnd()) {
550  this_sample = &samples_vec[0];
551  if (fit_under_over) weight *= signal_pars.at(sample_ID)[0];
552  //If fitting under/overflow: Need to consider here
553  }
554  else if (end_energy >
555  samples_vec[samples_vec.size()-2].RangeHighEnd()) {
556  //If fitting under/overflow: Need to consider here
557  this_sample = &samples_vec.back();
558  if (fit_under_over) weight *= signal_pars.at(sample_ID).back();
559  }
560  else {
561  std::cout << "Warning: could not find true bin " <<
562  end_energy << std::endl;
563  }
564  }
565  }
566 
567  int flux_type = this_sample->GetFluxType();
568  if (flux_pars.find(flux_type) != flux_pars.end()) {
569  weight *= flux_pars.at(flux_type);
570  }
571 
572  double val[1] = {0};
573 
574  int new_selection = selection_ID;
575  TH1D * selected_hist
576  = (TH1D*)this_sample->GetSelectionHists().at(new_selection);
577  if (new_selection == 4) {
578  if (selected_hist->FindBin(reco_beam_endZ) == 0) {
579  val[0] = selected_hist->GetBinCenter(1);
580  }
581  else if (selected_hist->FindBin(reco_beam_endZ) >
582  selected_hist->GetNbinsX()) {
583  val[0] = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
584  }
585  else {
586  val[0] = reco_beam_endZ;
587  }
588  }
589  else if (new_selection > 4) {
590  val[0] = .5;
591  }
592  else if (reco_beam_incidentEnergies.size()) {
593 
594  double energy[1] = {0.};
595  if (syst_pars.find("dEdX_Cal") != syst_pars.end()) {
596  energy[0] = sqrt(beam_inst_P*beam_inst_P*1.e6 + 139.57*139.57) -
597  139.57;
598  //limits?
599  for (size_t k = 0; k < calibrated_dQdX.size()-1; ++k) {
600  if ((calibrated_dQdX)[k] < 0.) continue;
601 
602  double dedx = (1./(syst_pars.at("dEdX_Cal").GetValue()));
603  dedx *= (calibrated_dQdX)[k];
604  dedx *= (fBetaP / ( fRho * (beam_EField)[k] ) * fWion);
605  dedx = exp(dedx);
606  dedx -= fAlpha;
607  dedx *= ((fRho*(beam_EField)[k])/fBetaP);
608 
609  if (dedx*(track_pitch)[k] > fEnergyFix)
610  continue;
611  energy[0] -= dedx*(track_pitch)[k];
612  }
613  }
614 
615  else {
616  energy[0] = {reco_beam_interactingEnergy};
617  if (fDoEnergyFix) {
618  for (size_t k = 1; k < reco_beam_incidentEnergies.size(); ++k) {
619  double deltaE = ((reco_beam_incidentEnergies)[k-1] -
620  (reco_beam_incidentEnergies)[k]);
621  if (deltaE > fEnergyFix) {
622  energy[0] += deltaE;
623  }
624  }
625  }
626  }
627 
628  if (selected_hist->FindBin(energy[0]) == 0) {
629  val[0] = selected_hist->GetBinCenter(1);
630  }
631  else if (selected_hist->FindBin(energy[0]) > selected_hist->GetNbinsX()) {
632  val[0] = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
633  }
634  else {
635  val[0] = energy[0];
636  }
637  }
638  else {
639  val[0] = selected_hist->GetBinCenter(1);
640  }
641 
642  if (syst_pars.find("dEdX_Cal_Spline") != syst_pars.end()) {
643  int bin = selected_hist->FindBin(val[0]);
644  TSpline3 * spline
645  = fFullSelectionSplines["dEdX_Cal_Spline"][new_selection][bin-1];
646  weight *= spline->Eval(syst_pars.at("dEdX_Cal_Spline").GetValue());
647  }
648  if (weight < 0.) {
649  std::cout << "Weight went negative after dedx spline" << std::endl;
650  }
651 
652  if (syst_pars.find("beam_shift_spline") != syst_pars.end()) {
653  int bin = selected_hist->FindBin(val[0]);
654  TSpline3 * spline
655  = fFullSelectionSplines["Beam_Shift_Spline"][new_selection/*selection_ID*/][bin-1];
656  weight *= spline->Eval(syst_pars.at("beam_shift_spline").GetValue());
657  }
658  if (syst_pars.find("eff_var") != syst_pars.end()) {
659  int bin = selected_hist->FindBin(val[0]);
660  TSpline3 * spline
661  = fFullSelectionSplines["EffVar_Spline"][new_selection/*selection_ID*/][bin-1];
662  weight *= spline->Eval(syst_pars.at("eff_var").GetValue());
663  }
664  if (weight < 0.) {
665  std::cout << "Weight went negative after eff var spline" << std::endl;
666  }
667 
668  if (syst_pars.find("beam_shift_spline_2") != syst_pars.end()) {
669  int bin = selected_hist->FindBin(val[0]);
670  TSpline3 * spline
671  = fFullSelectionSplines["BeamShiftSpline2"][new_selection][bin-1];
672  weight *= spline->Eval(syst_pars.at("beam_shift_spline_2").GetValue());
673  }
674  if (weight < 0.) {
675  std::cout << "Weight went negative after beam shift spline" << std::endl;
676  }
677 
678  weight *= GetSystWeight_G4RW(event, syst_pars, *this_sample, new_selection/*selection_ID*/,
679  val[0]);
680 
681  weight *= GetSystWeight_BeamShift(event, syst_pars);
682  if (weight < 0.) {
683  std::cout << "Weight went negative after beam shift" << std::endl;
684  }
685  //weight *= GetSystWeight_BeamShift2D(event, syst_pars);
686  //if (weight < 0.) {
687  // std::cout << "Weight went negative after beam shift 2D" << std::endl;
688  //}
689  weight *= GetSystWeight_EffVar(event, syst_pars);
690  if (weight < 0.) {
691  std::cout << "Weight went negative after eff" << std::endl;
692  }
693  weight *= GetSystWeight_EDiv(event, syst_pars);
694  if (weight < 0.) {
695  std::cout << "Weight went negative after ediv" << std::endl;
696  }
697  //weight *= GetSystWeight_NoTrack(event, syst_pars);
698  weight *= GetSystWeight_BeamEffs(event, syst_pars);
699  if (weight < 0.) {
700  std::cout << "Weight went negative after beam effs" << std::endl;
701  }
702 
703  this_sample->FillSelectionHist(new_selection, val, weight);
704 
705  //Fill the total incident hist with truth info
706  if (fill_incident) {
707  this_sample->FillTrueIncidentHist(good_true_incEnergies, weight);
708  this_sample->AddIncidentEnergies(good_true_incEnergies, weight);
709  if (true_beam_incidentEnergies.size() > 0) {
710  this_sample->AddESliceEnergies(
711  {(true_beam_incidentEnergies)[0],
712  end_energy}, weight);
713  }
714  }
715 
716  this_sample->AddVariedFlux(weight);
717  }
718 
719 }
720 
722  //if (fSetupSystBeamRes/*fSystBeamResTree*/) {
723  // output_file.cd("SystBeamRes");
724  // fSystBeamResTree->Write();
725  //}
727  output_file.cd("SystBeamShift");
728  fSystBeamShiftTree->Write();
729  }
730  /*
731  if (fSetupSystBeamShift2D) {
732  output_file.cd("SystBeamShift2D");
733  fSystBeamShift2DTree->Write();
734  }*/
735 }
736 
738  const std::vector<ThinSliceEvent> & events,
739  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
740  const std::map<int, bool> & signal_sample_checks,
741  std::vector<double> & beam_energy_bins,
742  const std::map<std::string, ThinSliceSystematic> & pars,
743  TFile & output_file) {
744 
745  if (pars.find("dEdX_Cal") != pars.end()) {
746  //std::cout << "Found par dEdX_Cal" << std::endl;
747  fhicl::ParameterSet cal_set
748  = pars.at("dEdX_Cal").GetOption<fhicl::ParameterSet>("Cal_set");
749  fBetaP = cal_set.get<double>("betap");
750  fRho = cal_set.get<double>("Rho");
751  fWion = cal_set.get<double>("Wion");
752  fAlpha = cal_set.get<double>("alpha");
753 
754  std::vector<fhicl::ParameterSet> PlanePars
755  = cal_set.get<std::vector<fhicl::ParameterSet>>("PlaneParameters");
756  bool found_collection = false;
757  for (auto & p : PlanePars) {
758  if (p.get<int>("PlaneID") == 2) {
759  fNominalCCal = p.get<double>("calib_factor");
760  found_collection = true;
761  break;
762  }
763  }
764 
765  if (!found_collection) {
766  std::string message = "Could not find collection plane calibration factor";
767  throw std::runtime_error(message);
768  }
769  }
770  else if (pars.find("dEdX_Cal_Spline") != pars.end()) {
771  fhicl::ParameterSet cal_set
772  = pars.at("dEdX_Cal_Spline").GetOption<fhicl::ParameterSet>("Cal_set");
773  fBetaP = cal_set.get<double>("betap");
774  fRho = cal_set.get<double>("Rho");
775  fWion = cal_set.get<double>("Wion");
776  fAlpha = cal_set.get<double>("alpha");
777 
778  std::vector<fhicl::ParameterSet> PlanePars
779  = cal_set.get<std::vector<fhicl::ParameterSet>>("PlaneParameters");
780  bool found_collection = false;
781  for (auto & p : PlanePars) {
782  if (p.get<int>("PlaneID") == 2) {
783  fNominalCCal = p.get<double>("calib_factor");
784  found_collection = true;
785  break;
786  }
787  }
788 
789  if (!found_collection) {
790  std::string message = "Could not find collection plane calibration factor";
791  throw std::runtime_error(message);
792  }
793  SetupSyst_dEdX_Cal(events, samples, pars, output_file);
794  }
795 
796  SetupSyst_G4RW(events, samples, signal_sample_checks, beam_energy_bins,
797  pars, output_file);
798 
799  //SetupSyst_BeamRes(events, samples, pars, output_file);
800  SetupSyst_BeamShift(pars, output_file);
801  SetupSyst_BeamShiftSpline(events, samples, pars, output_file);
802  SetupSyst_BeamShiftSpline2(events, samples, pars, output_file);
803  SetupSyst_BeamShiftRatio(events, samples, pars, output_file);
804  //SetupSyst_BeamShift2D(pars, output_file);
805  SetupSyst_EffVar(events, samples, pars, output_file);
807  SetupSyst_EDivWeight(pars);
808  //SetupSyst_NoTrackWeight(pars);
810 
811 }
812 
814  const std::map<std::string, ThinSliceSystematic> & pars) {
815  if (pars.find("eff_var_weight") == pars.end()) {
816  return;
817  }
818  fEffVarF = pars.at("eff_var_weight").GetOption<double>("F");
819  fEffVarCut = pars.at("eff_var_weight").GetOption<double>("Cut");
820 }
821 
822 
824  const ThinSliceEvent & event,
825  const std::map<std::string, ThinSliceSystematic> & pars) {
826 
827  if (pars.find("eff_var_weight") == pars.end()) return 1.;
828 
829  const int selection_ID = event.GetSelectionID();
830  if (selection_ID > 3) return 1.;
831 
832  const std::vector<double> daughter_thetas
833  = event.GetRecoDaughterTrackThetas();
834  const std::vector<double> track_scores
835  = event.GetRecoDaughterTrackScores();
836  size_t n = 0;
837  for (size_t i = 0; i < track_scores.size(); ++i) {
838  if ((track_scores[i] > fEffVarCut) &&
839  (daughter_thetas[i]*180./TMath::Pi() < 20.) &&
840  (daughter_thetas[i] > -999.))
841  ++n;
842  }
843  //std::cout << selection_ID << " Has " << n << " tracks under 20. degrees. Weight: ";
844 
845  double weight = 1.;
846  if (n > 0) {
847  if (selection_ID == 3) {
848  weight = (1 - std::pow(fEffVarF*pars.at("eff_var_weight").GetValue(), n))/
849  (1 - std::pow(fEffVarF, n));
850  }
851  else {
852  weight = (std::pow(pars.at("eff_var_weight").GetValue(), n));
853  }
854  }
855  //std::cout << weight << std::endl;
856  //std::cout << "\tF: " << fEffVarF << " Val: " <<
857  // pars.at("eff_var_weight").GetValue() << std::endl;
858  return weight;
859 }
860 
862  const std::map<std::string, ThinSliceSystematic> & pars) {
863  if (pars.find("ediv_weight") == pars.end()) {
864  return;
865  }
866  fEDivF = pars.at("ediv_weight").GetOption<double>("F");
867  fEDivCut = pars.at("ediv_weight").GetOption<double>("Cut");
868 }
869 
871  const std::map<std::string, ThinSliceSystematic> & pars) {
872  if (pars.find("no_track_weight") == pars.end()) {
873  return;
874  }
875  fNoTrackF = pars.at("no_track_weight").GetOption<double>("F");
876 }
877 
879  const std::map<std::string, ThinSliceSystematic> & pars) {
880  std::cout << "Beam effs" << std::endl;
881  if (pars.find("beam_cut_weight") != pars.end()) {
882  fBeamCutF = pars.at("beam_cut_weight").GetOption<double>("F");
883  }
884  if (pars.find("no_track_weight") != pars.end()) {
885  fNoTrackF = pars.at("no_track_weight").GetOption<double>("F");
886  }
887 }
888 
890  const ThinSliceEvent & event,
891  const std::map<std::string, ThinSliceSystematic> & pars) {
892 
893  if (pars.find("ediv_weight") == pars.end()) return 1.;
894 
895  const int selection_ID = event.GetSelectionID();
896  if (selection_ID != 4) return 1.;
897 
898  const double endZ = event.GetRecoEndZ();
899 
900  double weight = 1.;
901  double var = pars.at("ediv_weight").GetValue();
902  if (endZ < fEDivCut) {
903  weight = var;
904  }
905  else {
906  weight = (1. - var*fEDivF)/(1. - fEDivF);
907  }
908 
909  return weight;
910 }
911 
913  const ThinSliceEvent & event,
914  const std::map<std::string, ThinSliceSystematic> & pars) {
915 
916  if (pars.find("no_track_weight") == pars.end()) {
917  return 1.;
918  }
919 
920  const int selection_ID = event.GetSelectionID();
921 
922  double weight = 1.;
923  double var = pars.at("no_track_weight").GetValue();
924  if (selection_ID == 6) {
925  weight = var;
926  }
927  else {
928  weight = (1. - var*fNoTrackF)/(1. - fNoTrackF);
929  }
930  //std::cout << selection_ID << " " << fNoTrackF << " " << var << " " << weight << std::endl;
931 
932  return weight;
933 }
934 
936  const ThinSliceEvent & event,
937  const std::map<std::string, ThinSliceSystematic> & pars) {
938 
939  if (pars.find("beam_cut_weight") == pars.end() &&
940  pars.find("no_track_weight") == pars.end()) {
941  return 1.;
942  }
943  else if (pars.find("beam_cut_weight") != pars.end() &&
944  pars.find("no_track_weight") == pars.end()) {
945  const int selection_ID = event.GetSelectionID();
946 
947  double weight = 1.;
948  double var = pars.at("beam_cut_weight").GetValue();
949  if (selection_ID == 5) {
950  weight = var;
951  }
952  else {
953  weight = (1. - var*fBeamCutF)/(1. - fBeamCutF);
954  }
955 
956  return weight;
957  }
958  else if (pars.find("no_track_weight") != pars.end() &&
959  pars.find("beam_cut_weight") == pars.end()) {
960  const int selection_ID = event.GetSelectionID();
961 
962  double weight = 1.;
963  double var = pars.at("no_track_weight").GetValue();
964  if (selection_ID == 6) {
965  weight = var;
966  }
967  else {
968  weight = (1. - var*fNoTrackF)/(1. - fNoTrackF);
969  }
970 
971  return weight;
972  }
973  else {
974  const int selection_ID = event.GetSelectionID();
975 
976  double weight = 1.;
977  double var_no_track = pars.at("no_track_weight").GetValue();
978  double var_beam_cut = pars.at("beam_cut_weight").GetValue();
979  if (selection_ID == 6) {
980  weight = var_no_track;
981  }
982  else if (selection_ID == 5) {
983  weight = var_beam_cut;
984  }
985  else {
986  weight = (1. - var_no_track*fNoTrackF - var_beam_cut*fBeamCutF)/
987  (1. - fNoTrackF - fBeamCutF);
988  }
989 
990  if (weight < 0.) {
991  std::cout << "Negative beam cut weight: " << var_no_track << " " <<
992  fNoTrackF << " " << var_beam_cut << " " << fBeamCutF <<
993  std::endl;
994  }
995  return weight;
996  }
997 }
998 
1000  const std::vector<ThinSliceEvent> & events,
1001  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
1002  const std::map<std::string, ThinSliceSystematic> & pars,
1003  TFile & output_file) {
1004 
1005  if (pars.find("eff_var") == pars.end()) {
1006  return;
1007  }
1008 
1009  fSetupSystEffVar = true;
1010  //fEffVarSystVal = pars.at("eff_var").GetOption<double>("Val");
1011  //Get the systematic variations to the effeciency
1012  //then build systematic shift hists
1013  std::vector<double> vars;
1014  for (size_t i = 0; i < 11; ++i) {
1015  vars.push_back(.1*i);
1016  std::cout << vars.back() << " ";
1017  }
1018  std::cout << std::endl;
1019 
1020  //Get the first sample and get the selection hists
1021  //also make full hist
1022  std::map<int, TH1D*> full_hists;
1023 
1024  ThinSliceSample & temp_sample = samples.begin()->second[0][0];
1025  const std::map<int, TH1*> & sel_hists = temp_sample.GetSelectionHists();
1026  for (auto it = sel_hists.begin(); it != sel_hists.end(); ++it) {
1027  std::string sel_hist_name = it->second->GetName();
1028  sel_hist_name += "Syst_EffVar_Spline";
1029 
1030  fFullSelectionVars["EffVar_Spline"][it->first] = std::vector<TH1D*>();
1031  for (size_t k = 0; k < vars.size(); ++k) {
1032  std::string shift_name = sel_hist_name;
1033  shift_name += std::to_string(k);
1034  fFullSelectionVars["EffVar_Spline"][it->first].push_back((TH1D*)it->second->Clone(shift_name.c_str()));
1035  fFullSelectionVars["EffVar_Spline"][it->first].back()->Reset();
1036 
1037  }
1038 
1039  sel_hist_name += "_FullVar";
1040  full_hists[it->first] = (TH1D*)it->second->Clone(sel_hist_name.c_str());
1041  full_hists[it->first]->Reset();
1042  }
1043 
1044  for (size_t i = 0; i < events.size(); ++i) {
1045  const ThinSliceEvent & event = events.at(i);
1046  int sample_ID = event.GetSampleID();
1047  int selection_ID = event.GetSelectionID();
1048 
1049  double reco_beam_endZ = event.GetRecoEndZ();
1050 
1051  const std::vector<double> & reco_beam_incidentEnergies
1052  = event.GetRecoIncidentEnergies();
1053  double reco_beam_interactingEnergy = event.GetRecoInteractingEnergy();
1054  const std::vector<double> calibrated_dQdX
1055  = event.GetdQdXCalibrated();
1056  const std::vector<double> beam_EField
1057  = event.GetEField();
1058  const std::vector<double> track_pitch
1059  = event.GetTrackPitch();
1060  const std::vector<double> daughter_thetas
1061  = event.GetRecoDaughterTrackThetas();
1062  const std::vector<double> track_scores
1063  = event.GetRecoDaughterTrackScores();
1064 
1065  if (samples.find(sample_ID) == samples.end()) {
1066  std::cout << "Warning: skipping sample " << sample_ID << std::endl;
1067  continue;
1068  }
1069 
1070  std::vector<int> new_selections(vars.size(), selection_ID);
1071  if (selection_ID < 3) {
1072  for (size_t j = 0; j < vars.size(); ++j) {
1073  //Need check for CNN here
1074  for (size_t k = 0; k < daughter_thetas.size(); ++k) {
1075  if ((daughter_thetas[k] > -999) &&
1076  (track_scores[k] > .3) &&
1077  (daughter_thetas[k]*180./TMath::Pi() < 20.)) {
1078  double r = fRNG.Uniform();
1079  //std::cout << "Checking: " << r << " " << vars[j] << std::endl;
1080  if (r < vars[j]) {
1081  new_selections[j] = 3;
1082  break;
1083  }
1084  }
1085  }
1086  }
1087  }
1088 
1089  std::vector<double> vals(vars.size(), 0.);
1090  if (selection_ID == 4) {
1091  TH1D * selected_hist
1092  = fFullSelectionVars["EffVar_Spline"][selection_ID][0];
1093  if (selected_hist->FindBin(reco_beam_endZ) == 0) {
1094  for (double & v : vals) v = selected_hist->GetBinCenter(1);
1095  }
1096  else if (selected_hist->FindBin(reco_beam_endZ) >
1097  selected_hist->GetNbinsX()) {
1098  for (double & v : vals)
1099  v = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
1100  }
1101  else {
1102  for (double & v : vals) v = reco_beam_endZ;
1103  }
1104  }
1105  else if (selection_ID > 4) {
1106  for (double & v : vals) v = .5;
1107  }
1108  else if (reco_beam_incidentEnergies.size()) {
1109  double energy = reco_beam_interactingEnergy;
1110  if (fDoEnergyFix) {
1111  for (size_t k = 1; k < reco_beam_incidentEnergies.size(); ++k) {
1112  double deltaE = ((reco_beam_incidentEnergies)[k-1] -
1113  (reco_beam_incidentEnergies)[k]);
1114  if (deltaE > fEnergyFix) {
1115  energy += deltaE;
1116  }
1117  }
1118  }
1119 
1120  for (size_t j = 0; j < new_selections.size(); ++j) {
1121  TH1D * selected_hist
1122  = fFullSelectionVars["EffVar_Spline"][new_selections[j]][0];
1123  if (selected_hist->FindBin(energy) == 0) {
1124  vals[j] = selected_hist->GetBinCenter(1);
1125  }
1126  else if (selected_hist->FindBin(energy) >
1127  selected_hist->GetNbinsX()) {
1128  vals[j] = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
1129  }
1130  else {
1131  vals[j] = energy;
1132  }
1133  }
1134  }
1135  else {
1136  for (size_t j = 0; j < new_selections.size(); ++j) {
1137  TH1D * selected_hist
1138  = fFullSelectionVars["EffVar_Spline"][new_selections[j]][0];
1139  vals[j] = selected_hist->GetBinCenter(1);
1140  }
1141  }
1142 
1143  for (size_t j = 0; j < vals.size(); ++j) {
1144  int ID = (selection_ID < 3 ? new_selections[j] : selection_ID);
1145  //std::cout << "Filling " << ID << " " << j << std::endl;
1146  //std::cout << selection_ID << " " << new_selections[j] << std::endl;
1147  //std::cout << fFullSelectionVars["EffVar_Spline"][ID][j] << std::endl;
1148  fFullSelectionVars["EffVar_Spline"][ID][j]->Fill(vals[j]);
1149  }
1150  }
1151 
1152  TDirectory * dir = output_file.mkdir("EffVar_Spline_Syst");
1153  dir->cd();
1154 
1155  //Take the vars and make into ratios, then turn into splines
1156  for (auto it = fFullSelectionVars["EffVar_Spline"].begin();
1157  it != fFullSelectionVars["EffVar_Spline"].end(); ++it) {
1158  int selection_ID = it->first;
1159 
1160  //Build the full hist
1161  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
1162  for (size_t i = 0; i < it2->second.size(); ++i) {
1163  for (size_t j = 0; j < it2->second[i].size(); ++j) {
1164  full_hists[selection_ID]->Add(it2->second[i][j].GetSelectionHist(
1165  selection_ID));
1166  }
1167  }
1168  }
1169 
1170  for (size_t i = 0; i < it->second.size(); ++i) {
1171  it->second[i]->Write();
1172  it->second[i]->Divide(full_hists[selection_ID]);
1173  }
1174 
1175  fFullSelectionSplines["EffVar_Spline"][selection_ID] = std::vector<TSpline3*>();
1176  for (int i = 1; i <= full_hists[selection_ID]->GetNbinsX(); ++i) {
1177  std::vector<double> vals;
1178  for (size_t j = 0; j < it->second.size(); ++j) {
1179  vals.push_back(it->second[j]->GetBinContent(i));
1180  }
1181 
1182  std::string spline_name = full_hists[selection_ID]->GetName();
1183  spline_name += "_Spline" + std::to_string(i);
1184 
1185  fFullSelectionSplines["EffVar_Spline"][selection_ID].push_back(
1186  new TSpline3(spline_name.c_str(), &vars[0], &vals[0], vals.size()));
1187  TCanvas c(spline_name.c_str(), "");
1188  fFullSelectionSplines["EffVar_Spline"][selection_ID].back()->Draw();
1189  c.Write();
1190  }
1191  }
1192 
1193 }
1194 
1196  const std::map<std::string, ThinSliceSystematic> & pars,
1197  TFile & output_file) {
1198  if (pars.find("beam_shift") == pars.end()) {
1199  return;
1200  }
1201 
1202  TFile shift_file(
1203  pars.at("beam_shift").GetOption<std::string>("ShiftFile").c_str());
1204  fSystBeamShiftMap = (TGraph2D*)shift_file.Get("g2d");
1205  fSystBeamShiftMap->SetDirectory(0);
1207  = pars.at("beam_shift").GetOption<std::pair<double, double>>("Limits");
1208 
1209  //fSystBeamShiftRatioLimitUp = pars.at("beam_shift").GetOption<double>("RatioLimitUp");
1210  //fSystBeamShiftRatioLimitDown = pars.at("beam_shift").GetOption<double>("RatioLimitDown");
1211  fSystBeamShiftMeans = (TGraph*)shift_file.Get("gMeans");
1212  //fSystBeamShiftMeans->SetDirectory(0);
1213  fSystBeamShiftWidths = (TGraph*)shift_file.Get("gWidths");
1214  //fSystBeamShiftWidths->SetDirectory(0);
1215  shift_file.Close();
1216 
1217  fSystBeamShiftTreeSave = pars.at("beam_shift").GetOption<bool>("SaveInfo");
1218  fSystBeamShiftWeightCap = pars.at("beam_shift").GetOption<double>("WeightCap");
1219  if (fSystBeamShiftTreeSave) {
1220  output_file.mkdir("SystBeamShift");
1221  output_file.cd("SystBeamShift");
1222  fSystBeamShiftTree = new TTree("tree", "");
1223  fSystBeamShiftTree->Branch("Weight", &fSystBeamShiftWeight);
1224  fSystBeamShiftTree->Branch("Val", &fSystBeamShiftVal);
1225  fSystBeamShiftTree->Branch("R", &fSystBeamShiftR);
1226  }
1227  fSetupSystBeamShift = true;
1228 
1229 }
1230 
1231 /*
1232 void protoana::AbsCexDriver::SetupSyst_BeamShift2D(
1233  const std::map<std::string, ThinSliceSystematic> & pars,
1234  TFile & output_file) {
1235  bool has_2D_shift = (pars.find("beam_2D_shift") != pars.end());
1236  bool has_2D_B = (pars.find("beam_2D_B") != pars.end());
1237 
1238  if (!has_2D_shift && !has_2D_B) return;
1239  std::string shift_file_name
1240  = (has_2D_shift ?
1241  pars.at("beam_2D_shift").GetOption<std::string>("MapFile") :
1242  pars.at("beam_2D_B").GetOption<std::string>("MapFile"));
1243  TFile shift_file(shift_file_name.c_str());
1244 
1245  fSystBeam2DMeans = (TGraph2D*)shift_file.Get("means");
1246  fSystBeam2DMeans->SetDirectory(0);
1247  fSystBeam2DStdDevs = (TGraph2D*)shift_file.Get("std_devs");
1248  fSystBeam2DStdDevs->SetDirectory(0);
1249 
1250  shift_file.Close();
1251 
1252  output_file.mkdir("SystBeamShift2D");
1253  output_file.cd("SystBeamShift2D");
1254  fSystBeamShift2DTree = new TTree("tree", "");
1255  fSystBeamShift2DTree->Branch("Weight", &fSystBeamShift2DWeight);
1256  fSystBeamShift2DTree->Branch("B", &fSystBeamShift2DBVal);
1257  fSystBeamShift2DTree->Branch("Shift", &fSystBeamShift2DVal);
1258  fSystBeamShift2DTree->Branch("R", &fSystBeamShift2DR);
1259  fSetupSystBeamShift2D = true;
1260 
1261 }*/
1262 
1264  const std::vector<ThinSliceEvent> & events,
1265  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
1266  const std::map<std::string, ThinSliceSystematic> & pars,
1267  TFile & output_file) {
1268  if (pars.find("beam_shift_spline") == pars.end()) {
1269  return;
1270  }
1271 
1272  TFile shift_file(
1273  pars.at("beam_shift_spline").GetOption<std::string>("ShiftFile").c_str());
1274  std::pair<double, double> limits
1275  = pars.at("beam_shift_spline").GetOption<std::pair<double, double>>("Limits");
1276 
1277  TGraph * gMeans = (TGraph*)shift_file.Get("gMeans");
1278  TGraph * gWidths = (TGraph*)shift_file.Get("gWidths");
1279 
1280  std::vector<double> means, widths, beam_shift_vals;
1281  int n = -2;
1282  for (int i = ((gMeans->GetN() - 1)/2 - 2);
1283  i <= ((gMeans->GetN() - 1)/2 + 2); ++i) {
1284  means.push_back(gMeans->GetY()[i]);
1285  widths.push_back(gWidths->GetY()[i]);
1286  beam_shift_vals.push_back(n);
1287  ++n;
1288  }
1289 
1290  double nominal_mean = gMeans->GetY()[(gMeans->GetN() - 1)/2];
1291  double nominal_width = gWidths->GetY()[(gWidths->GetN() - 1)/2];
1292  shift_file.Close();
1293 
1294  //Get the first sample and get the selection hists
1295  //also make full hist
1296  std::map<int, TH1D*> full_hists;
1297 
1298  ThinSliceSample & temp_sample = samples.begin()->second[0][0];
1299  const std::map<int, TH1*> & sel_hists = temp_sample.GetSelectionHists();
1300  for (auto it = sel_hists.begin(); it != sel_hists.end(); ++it) {
1301  std::string sel_hist_name = it->second->GetName();
1302  sel_hist_name += "Syst_Beam_Shift_Spline";
1303  int shift_number = -2;
1304 
1305  fFullSelectionVars["Beam_Shift_Spline"][it->first] = std::vector<TH1D*>();
1306  for (size_t k = 0; k < beam_shift_vals.size(); ++k) {
1307  std::string shift_name = sel_hist_name;
1308  shift_name += std::to_string(shift_number);
1309  fFullSelectionVars["Beam_Shift_Spline"][it->first].push_back((TH1D*)it->second->Clone(shift_name.c_str()));
1310  fFullSelectionVars["Beam_Shift_Spline"][it->first].back()->Reset();
1311 
1312  ++shift_number;
1313  if (shift_number == 0)
1314  ++shift_number;
1315  }
1316 
1317  sel_hist_name += "_FullVar";
1318  full_hists[it->first] = (TH1D*)it->second->Clone(sel_hist_name.c_str());
1319  full_hists[it->first]->Reset();
1320  }
1321 
1322  for (size_t i = 0; i < events.size(); ++i) {
1323  const ThinSliceEvent & event = events.at(i);
1324  int sample_ID = event.GetSampleID();
1325  int selection_ID = event.GetSelectionID();
1326  double reco_beam_endZ = event.GetRecoEndZ();
1327 
1328  const std::vector<double> & reco_beam_incidentEnergies
1329  = event.GetRecoIncidentEnergies();
1330  double reco_beam_interactingEnergy = event.GetRecoInteractingEnergy();
1331  double beam_inst_P = event.GetBeamInstP();
1332  const std::vector<double> calibrated_dQdX
1333  = event.GetdQdXCalibrated();
1334  const std::vector<double> beam_EField
1335  = event.GetEField();
1336  const std::vector<double> track_pitch
1337  = event.GetTrackPitch();
1338 
1339 
1340  if (samples.find(sample_ID) == samples.end()) {
1341  std::cout << "Warning: skipping sample " << sample_ID << std::endl;
1342  continue;
1343  }
1344 
1345  std::vector<double> weights, y_vals;
1346  for (size_t j = 0; j < means.size(); ++j) {
1347  double y_val = (beam_inst_P - event.GetTrueStartP())/
1348  event.GetTrueStartP();
1349  y_vals.push_back(y_val);
1350  if (y_val < limits.first ||
1351  y_val > limits.second || event.GetPDG() != 211) {
1352  weights.push_back(1.);
1353  continue;
1354  }
1355  double varied_width = widths[j];
1356  double varied_mean = means[j];
1357  weights.push_back((nominal_width/varied_width)*
1358  exp(.5*std::pow(((y_val - nominal_mean)/nominal_width), 2)
1359  - .5*std::pow(((y_val - varied_mean)/varied_width), 2)));
1360  }
1361  /*
1362  std::cout << "(y, m, s, w): " << std::endl;
1363  for (size_t j = 0; j < means.size(); ++j) {
1364  std::cout << "\t(" << y_vals[j] << ", " << means[j] << ", " << widths[j] << ", " <<
1365  weights[j] << ")" << std::endl;
1366  }
1367  std::cout << "nom mean, width: " << nominal_mean << " " << nominal_width << std::endl;
1368  */
1369 
1370  double val = 0.;
1371  if (selection_ID == 4) {
1372  TH1D * selected_hist
1373  = fFullSelectionVars["Beam_Shift_Spline"][selection_ID][0];
1374  if (selected_hist->FindBin(reco_beam_endZ) == 0) {
1375  val = selected_hist->GetBinCenter(1);
1376  }
1377  else if (selected_hist->FindBin(reco_beam_endZ) >
1378  selected_hist->GetNbinsX()) {
1379  val = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
1380  }
1381  else {
1382  val = reco_beam_endZ;
1383  }
1384  }
1385  else if (selection_ID > 4) {
1386  val = .5;
1387  }
1388  else if (reco_beam_incidentEnergies.size()) {
1389  double energy = reco_beam_interactingEnergy;
1390  if (fDoEnergyFix) {
1391  for (size_t k = 1; k < reco_beam_incidentEnergies.size(); ++k) {
1392  double deltaE = ((reco_beam_incidentEnergies)[k-1] -
1393  (reco_beam_incidentEnergies)[k]);
1394  if (deltaE > fEnergyFix) {
1395  energy += deltaE;
1396  }
1397  }
1398  }
1399  TH1D * selected_hist
1400  = fFullSelectionVars["Beam_Shift_Spline"][selection_ID][0];
1401  if (selected_hist->FindBin(energy) == 0) {
1402  val = selected_hist->GetBinCenter(1);
1403  }
1404  else if (selected_hist->FindBin(energy) >
1405  selected_hist->GetNbinsX()) {
1406  val = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
1407  }
1408  else {
1409  val = energy;
1410  }
1411  }
1412  else {
1413  TH1D * selected_hist
1414  = fFullSelectionVars["Beam_Shift_Spline"][selection_ID][0];
1415  val = selected_hist->GetBinCenter(1);
1416  }
1417  for (size_t j = 0; j < weights.size(); ++j) {
1418  fFullSelectionVars["Beam_Shift_Spline"][selection_ID][j]->Fill(val, weights[j]);
1419  }
1420  }
1421 
1422  TDirectory * dir = output_file.mkdir("Beam_Shift_Spline_Syst");
1423  dir->cd();
1424 
1425  //Take the vars and make into ratios, then turn into splines
1426  for (auto it = fFullSelectionVars["Beam_Shift_Spline"].begin();
1427  it != fFullSelectionVars["Beam_Shift_Spline"].end(); ++it) {
1428  int selection_ID = it->first;
1429 
1430  //Build the full hist
1431  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
1432  for (size_t i = 0; i < it2->second.size(); ++i) {
1433  for (size_t j = 0; j < it2->second[i].size(); ++j) {
1434  full_hists[selection_ID]->Add(it2->second[i][j].GetSelectionHist(
1435  selection_ID));
1436  }
1437  }
1438  }
1439 
1440  for (size_t i = 0; i < it->second.size(); ++i) {
1441  it->second[i]->Write();
1442  it->second[i]->Divide(full_hists[selection_ID]);
1443  }
1444 
1445  fFullSelectionSplines["Beam_Shift_Spline"][selection_ID] = std::vector<TSpline3*>();
1446  for (int i = 1; i <= full_hists[selection_ID]->GetNbinsX(); ++i) {
1447  std::vector<double> vals;
1448  for (size_t j = 0; j < it->second.size(); ++j) {
1449  vals.push_back(it->second[j]->GetBinContent(i));
1450  }
1451 
1452  std::string spline_name = full_hists[selection_ID]->GetName();
1453  spline_name += "_Spline" + std::to_string(i);
1454 
1455  std::string temp_name = "temp_" + spline_name;
1456  TSpline3 temp_spline = TSpline3(temp_name.c_str(), &beam_shift_vals[0],
1457  &vals[0], vals.size());
1458 
1459 
1460 
1461  std::cout << "Derivative, y at -2: " << temp_spline.Derivative(-2.) <<
1462  " " << temp_spline.Eval(-2.) << std::endl;
1463  std::cout << "Derivative, y at 2: " << temp_spline.Derivative(2.) <<
1464  " " << temp_spline.Eval(2.) << std::endl;
1465 
1466  std::vector<double> new_vals, new_beam_shift_vals;
1467  double neg_2_val = temp_spline.Eval(-2.);
1468  double neg_2_slope = temp_spline.Derivative(-2.);
1469  double neg_5_new_point = -3.*neg_2_slope + neg_2_val;
1470  if (neg_5_new_point < 0.)
1471  neg_5_new_point = 1.e-5;
1472  new_vals.push_back(neg_5_new_point);
1473 
1474  /*
1475  if (temp_spline.Derivative(-2.) > 0.) {
1476  new_vals.push_back(1.e-5);
1477  }
1478  else {
1479  new_vals.push_back(2.*temp_spline.Eval(-2.));
1480  }*/
1481  new_beam_shift_vals.push_back(-5.);
1482 
1483  for (size_t j = 0; j < vals.size(); ++j) {
1484  new_vals.push_back(vals[j]);
1485  new_beam_shift_vals.push_back(beam_shift_vals[j]);
1486  }
1487 
1488  double pos_2_val = temp_spline.Eval(2.);
1489  double pos_2_slope = temp_spline.Derivative(2.);
1490  double pos_5_new_point = 3.*pos_2_slope + pos_2_val;
1491  if (pos_5_new_point < 0.)
1492  pos_5_new_point = 1.e-5;
1493  new_vals.push_back(pos_5_new_point);
1494 
1495  //if (temp_spline.Derivative(2.) < 0.) {
1496  // new_vals.push_back(1.e-5);
1497  //}
1498  //else {
1499  // new_vals.push_back(2.*temp_spline.Eval(2.));
1500  //}
1501  new_beam_shift_vals.push_back(5.);
1502 
1503  TSpline3 * spline = new TSpline3(spline_name.c_str(), &new_beam_shift_vals[0],
1504  &new_vals[0], new_vals.size());
1505  fFullSelectionSplines["Beam_Shift_Spline"][selection_ID].push_back(spline);
1506  TCanvas c(spline_name.c_str(), "");
1507  spline->SetMarkerStyle(20);
1508  spline->Draw("P");
1509  c.Write();
1510  spline->Write(spline_name.c_str());
1511  }
1512  }
1513 
1514 
1515 }
1516 
1518  const std::vector<ThinSliceEvent> & events,
1519  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
1520  const std::map<int, bool> & signal_sample_checks,
1521  std::vector<double> & beam_energy_bins,
1522  const std::map<std::string, ThinSliceSystematic> & pars,
1523  TFile & output_file) {
1524 
1525  for (auto it = pars.begin(); it != pars.end(); ++it) {
1526  if (it->first.find("g4rw") != std::string::npos ||
1527  it->first.find("G4RW") != std::string::npos) {
1528  std::cout << "Setting up g4rw syst: " << it->first << std::endl;
1529  }
1530  else {
1531  continue;
1532  }
1533  fActiveG4RWSysts.push_back(it->first);
1534 
1535  std::string dir_name = it->first;
1536  dir_name += "_Syst_Dir";
1537  TDirectory * dir = output_file.mkdir(dir_name.c_str());
1538 
1539  size_t position = it->second.GetOption<size_t>("Position");
1540  std::string plus_branch = it->second.GetOption<std::string>("PlusBranch");
1541  std::string minus_branch = it->second.GetOption<std::string>("MinusBranch");
1542  bool is_grid = it->second.GetOption<bool>("IsGrid");
1543  std::string grid_branch = it->second.GetOption<std::string>("GridBranch");
1544  std::vector<double> syst_vals;
1545 
1546  if (!is_grid) {
1547  syst_vals = {
1548  it->second.GetLowerLimit(),
1549  it->second.GetCentral(),
1550  it->second.GetUpperLimit(),
1551  };
1552  }
1553  else {
1554  //double end = it->second.GetOption<double>("GridEnd");
1555  double delta = it->second.GetOption<double>("GridDelta");
1556  double start = it->second.GetOption<double>("GridStart");
1557  int n = it->second.GetOption<int>("GridN");
1558 
1559  //double delta = (end - start)/(n-1);
1560  std::cout << "Added to grid: ";
1561  //while (start <= end) {
1562  for (int i = 0; i < n; ++i) {
1563  syst_vals.push_back(start);
1564  std::cout << syst_vals.back() << " ";
1565  start += delta;
1566  }
1567  std::cout << std::endl;
1568  };
1569 
1570  //Set up the variation hists
1571  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
1572  for (size_t i = 0; i < it2->second.size(); ++i) {
1573  for (size_t j = 0; j < it2->second[i].size(); ++j) {
1574  const std::map<int, TH1 *> & sel_hists
1575  = it2->second[i][j].GetSelectionHists();
1576  for (auto it3 = sel_hists.begin(); it3 != sel_hists.end(); ++it3) {
1577  if (!is_grid) {
1578  std::string shift_name = it3->second->GetName();
1579  shift_name += "Minus";
1580  TH1D * temp_hist = (TH1D*)it3->second->Clone(shift_name.c_str());
1581 
1582  temp_hist->Reset();
1583  it2->second[i][j].AddSystematicShift(temp_hist, it->first,
1584  it3->first);
1585 
1586  shift_name = it3->second->GetName();
1587  shift_name += "Plus";
1588  temp_hist = (TH1D*)it3->second->Clone(shift_name.c_str());
1589  temp_hist->Reset();
1590 
1591  it2->second[i][j].AddSystematicShift(temp_hist, it->first,
1592  it3->first);
1593  }
1594  else {
1595  for (size_t k = 0; k < syst_vals.size(); ++k) {
1596  if (k == ((syst_vals.size() - 1)/2)) continue;
1597  //std::cout << "Adding shift " << k << std::endl;
1598  std::string shift_name = it3->second->GetName();
1599  shift_name += "_" + std::to_string(k);
1600  TH1D * temp_hist = (TH1D*)it3->second->Clone(shift_name.c_str());
1601  temp_hist->Reset();
1602  it2->second[i][j].AddSystematicShift(temp_hist, it->first,
1603  it3->first);
1604  }
1605  }
1606  }
1607  }
1608  }
1609  }
1610 
1611  for (size_t i = 0; i < events.size(); ++i) {
1612  const ThinSliceEvent & event = events.at(i);
1613  int sample_ID = event.GetSampleID();
1614  int selection_ID = event.GetSelectionID();
1615 
1616  double reco_beam_endZ = event.GetRecoEndZ();
1617 
1618  const std::vector<double> & reco_beam_incidentEnergies
1619  = event.GetRecoIncidentEnergies();
1620  //double beam_inst_P = event.GetBeamInstP();
1621  double reco_beam_interactingEnergy = event.GetRecoInteractingEnergy();
1622 
1623  double end_energy = event.GetTrueInteractingEnergy();
1624  double true_beam_endP = event.GetTrueEndP();
1625  double true_beam_startP = event.GetTrueStartP();
1626  const std::vector<double> & true_beam_traj_Z = event.GetTrueTrajZ();
1627  if (fSliceMethod == "Traj") {
1628  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
1629  }
1630  else if (fSliceMethod == "E") {
1631  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
1632  }
1633  else if (fSliceMethod == "Alt") {
1634  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z.back());
1635  if (bin > 0)
1636  end_energy = fMeans.at(bin);
1637  }
1638 
1639  if (samples.find(sample_ID) == samples.end()) {
1640  std::cout << "Warning: skipping sample " << sample_ID << std::endl;
1641  continue;
1642  }
1643 
1644  int bin = GetBeamBin(beam_energy_bins, true_beam_startP);
1645 
1646 
1647  std::vector<ThinSliceSample> & samples_vec = samples.at(sample_ID)[bin];
1648  bool is_signal = signal_sample_checks.at(sample_ID);
1649 
1650  ThinSliceSample * this_sample = 0x0;
1651  if (!is_signal) {
1652  this_sample = &samples_vec.at(0);
1653  }
1654  else {
1655  //Iterate through the true bins and find the correct one
1656  bool found = false;
1657  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
1658  ThinSliceSample & sample = samples_vec.at(j);
1659  if (sample.CheckInSignalRange(end_energy)) {
1660  this_sample = &sample;
1661  found = true;
1662  break;
1663  }
1664  }
1665  if (!found) {
1666  //over/underflow here
1667  if (end_energy <= samples_vec[1].RangeLowEnd()) {
1668  this_sample = &samples_vec[0];
1669  }
1670  else if (end_energy >
1671  samples_vec[samples_vec.size()-2].RangeHighEnd()) {
1672  this_sample = &samples_vec.back();
1673  }
1674  else {
1675  std::cout << "Warning: could not find true bin " <<
1676  end_energy << std::endl;
1677  }
1678  }
1679  }
1680 
1681  std::vector<double> vals;
1682  std::vector<double> weights;
1683  if (!is_grid) {
1684  vals = std::vector<double>(2, 0.);
1685  weights = {event.GetG4RWWeight(minus_branch, position),
1686  event.GetG4RWWeight(plus_branch, position)};
1687  }
1688  else {
1689  if (event.HasG4RWBranch(grid_branch)) {
1690  if (!event.GetG4RWBranch(grid_branch).size()) {
1691  weights = std::vector<double>(syst_vals.size(), 1.);
1692  vals = std::vector<double>(syst_vals.size(), 0.);
1693  }
1694  else {
1695  weights = event.GetG4RWBranch(grid_branch);
1696  vals = std::vector<double>(weights.size(), 0.);
1697  }
1698  }
1699  else {
1700  weights = std::vector<double>(syst_vals.size(), 1.);
1701  vals = std::vector<double>(syst_vals.size(), 0.);
1702  }
1703  weights.erase(weights.begin() + ((weights.size()-1)/2));
1704  vals.erase(vals.begin() + ((vals.size()-1)/2));
1705  }
1706 
1707  TH1D * selected_hist = (TH1D*)this_sample->GetSelectionHist(selection_ID);
1708  if (selection_ID == 4) {
1709  if (selected_hist->FindBin(reco_beam_endZ) == 0) {
1710  for (double & v : vals) v = selected_hist->GetBinCenter(1);
1711  }
1712  else if (selected_hist->FindBin(reco_beam_endZ) >
1713  selected_hist->GetNbinsX()) {
1714  for (double & v : vals)
1715  v = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
1716  }
1717  else {
1718  for (double & v : vals) v = reco_beam_endZ;
1719  }
1720  }
1721  else if (selection_ID > 4) {
1722  for (double & v : vals) v = .5;
1723  }
1724  else if (reco_beam_incidentEnergies.size()) {
1725  double energy = reco_beam_interactingEnergy;
1726  if (fDoEnergyFix) {
1727  for (size_t k = 1; k < reco_beam_incidentEnergies.size(); ++k) {
1728  double deltaE = ((reco_beam_incidentEnergies)[k-1] -
1729  (reco_beam_incidentEnergies)[k]);
1730  if (deltaE > fEnergyFix) {
1731  energy += deltaE;
1732  }
1733  }
1734  }
1735  if (selected_hist->FindBin(energy) == 0) {
1736  for (double & v : vals) v = selected_hist->GetBinCenter(1);
1737  }
1738  else if (selected_hist->FindBin(energy) >
1739  selected_hist->GetNbinsX()) {
1740  for (double & v : vals)
1741  v = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
1742  }
1743  else {
1744  for (double & v : vals) v = energy;
1745  }
1746  }
1747  else {
1748  for (double & v : vals) v = selected_hist->GetBinCenter(1);
1749  }
1750  this_sample->FillSystematicShift(it->first, selection_ID, vals, weights);
1751  }
1752  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
1753  for (size_t i = 0; i < it2->second.size(); ++i) {
1754  for (size_t j = 0; j < it2->second[i].size(); ++j) {
1755  it2->second[i][j].SetSystematicVals(it->first, syst_vals);
1756  it2->second[i][j].MakeSystematicSplines(it->first);
1757  it2->second[i][j].SaveSystematics(it->first, dir);
1758  }
1759  }
1760  }
1761  }
1762 
1763 }
1764 
1766  const std::vector<ThinSliceEvent> & events,
1767  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
1768  const std::map<std::string, ThinSliceSystematic> & pars,
1769  TFile & output_file) {
1770 
1771  //Get the systematic variations to the calibration constant
1772  //then build systematic shift hists
1773  std::vector<double> C_cal_vars
1774  = pars.at("dEdX_Cal_Spline").GetOption<std::vector<double>>("C_cal_vars");
1775 
1776  //make sure the number of shifts are even
1777  //such that you have same number +/-
1778  if (C_cal_vars.size() % 2) {
1779  std::string message = "SetupSyst_dEdX_Cal Error: ";
1780  message += "odd number of variations to cal constant";
1781  throw std::runtime_error(message);
1782  }
1783 
1784  TFile template_file(
1785  pars.at("dEdX_Cal_Spline").GetOption<std::string>("TemplateFile").c_str());
1786  TProfile * prot_template = (TProfile*)template_file.Get("dedx_range_pro");
1787 
1788  //Get the first sample and get the selection hists
1789  //also make full hist
1790  std::map<int, TH1D*> full_hists;
1791 
1792  ThinSliceSample & temp_sample = samples.begin()->second[0][0];
1793  const std::map<int, TH1*> & sel_hists = temp_sample.GetSelectionHists();
1794  for (auto it = sel_hists.begin(); it != sel_hists.end(); ++it) {
1795  std::string sel_hist_name = it->second->GetName();
1796  sel_hist_name += "Syst_dEdX_Cal_Spline";
1797  int shift_number = -2;
1798 
1799  fFullSelectionVars["dEdX_Cal_Spline"][it->first] = std::vector<TH1D*>();
1800  for (size_t k = 0; k < C_cal_vars.size(); ++k) {
1801  std::string shift_name = sel_hist_name;
1802  shift_name += std::to_string(shift_number);
1803  fFullSelectionVars["dEdX_Cal_Spline"][it->first].push_back((TH1D*)it->second->Clone(shift_name.c_str()));
1804  fFullSelectionVars["dEdX_Cal_Spline"][it->first].back()->Reset();
1805 
1806  ++shift_number;
1807  if (shift_number == 0)
1808  ++shift_number;
1809  }
1810 
1811  sel_hist_name += "_FullVar";
1812  full_hists[it->first] = (TH1D*)it->second->Clone(sel_hist_name.c_str());
1813  full_hists[it->first]->Reset();
1814  }
1815 
1816  for (size_t i = 0; i < events.size(); ++i) {
1817  const ThinSliceEvent & event = events.at(i);
1818  int sample_ID = event.GetSampleID();
1819  //int selection_ID = event.GetSelectionID();
1820 
1821  std::vector<int> new_selection_IDs;
1822  for (double c : C_cal_vars) {
1823 
1824  int new_selection_ID = RecalculateSelectionID(
1825  event,
1826  /*(pars.at("dEdX_Cal_Spline").GetCentral()/c),*/
1827  (1./c),
1828  prot_template);
1829  new_selection_IDs.push_back(new_selection_ID);
1830  //std::cout << "\t" << c << " " <<
1831  // pars.at("dEdX_Cal_Spline").GetValue() << std::endl;
1832  //if (new_selection_ID != selection_ID) {
1833  // std::cout << "\tDiff selection " << selection_ID << " " << new_selection_ID << std::endl;
1834  //}
1835  }
1836  double reco_beam_endZ = event.GetRecoEndZ();
1837 
1838  const std::vector<double> & reco_beam_incidentEnergies
1839  = event.GetRecoIncidentEnergies();
1840  double beam_inst_P = event.GetBeamInstP();
1841  const std::vector<double> calibrated_dQdX
1842  = event.GetdQdXCalibrated();
1843  const std::vector<double> beam_EField
1844  = event.GetEField();
1845  const std::vector<double> track_pitch
1846  = event.GetTrackPitch();
1847 
1848 
1849  if (samples.find(sample_ID) == samples.end()) {
1850  std::cout << "Warning: skipping sample " << sample_ID << std::endl;
1851  continue;
1852  }
1853 
1854  std::vector<double> vals(C_cal_vars.size(), 0.);
1855  for (size_t j = 0; j < vals.size(); ++j) {
1856  int new_selection_ID = new_selection_IDs[j];
1857  if (new_selection_ID == 4) {
1858  TH1D * selected_hist
1859  = fFullSelectionVars["dEdX_Cal_Spline"][new_selection_ID][0];
1860  if (selected_hist->FindBin(reco_beam_endZ) == 0) {
1861  //for (double & v : vals) v = selected_hist->GetBinCenter(1);
1862  vals[j] = selected_hist->GetBinCenter(1);
1863  }
1864  else if (selected_hist->FindBin(reco_beam_endZ) >
1865  selected_hist->GetNbinsX()) {
1866  //for (double & v : vals)
1867  // v = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
1868  vals[j] = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
1869  }
1870  else {
1871  //for (double & v : vals) v = reco_beam_endZ;
1872  vals[j] = reco_beam_endZ;
1873  }
1874  }
1875  else if (new_selection_ID > 4) {
1876  //for (double & v : vals) v = .5;
1877  vals[j] = .5;
1878  }
1879  else if (reco_beam_incidentEnergies.size()) {
1880  //for (size_t j = 0; j < C_cal_vars.size(); ++j) {
1881  double energy = sqrt(beam_inst_P*beam_inst_P*1.e6 + 139.57*139.57) -
1882  139.57;
1883  //limits?
1884  for (size_t k = 0; k < calibrated_dQdX.size()-1; ++k) {
1885  if ((calibrated_dQdX)[k] < 0.) continue;
1886 
1887  double dedx = (C_cal_vars[j]);/*(pars.at("dEdX_Cal_Spline").GetCentral()/C_cal_vars[j]);*/
1888  dedx *= (calibrated_dQdX)[k];
1889  dedx *= (fBetaP / ( fRho * (beam_EField)[k] ) * fWion);
1890  dedx = exp(dedx);
1891  dedx -= fAlpha;
1892  dedx *= ((fRho*(beam_EField)[k])/fBetaP);
1893 
1894  if (dedx*(track_pitch)[k] > fEnergyFix)
1895  continue;
1896  energy -= dedx*(track_pitch)[k];
1897 
1898  }
1899  TH1D * selected_hist
1900  = fFullSelectionVars["dEdX_Cal_Spline"][new_selection_ID][0];
1901  if (selected_hist->FindBin(energy) == 0) {
1902  vals[j] = selected_hist->GetBinCenter(1);
1903  }
1904  else if (selected_hist->FindBin(energy) >
1905  selected_hist->GetNbinsX()) {
1906  vals[j] = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
1907  }
1908  else {
1909  vals[j] = energy;
1910  }
1911  //}
1912  }
1913  else {
1914  TH1D * selected_hist
1915  = fFullSelectionVars["dEdX_Cal_Spline"][new_selection_ID][0];
1916  //for (double & v : vals) v = selected_hist->GetBinCenter(1);
1917  vals[j] = selected_hist->GetBinCenter(1);
1918  }
1919  //for (size_t j = 0; j < vals.size(); ++j) {
1920  fFullSelectionVars["dEdX_Cal_Spline"][new_selection_ID][j]->Fill(vals[j]);
1921  //}
1922  }
1923  }
1924 
1925  C_cal_vars.insert(C_cal_vars.begin() + C_cal_vars.size()/2,
1926  pars.at("dEdX_Cal_Spline").GetCentral());
1927 
1928  TDirectory * dir = output_file.mkdir("dEdX_Cal_Spline_Syst");
1929  dir->cd();
1930 
1931  //Take the vars and make into ratios, then turn into splines
1932  for (auto it = fFullSelectionVars["dEdX_Cal_Spline"].begin();
1933  it != fFullSelectionVars["dEdX_Cal_Spline"].end(); ++it) {
1934  int selection_ID = it->first;
1935 
1936  //Build the full hist
1937  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
1938  for (size_t i = 0; i < it2->second.size(); ++i) {
1939  for (size_t j = 0; j < it2->second[i].size(); ++j) {
1940  full_hists[selection_ID]->Add(it2->second[i][j].GetSelectionHist(
1941  selection_ID));
1942  }
1943  }
1944  }
1945 
1946  for (size_t i = 0; i < it->second.size(); ++i) {
1947  it->second[i]->Write();
1948  it->second[i]->Divide(full_hists[selection_ID]);
1949  }
1950 
1951  fFullSelectionSplines["dEdX_Cal_Spline"][selection_ID] = std::vector<TSpline3*>();
1952  for (int i = 1; i <= full_hists[selection_ID]->GetNbinsX(); ++i) {
1953  std::vector<double> vals;
1954  for (size_t j = 0; j < it->second.size(); ++j) {
1955  vals.push_back(it->second[j]->GetBinContent(i));
1956  }
1957  vals.insert(vals.begin() + vals.size()/2, 1.);
1958 
1959  std::string spline_name = full_hists[selection_ID]->GetName();
1960  spline_name += "_Spline" + std::to_string(i);
1961 
1962  fFullSelectionSplines["dEdX_Cal_Spline"][selection_ID].push_back(
1963  new TSpline3(spline_name.c_str(), &C_cal_vars[0], &vals[0], vals.size()));
1964  TCanvas c(spline_name.c_str(), "");
1965  fFullSelectionSplines["dEdX_Cal_Spline"][selection_ID].back()->SetMarkerStyle(20);
1966  fFullSelectionSplines["dEdX_Cal_Spline"][selection_ID].back()->Draw("P");
1967  c.Write();
1968  fFullSelectionSplines["dEdX_Cal_Spline"][selection_ID].back()->Write(spline_name.c_str());
1969  }
1970  }
1971 }
1972 
1974  const std::vector<ThinSliceEvent> & events,
1975  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
1976  const std::map<std::string, ThinSliceSystematic> & pars,
1977  TFile & output_file) {
1978 
1979  if (pars.find("beam_shift_spline_2") == pars.end()) {
1980  return;
1981  }
1982 
1983  //Get the systematic variations to the calibration constant
1984  //then build systematic shift hists
1985  std::vector<double> beam_shift_vals
1986  = pars.at("beam_shift_spline_2").GetOption<std::vector<double>>("ShiftVals");
1987 
1988  //make sure the number of shifts are even
1989  //such that you have same number +/-
1990  if (beam_shift_vals.size() % 2) {
1991  std::string message = "SetupSyst_BeamShiftSpline2 Error: ";
1992  message += "odd number of shifts to reco momentum";
1993  throw std::runtime_error(message);
1994  }
1995 
1996  //Get the first sample and get the selection hists
1997  //also make full hist
1998  std::map<int, TH1D*> full_hists;
1999 
2000  ThinSliceSample & temp_sample = samples.begin()->second[0][0];
2001  const std::map<int, TH1*> & sel_hists = temp_sample.GetSelectionHists();
2002  for (auto it = sel_hists.begin(); it != sel_hists.end(); ++it) {
2003  std::string sel_hist_name = it->second->GetName();
2004  sel_hist_name += "Syst_BeamShiftSpline2";
2005  int shift_number = -2;
2006 
2007  fFullSelectionVars["BeamShiftSpline2"][it->first] = std::vector<TH1D*>();
2008  for (size_t k = 0; k < beam_shift_vals.size(); ++k) {
2009  std::string shift_name = sel_hist_name;
2010  shift_name += std::to_string(shift_number);
2011  fFullSelectionVars["BeamShiftSpline2"][it->first].push_back((TH1D*)it->second->Clone(shift_name.c_str()));
2012  fFullSelectionVars["BeamShiftSpline2"][it->first].back()->Reset();
2013 
2014  ++shift_number;
2015  if (shift_number == 0)
2016  ++shift_number;
2017  }
2018 
2019  sel_hist_name += "_FullVar";
2020  full_hists[it->first] = (TH1D*)it->second->Clone(sel_hist_name.c_str());
2021  full_hists[it->first]->Reset();
2022  }
2023 
2024  for (size_t i = 0; i < events.size(); ++i) {
2025  const ThinSliceEvent & event = events.at(i);
2026  int sample_ID = event.GetSampleID();
2027  int selection_ID = event.GetSelectionID();
2028 
2029  double reco_beam_endZ = event.GetRecoEndZ();
2030 
2031  const std::vector<double> & reco_beam_incidentEnergies
2032  = event.GetRecoIncidentEnergies();
2033  double beam_inst_P = event.GetBeamInstP();
2034  const std::vector<double> calibrated_dQdX
2035  = event.GetdQdXCalibrated();
2036  const std::vector<double> beam_EField
2037  = event.GetEField();
2038  const std::vector<double> track_pitch
2039  = event.GetTrackPitch();
2040 
2041 
2042  if (samples.find(sample_ID) == samples.end()) {
2043  std::cout << "Warning: skipping sample " << sample_ID << std::endl;
2044  continue;
2045  }
2046 
2047  std::vector<double> vals(beam_shift_vals.size(), 0.);
2048  for (size_t j = 0; j < vals.size(); ++j) {
2049  if (selection_ID == 4) {
2050  TH1D * selected_hist
2051  = fFullSelectionVars["BeamShiftSpline2"][selection_ID][0];
2052  if (selected_hist->FindBin(reco_beam_endZ) == 0) {
2053  vals[j] = selected_hist->GetBinCenter(1);
2054  }
2055  else if (selected_hist->FindBin(reco_beam_endZ) >
2056  selected_hist->GetNbinsX()) {
2057  vals[j] = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
2058  }
2059  else {
2060  vals[j] = reco_beam_endZ;
2061  }
2062  }
2063  else if (selection_ID > 4) {
2064  vals[j] = .5;
2065  }
2066  else if (reco_beam_incidentEnergies.size()) {
2067  //get the energy -- have to do some manipulation for the
2068  //momentum shift variation and getting back to KE
2069  double energy
2070  = sqrt(std::pow(beam_inst_P*beam_shift_vals[j], 2)*1.e6 +
2071  139.57*139.57) - 139.57;
2072 
2073  if (fDoEnergyFix) {
2074  for (size_t k = 1; k < reco_beam_incidentEnergies.size(); ++k) {
2075  double deltaE = (reco_beam_incidentEnergies[k-1] -
2076  reco_beam_incidentEnergies[k]);
2077  if (deltaE > fEnergyFix)
2078  continue;
2079  energy -= deltaE;
2080  }
2081  }
2082 
2083 
2084  TH1D * selected_hist
2085  = fFullSelectionVars["BeamShiftSpline2"][selection_ID][0];
2086  if (selected_hist->FindBin(energy) == 0) {
2087  vals[j] = selected_hist->GetBinCenter(1);
2088  }
2089  else if (selected_hist->FindBin(energy) >
2090  selected_hist->GetNbinsX()) {
2091  vals[j] = selected_hist->GetBinCenter(selected_hist->GetNbinsX());
2092  }
2093  else {
2094  vals[j] = energy;
2095  }
2096  }
2097  else {
2098  TH1D * selected_hist
2099  = fFullSelectionVars["BeamShiftSpline2"][selection_ID][0];
2100  vals[j] = selected_hist->GetBinCenter(1);
2101  }
2102  fFullSelectionVars["BeamShiftSpline2"][selection_ID][j]->Fill(vals[j]);
2103  }
2104  }
2105 
2106  beam_shift_vals.insert(beam_shift_vals.begin() + beam_shift_vals.size()/2,
2107  pars.at("beam_shift_spline_2").GetCentral());
2108 
2109  TDirectory * dir = output_file.mkdir("BeamShiftSpline2_Syst");
2110  dir->cd();
2111 
2112  //Take the vars and make into ratios, then turn into splines
2113  for (auto it = fFullSelectionVars["BeamShiftSpline2"].begin();
2114  it != fFullSelectionVars["BeamShiftSpline2"].end(); ++it) {
2115  int selection_ID = it->first;
2116 
2117  //Build the full hist
2118  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
2119  for (size_t i = 0; i < it2->second.size(); ++i) {
2120  for (size_t j = 0; j < it2->second[i].size(); ++j) {
2121  full_hists[selection_ID]->Add(it2->second[i][j].GetSelectionHist(
2122  selection_ID));
2123  }
2124  }
2125  }
2126 
2127  for (size_t i = 0; i < it->second.size(); ++i) {
2128  it->second[i]->Write();
2129  it->second[i]->Divide(full_hists[selection_ID]);
2130  }
2131 
2132  fFullSelectionSplines["BeamShiftSpline2"][selection_ID] = std::vector<TSpline3*>();
2133  for (int i = 1; i <= full_hists[selection_ID]->GetNbinsX(); ++i) {
2134  std::vector<double> vals;
2135  for (size_t j = 0; j < it->second.size(); ++j) {
2136  vals.push_back(it->second[j]->GetBinContent(i));
2137  }
2138  vals.insert(vals.begin() + vals.size()/2, 1.);
2139 
2140  std::string spline_name = full_hists[selection_ID]->GetName();
2141  spline_name += "_Spline" + std::to_string(i);
2142 
2143  fFullSelectionSplines["BeamShiftSpline2"][selection_ID].push_back(
2144  new TSpline3(spline_name.c_str(), &beam_shift_vals[0], &vals[0], vals.size()));
2145  TCanvas c(spline_name.c_str(), "");
2146  fFullSelectionSplines["BeamShiftSpline2"][selection_ID].back()->SetMarkerStyle(20);
2147  fFullSelectionSplines["BeamShiftSpline2"][selection_ID].back()->Draw("P");
2148  c.Write();
2149  fFullSelectionSplines["BeamShiftSpline2"][selection_ID].back()->Write(spline_name.c_str());
2150  }
2151  }
2152 }
2153 
2155  const std::vector<ThinSliceEvent> & events,
2156  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
2157  const std::map<std::string, ThinSliceSystematic> & pars,
2158  TFile & output_file) {
2159  if (pars.find("beam_shift_ratio") == pars.end()) {
2160  return;
2161  }
2162  //std::pair<double, double>> limits
2163  // = pars.at("beam_shift_ratio").GetOption<std::pair<double, double>>(
2164  // "Limits");
2165  int nBins = pars.at("beam_shift_ratio").GetOption<int>("nBins");
2166  std::pair<double, double> binning
2167  = pars.at("beam_shift_ratio").GetOption<std::pair<double, double>>(
2168  "Binning");
2169  fBeamShiftRatioNomHist = TH1D("fBeamShiftRatioNomHist", "", nBins,
2170  binning.first, binning.second);
2171  std::vector<double> vals
2172  = pars.at("beam_shift_ratio").GetOption<std::vector<double>>("Vals");
2173 
2174  std::vector<TH1D*> var_hists;
2175  for (size_t i = 0; i < vals.size(); ++i) {
2176  std::string name = "fBeamShiftRatioVarHist" + std::to_string(i);
2177  var_hists.push_back(new TH1D(name.c_str(), "", nBins,
2178  binning.first, binning.second));
2179  }
2180 
2181  for (size_t i = 0; i < events.size(); ++i) {
2182  const ThinSliceEvent & event = events.at(i);
2183  double beam_inst_P = event.GetBeamInstP();
2184  fBeamShiftRatioNomHist.Fill(beam_inst_P);
2185  for (size_t j = 0; j < vals.size(); ++j) {
2186  var_hists[j]->Fill(vals[j]*beam_inst_P);
2187  }
2188  }
2189 
2190  TDirectory * dir = output_file.mkdir("BeamShiftRatio_Syst");
2191  dir->cd();
2192  std::vector<TSpline3*> fBeamShiftRatioSplines;
2193  for (int i = 0; i < nBins + 2; ++i) { //+2 for over/underflow
2194  std::vector<double> ratios;
2195  for (size_t j = 0; j < var_hists.size(); ++j) {
2196  ratios.push_back(
2197  fBeamShiftRatioNomHist.GetBinContent(i)/
2198  var_hists[j]->GetBinContent(i));
2199  }
2200 
2201  std::string name = "fBeamShiftRatioSpline" + std::to_string(i);
2202  fBeamShiftRatioSplines.push_back(
2203  new TSpline3(name.c_str(), &vals[0], &ratios[0], ratios.size()));
2204 
2205  TCanvas c(name.c_str(), "");
2206  fBeamShiftRatioSplines.back()->SetMarkerStyle(20);
2207  fBeamShiftRatioSplines.back()->Draw("P");
2208  c.Write();
2209  }
2210 
2211 }
2212 
2214  const ThinSliceEvent & event,
2215  const std::map<std::string, ThinSliceSystematic> & pars,
2216  const ThinSliceSample & sample,
2217  int selection_ID, double val) {
2218  double weight = 1.;
2219  for (std::string & s : fActiveG4RWSysts) {
2220  if (std::isnan(pars.at(s).GetValue())) {
2221  std::string message = "protoana::AbsCexDriver::GetSystWeight_G4RW ";
2222  message += s;
2223  message += " has nan value";
2224  throw std::runtime_error(message);
2225  }
2226  weight *= sample.GetSplineWeight(s, pars.at(s).GetValue(), selection_ID, val);
2227  if (weight < 0.) {
2228  std::cout << "G4RW turned negative for " << s << std::endl;
2229  }
2230  }
2231 
2232  if (weight < 0.) {
2233  std::cout << "Warning: returning negative value for event " <<
2234  event.GetEventID() << " " << event.GetSubrunID() << " " <<
2235  event.GetRunID() << std::endl;
2236  }
2237  return weight;
2238 }
2239 
2241  const ThinSliceEvent & event,
2242  const std::map<std::string, ThinSliceSystematic> & pars) {
2243  if (pars.find("beam_shift") == pars.end()) return 1.;
2244  if (event.GetPDG() != 211) return 1.;
2245  double x_val = pars.at("beam_shift").GetValue();
2246  double y_val = (event.GetBeamInstP() - event.GetTrueStartP())/
2247  event.GetTrueStartP();
2248  if (y_val < fSystBeamShiftLimits.first/*fSystBeamShiftMap->GetYmin()*/ ||
2249  y_val > fSystBeamShiftLimits.second/*fSystBeamShiftMap->GetYmax()*/) {
2250  return 1.;
2251  }
2252 
2253  double nominal_mean = fSystBeamShiftMeans->Eval(0.);
2254  double nominal_width = fSystBeamShiftWidths->Eval(0.);
2255  double varied_mean = fSystBeamShiftMeans->Eval(x_val);
2256  double varied_width = fSystBeamShiftWidths->Eval(x_val);
2257 
2258  //double weight = 1.;
2259 
2260  /*
2261  if (y_val > fSystBeamShiftRatioLimitUp) {
2262  if (x_val != 0.) std::cout << x_val << " Past limit: " << y_val << " ";
2263  weight = ROOT::Math::normal_cdf_c(y_val, varied_width, varied_mean);
2264  if (x_val != 0.) std::cout << weight << " ";
2265  weight /= ROOT::Math::normal_cdf_c(y_val, nominal_width, nominal_mean);
2266  if (x_val != 0.) std::cout << weight << std::endl;
2267  }
2268  else if (y_val < fSystBeamShiftRatioLimitDown) {
2269  if (x_val != 0.) std::cout << x_val << " Past limit: " << y_val << " ";
2270  weight = ROOT::Math::normal_cdf(y_val, varied_width, varied_mean);
2271  if (x_val != 0.) std::cout << weight << " ";
2272  weight /= ROOT::Math::normal_cdf(y_val, nominal_width, nominal_mean);
2273  if (x_val != 0.) std::cout << weight << std::endl;
2274  }
2275  else {*/
2276  double weight = (nominal_width/varied_width)*
2277  exp(.5*std::pow(((y_val - nominal_mean)/nominal_width), 2)
2278  - .5*std::pow(((y_val - varied_mean)/varied_width), 2));
2279 
2280  if (weight > fSystBeamShiftWeightCap && fSystBeamShiftWeightCap > 0.) {
2281  //std::cout << "Weight above cap: " << weight << " " << x_val <<
2282  // " event: " << event.GetEventID() << std::endl;
2283  weight = fSystBeamShiftWeightCap;
2284  }
2285  //}
2286 
2287  //fSystBeamShiftWeight = fSystBeamShiftMap->Interpolate(x_val, y_val);
2288  if (fSystBeamShiftTreeSave) {
2290  fSystBeamShiftVal = x_val;
2291  fSystBeamShiftR = y_val;
2292  fSystBeamShiftTree->Fill();
2293  }
2294  return weight;
2295 }
2296 
2297 /*
2298 double protoana::AbsCexDriver::GetSystWeight_BeamShift2D(
2299  const ThinSliceEvent & event,
2300  const std::map<std::string, ThinSliceSystematic> & pars) {
2301  bool has_shift = pars.find("beam_2D_shift") != pars.end();
2302  bool has_B = pars.find("beam_2D_B") != pars.end();
2303  if (!has_shift && !has_B) return 1.;
2304  if (event.GetPDG() != 211) return 1.;
2305 
2306  double x_val = (has_B ? pars.at("beam_2D_B").GetValue() : 0.);
2307  double y_val = (has_shift ? pars.at("beam_2D_shift").GetValue() : 0.);
2308 
2309  double r_val = (event.GetBeamInstP() - event.GetTrueStartP())/
2310  event.GetTrueStartP();
2311  if (abs(r_val) > .2) {
2312  return 1.;
2313  }
2314 
2315  double nominal_mean = fSystBeam2DMeans->Interpolate(0., 0.);
2316  double nominal_std_dev = fSystBeam2DStdDevs->Interpolate(0., 0.);
2317  double varied_mean = fSystBeam2DMeans->Interpolate(x_val, y_val);
2318  double varied_std_dev = fSystBeam2DStdDevs->Interpolate(x_val, y_val);
2319 
2320  double weight = (nominal_std_dev/varied_std_dev)*
2321  exp(.5*std::pow(((r_val - nominal_mean)/nominal_std_dev), 2)
2322  - .5*std::pow(((r_val - varied_mean)/varied_std_dev), 2));
2323  if (isnan(weight)) {
2324  std::cout << "WARNING: RETURNED NAN " << weight << " " <<
2325  varied_mean << " " << varied_std_dev << " " << x_val <<
2326  " " << y_val << std::endl;
2327  }
2328 
2329  //if (fSystBeamShiftMap->Interpolate(x_val, y_val) < 0.) {
2330  // std::cout << "WARNING: Interpolated " << x_val << " " << y_val <<
2331  // fSystBeamShiftMap->Interpolate(x_val, y_val) << std::endl;
2332  //}
2333  //else if (isnan(fSystBeamShiftMap->Interpolate(x_val, y_val))) {
2334  // std::cout << "WARNING: Interpolated " << x_val << " " << y_val <<
2335  // fSystBeamShiftMap->Interpolate(x_val, y_val) << std::endl;
2336  //}
2337 
2338  fSystBeamShift2DWeight = weight;
2339  fSystBeamShift2DBVal = x_val;
2340  fSystBeamShift2DVal = y_val;
2341  fSystBeamShift2DR = r_val;
2342  fSystBeamShift2DTree->Fill();
2343  return weight;//fSystBeamShiftMap->Interpolate(x_val, y_val);
2344 }*/
2345 
2347  TTree * tree, ThinSliceDataSet & data_set, double & flux,
2348  int split_val) {
2349  int selection_ID;
2350  double reco_beam_interactingEnergy, reco_beam_endZ;
2351  std::vector<double> * reco_beam_incidentEnergies = 0x0;
2352  tree->SetBranchAddress("selection_ID", &selection_ID);
2353  tree->SetBranchAddress("reco_beam_interactingEnergy",
2354  &reco_beam_interactingEnergy);
2355  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
2356  tree->SetBranchAddress("reco_beam_incidentEnergies",
2357  &reco_beam_incidentEnergies);
2358  double beam_inst_P;
2359  tree->SetBranchAddress("beam_inst_P", &beam_inst_P);
2360 
2361  TH1D & incident_hist = data_set.GetIncidentHist();
2362  std::map<int, TH1 *> & selected_hists = data_set.GetSelectionHists();
2363 
2364  flux = tree->GetEntries() - split_val;
2365 
2366  for (int i = /*0*/split_val; i < tree->GetEntries(); ++i) {
2367  tree->GetEntry(i);
2368  //if (beam_fluxes) beam
2369  double val = 0.;
2370  if (selection_ID == 4) {
2371  if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) == 0) {
2372  val = selected_hists[selection_ID]->GetBinCenter(1);
2373  }
2374  else if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) >
2375  selected_hists[selection_ID]->GetNbinsX()) {
2376  val = selected_hists[selection_ID]->GetBinCenter(
2377  selected_hists[selection_ID]->GetNbinsX());
2378  }
2379  else {
2380  val = reco_beam_endZ;
2381  }
2382  }
2383  else if (selection_ID > 4) {
2384  val = .5;
2385  }
2386  else if (reco_beam_incidentEnergies->size()) {
2387  for (size_t j = 0; j < reco_beam_incidentEnergies->size(); ++j) {
2388  incident_hist.Fill((*reco_beam_incidentEnergies)[j]);
2389  }
2390  if (selected_hists.find(selection_ID) != selected_hists.end()) {
2391  if (selection_ID != 4 && selection_ID != 5 && selection_ID != 6) {
2392  double energy = reco_beam_interactingEnergy;
2393  if (fDoEnergyFix) {
2394  for (size_t k = 1; k < reco_beam_incidentEnergies->size(); ++k) {
2395  double deltaE = ((*reco_beam_incidentEnergies)[k-1] -
2396  (*reco_beam_incidentEnergies)[k]);
2397  if (deltaE > fEnergyFix) {
2398  energy += deltaE;
2399  }
2400  }
2401  }
2402  if (selected_hists[selection_ID]->FindBin(energy) == 0) {
2403  val = selected_hists[selection_ID]->GetBinCenter(1);
2404  }
2405  else if (selected_hists[selection_ID]->FindBin(energy) >
2406  selected_hists[selection_ID]->GetNbinsX()) {
2407  val = selected_hists[selection_ID]->GetBinCenter(
2408  selected_hists[selection_ID]->GetNbinsX());
2409  }
2410  else {
2411  val = energy;
2412  }
2413  }
2414  }
2415  }
2416  else {
2417  val = selected_hists[selection_ID]->GetBinCenter(1);
2418  }
2419 
2420  selected_hists[selection_ID]->Fill(val);
2421  }
2422 
2423 }
2424 
2426  TTree * tree,
2427  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
2428  const std::map<int, bool> & signal_sample_checks,
2429  ThinSliceDataSet & data_set, double & flux,
2430  std::map<int, std::vector<double>> & sample_scales,
2431  std::vector<double> & beam_energy_bins,
2432  int split_val) {
2433  std::string routine = fExtraOptions.get<std::string>("FakeDataRoutine");
2434  if (routine == "SampleScales") {
2435  FakeDataSampleScales(tree, samples, signal_sample_checks, data_set, flux,
2436  sample_scales, split_val);
2437  }
2438  else if (routine == "G4RW") {
2439  FakeDataG4RW(tree, samples, signal_sample_checks, data_set, flux,
2440  sample_scales, split_val);
2441  }
2442  else if (routine == "G4RWGrid") {
2443  FakeDataG4RWGrid(tree, samples, signal_sample_checks, data_set, flux,
2444  sample_scales, beam_energy_bins,
2445  split_val);
2446  }
2447  else if (routine == "EffVar") {
2448  FakeDataEffVar(tree, samples, signal_sample_checks, data_set, flux,
2449  sample_scales, split_val);
2450  }
2451  else if (routine == "BinnedScales") {
2452  FakeDataBinnedScales(tree, samples, signal_sample_checks, data_set, flux,
2453  sample_scales, split_val);
2454  }
2455  else if (routine == "dEdX") {
2456  FakeDatadEdX(tree, samples, signal_sample_checks, data_set, flux,
2457  sample_scales, split_val);
2458  }
2459  else if (routine == "PionAngle") {
2460  FakeDataPionAngle(tree, samples, signal_sample_checks, data_set, flux,
2461  sample_scales, split_val);
2462  }
2463  else if (routine == "AngleVar") {
2464  FakeDataAngleVar(tree, samples, signal_sample_checks, data_set, flux,
2465  sample_scales, split_val);
2466  }
2467  else if (routine == "BeamWeight") {
2468  FakeDataBeamWeight(tree, samples, signal_sample_checks, data_set, flux,
2469  sample_scales, split_val);
2470  }
2471 }
2472 
2474  TTree * tree,
2475  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
2476  const std::map<int, bool> & signal_sample_checks,
2477  ThinSliceDataSet & data_set, double & flux,
2478  std::map<int, std::vector<double>> & sample_scales,
2479  int split_val) {
2480 
2481 
2482  //Build the map for fake data scales
2483  std::vector<std::pair<int, double>> temp_vec
2484  = fExtraOptions.get<std::vector<std::pair<int, double>>>(
2485  "FakeDataScales");
2486  std::map<int, double> fake_data_scales(temp_vec.begin(), temp_vec.end());
2487 
2488  int sample_ID, selection_ID;
2489  double true_beam_interactingEnergy, reco_beam_interactingEnergy;
2490  double true_beam_endP;
2491  std::vector<double> * reco_beam_incidentEnergies = 0x0,
2492  * true_beam_traj_KE = 0x0,
2493  * true_beam_traj_Z = 0x0;
2494  std::vector<int> * true_beam_slices = 0x0;
2495  double reco_beam_endZ;
2496  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
2497  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
2498  tree->SetBranchAddress("selection_ID", &selection_ID);
2499  tree->SetBranchAddress("true_beam_interactingEnergy",
2500  &true_beam_interactingEnergy);
2501  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
2502  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
2503  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
2504  tree->SetBranchAddress("true_beam_slices", &true_beam_slices);
2505  tree->SetBranchAddress("reco_beam_interactingEnergy",
2506  &reco_beam_interactingEnergy);
2507  tree->SetBranchAddress("reco_beam_incidentEnergies",
2508  &reco_beam_incidentEnergies);
2509  std::vector<double> * true_beam_incidentEnergies = 0x0;
2510  tree->SetBranchAddress("true_beam_incidentEnergies",
2511  &true_beam_incidentEnergies);
2512 
2513  TH1D & incident_hist = data_set.GetIncidentHist();
2514  std::map<int, TH1 *> & selected_hists = data_set.GetSelectionHists();
2515 
2516  double new_flux = 0.;
2517  flux = tree->GetEntries() - split_val;
2518 
2519  std::map<int, std::vector<double>> nominal_samples;
2520  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
2521  nominal_samples[it->first] = std::vector<double>(it->second.size(), 0.);
2522  }
2523 
2524  for (int i = split_val; i < tree->GetEntries(); ++i) {
2525  tree->GetEntry(i);
2526 
2527  double end_energy = true_beam_interactingEnergy;
2528  if (fSliceMethod == "Traj") {
2529  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
2530  }
2531  else if (fSliceMethod == "E") {
2532  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
2533  }
2534  else if (fSliceMethod == "Alt") {
2535  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z->back());
2536  if (bin > 0)
2537  end_energy = fMeans.at(bin);
2538  }
2539 
2540  //Add under/overflow check here
2541  if (samples.find(sample_ID) == samples.end())
2542  continue;
2543 
2544  double scale = (fake_data_scales.find(sample_ID) != fake_data_scales.end() ?
2545  fake_data_scales.at(sample_ID) : 1.);
2546 
2547  //If it's signal
2548  //Determine if the over/underflow bin
2549  bool is_signal = signal_sample_checks.at(sample_ID);
2550  ThinSliceSample * this_sample = 0x0;
2551  if (is_signal) {
2552  std::vector<ThinSliceSample> & samples_vec = samples[sample_ID][0];
2553  //Get the samples vec from the first beam energy bin
2554  bool found = false;
2555  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
2556  ThinSliceSample & sample = samples_vec.at(j);
2557  if (sample.CheckInSignalRange(end_energy)) {
2558  found = true;
2559  sample_scales[sample_ID][j] += scale;
2560  nominal_samples[sample_ID][j] += 1.;
2561  this_sample = &sample;
2562  break;
2563  }
2564  }
2565  if (!found) {//If in the under/overflow, just set to 1.
2566 
2567  scale = 1.;
2568  if (end_energy < samples_vec[1].RangeLowEnd()) {
2569  this_sample = &samples_vec[0];
2570  sample_scales[sample_ID][0] += scale;
2571  nominal_samples[sample_ID][0] += 1.;
2572  }
2573  else if (end_energy >
2574  samples_vec[samples_vec.size()-2].RangeHighEnd()) {
2575 
2576  this_sample = &samples_vec.back();
2577  sample_scales[sample_ID].back() += scale;
2578  nominal_samples[sample_ID].back() += 1.;
2579  }
2580  }
2581  }
2582  else {
2583  sample_scales[sample_ID][0] += scale;
2584  nominal_samples[sample_ID][0] += 1.;
2585  this_sample = &samples[sample_ID][0][0];
2586  }
2587 
2588  //this_sample
2589  new_flux += scale; //1 or scaled
2590 
2591  double val = 0.;
2592  if (selection_ID == 4) {
2593  if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) == 0) {
2594  val = selected_hists[selection_ID]->GetBinCenter(1);
2595  }
2596  else if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) >
2597  selected_hists[selection_ID]->GetNbinsX()) {
2598  val = selected_hists[selection_ID]->GetBinCenter(
2599  selected_hists[selection_ID]->GetNbinsX());
2600  }
2601  else {
2602  val = reco_beam_endZ;
2603  }
2604  }
2605  else if (selection_ID > 4) {
2606  val = .5;
2607  }
2608  else if (reco_beam_incidentEnergies->size()) {
2609  for (size_t j = 0; j < reco_beam_incidentEnergies->size(); ++j) {
2610  incident_hist.Fill((*reco_beam_incidentEnergies)[j]);
2611  }
2612  if (selected_hists.find(selection_ID) != selected_hists.end()) {
2613  if (selection_ID != 4 && selection_ID != 5 && selection_ID != 6) {
2614  double energy = reco_beam_interactingEnergy;
2615  if (fDoEnergyFix) {
2616  for (size_t k = 1; k < reco_beam_incidentEnergies->size(); ++k) {
2617  double deltaE = ((*reco_beam_incidentEnergies)[k-1] -
2618  (*reco_beam_incidentEnergies)[k]);
2619  if (deltaE > fEnergyFix) {
2620  energy += deltaE;
2621  }
2622  }
2623  }
2624  if (selected_hists[selection_ID]->FindBin(energy) == 0) {
2625  val = selected_hists[selection_ID]->GetBinCenter(1);
2626  }
2627  else if (selected_hists[selection_ID]->FindBin(energy) >
2628  selected_hists[selection_ID]->GetNbinsX()) {
2629  val = selected_hists[selection_ID]->GetBinCenter(
2630  selected_hists[selection_ID]->GetNbinsX());
2631  }
2632  else {
2633  val = energy;
2634  }
2635  }
2636  }
2637  }
2638  else {
2639  val = selected_hists[selection_ID]->GetBinCenter(1);
2640  }
2641 
2642  selected_hists[selection_ID]->Fill(val, scale);
2643  std::vector<double> good_true_incEnergies = MakeTrueIncidentEnergies(
2644  *true_beam_traj_Z, *true_beam_traj_KE, *true_beam_slices,
2645  *true_beam_incidentEnergies);
2646  //if (fSliceMethod == "Traj") {
2647  // double next_slice_z = fTrajZStart;
2648  // int next_slice_num = 0;
2649  // for (size_t j = 1; j < true_beam_traj_Z->size() - 1; ++j) {
2650  // double z = (*true_beam_traj_Z)[j];
2651  // double ke = (*true_beam_traj_KE)[j];
2652 
2653  // if (z < fTrajZStart) {
2654  // //std::cout << "Skipping " << z << std::endl;
2655  // continue;
2656  // }
2657 
2658  // if (z >= next_slice_z) {
2659  // double temp_z = (*true_beam_traj_Z)[j-1];
2660  // double temp_e = (*true_beam_traj_KE)[j-1];
2661  //
2662  // while (next_slice_z < z && next_slice_num < fSliceCut) {
2663  // double sub_z = next_slice_z - temp_z;
2664  // double delta_e = (*true_beam_traj_KE)[j-1] - ke;
2665  // double delta_z = z - (*true_beam_traj_Z)[j-1]/* - z*/;
2666  // temp_e -= (sub_z/delta_z)*delta_e;
2667  // good_true_incEnergies.push_back(temp_e);
2668  // temp_z = next_slice_z;
2669  // next_slice_z += fPitch;
2670  // ++next_slice_num;
2671  // }
2672  // }
2673  // }
2674  //}
2675  //else if (fSliceMethod == "Default") {
2676  // for (size_t j = 0; j < true_beam_incidentEnergies->size(); ++j) {
2677  // int slice = (*true_beam_slices)[j];
2678  // if (slice > fSliceCut) continue;
2679  // good_true_incEnergies.push_back((*true_beam_incidentEnergies)[j]);
2680  // }
2681  //}
2682  this_sample->AddVariedFlux(scale);
2683  this_sample->AddIncidentEnergies(good_true_incEnergies, scale);
2684  }
2685 
2686  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
2687  for (size_t i = 0; i < it->second.size(); ++i) {
2688  if (it->second[i] > 0.) {
2689  it->second[i] /= nominal_samples[it->first][i];
2690  }
2691  else {
2692  it->second[i] = 1.;
2693  }
2694  it->second[i] *= (flux/new_flux);
2695  }
2696  }
2697 
2698  incident_hist.Scale(flux/new_flux);
2699  for (auto it = selected_hists.begin(); it != selected_hists.end(); ++it) {
2700  it->second->Scale(flux/new_flux);
2701  }
2702 }
2703 
2705  TTree * tree,
2706  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
2707  const std::map<int, bool> & signal_sample_checks,
2708  ThinSliceDataSet & data_set, double & flux,
2709  std::map<int, std::vector<double>> & sample_scales, int split_val) {
2710 
2711  //Build the map for fake data scales
2712  std::vector<std::pair<int, std::vector<double>>> temp_vec
2713  = fExtraOptions.get<std::vector<std::pair<int, std::vector<double>>>>(
2714  "FakeDataBinnedScales");
2715  std::map<int, std::vector<double>> fake_data_scales(temp_vec.begin(), temp_vec.end());
2716 
2717  int sample_ID, selection_ID;
2718  double true_beam_interactingEnergy, reco_beam_interactingEnergy;
2719  double true_beam_endP;
2720  std::vector<double> * reco_beam_incidentEnergies = 0x0,
2721  * true_beam_traj_KE = 0x0,
2722  * true_beam_traj_Z = 0x0;
2723  std::vector<int> * true_beam_slices = 0x0;
2724  double reco_beam_endZ;
2725  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
2726  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
2727  tree->SetBranchAddress("selection_ID", &selection_ID);
2728  tree->SetBranchAddress("true_beam_interactingEnergy",
2729  &true_beam_interactingEnergy);
2730  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
2731  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
2732  tree->SetBranchAddress("true_beam_slices", &true_beam_slices);
2733  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
2734  tree->SetBranchAddress("reco_beam_interactingEnergy",
2735  &reco_beam_interactingEnergy);
2736  tree->SetBranchAddress("reco_beam_incidentEnergies",
2737  &reco_beam_incidentEnergies);
2738  std::vector<double> * true_beam_incidentEnergies = 0x0;
2739  tree->SetBranchAddress("true_beam_incidentEnergies",
2740  &true_beam_incidentEnergies);
2741 
2742  TH1D & incident_hist = data_set.GetIncidentHist();
2743  std::map<int, TH1 *> & selected_hists = data_set.GetSelectionHists();
2744 
2745 
2746  double new_flux = 0.;
2747  flux = tree->GetEntries() - split_val;
2748 
2749  std::map<int, std::vector<double>> nominal_samples;
2750  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
2751  nominal_samples[it->first] = std::vector<double>(it->second.size(), 0.);
2752  }
2753 
2754  for (int i = /*0*/split_val; i < tree->GetEntries(); ++i) {
2755  tree->GetEntry(i);
2756 
2757  double end_energy = true_beam_interactingEnergy;
2758  if (fSliceMethod == "Traj") {
2759  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
2760  }
2761  else if (fSliceMethod == "E") {
2762  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
2763  }
2764  else if (fSliceMethod == "Alt") {
2765  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z->back());
2766  if (bin > 0) {
2767  end_energy = fMeans.at(bin);
2768  }
2769  }
2770 
2771  //Add under/overflow check here
2772  if (samples.find(sample_ID) == samples.end())
2773  continue;
2774  double scale = 1.;
2775 
2776  bool is_scaled = (fake_data_scales.find(sample_ID) !=
2777  fake_data_scales.end());
2778 
2779  //If it's signal
2780  //Determine if the over/underflow bin
2781  bool is_signal = signal_sample_checks.at(sample_ID);
2782  ThinSliceSample * this_sample = 0x0;
2783  if (is_signal) {
2784  std::vector<ThinSliceSample> & samples_vec = samples[sample_ID][0];
2785  //Get the samples vec from the first beam energy bin
2786  bool found = false;
2787  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
2788  ThinSliceSample & sample = samples_vec.at(j);
2789  if (sample.CheckInSignalRange(end_energy)) {
2790  found = true;
2791  if (is_scaled) {
2792  scale = fake_data_scales.at(sample_ID)[j];
2793  sample_scales[sample_ID][j] += scale;
2794  nominal_samples[sample_ID][j] += 1.;
2795  }
2796  this_sample = &sample;
2797  break;
2798  }
2799  }
2800  if (!found) {
2801  if (end_energy < samples_vec[1].RangeLowEnd()) {
2802  this_sample = &samples_vec[0];
2803  if (is_scaled) {
2804  scale = fake_data_scales.at(sample_ID)[0];
2805  sample_scales[sample_ID][0] += scale;
2806  nominal_samples[sample_ID][0] += 1.;
2807  }
2808  }
2809  else if (end_energy >
2810  samples_vec[samples_vec.size()-2].RangeHighEnd()) {
2811  this_sample = &samples_vec.back();
2812  if (is_scaled) {
2813  scale = fake_data_scales.at(sample_ID).back();
2814  sample_scales[sample_ID].back() += scale;
2815  nominal_samples[sample_ID].back() += 1.;
2816  }
2817  }
2818  }
2819  }
2820  if (!is_signal) {
2821  if (is_scaled) {
2822  scale = fake_data_scales.at(sample_ID)[0];
2823  sample_scales[sample_ID][0] += scale;
2824  nominal_samples[sample_ID][0] += 1.;
2825  }
2826  this_sample = &samples[sample_ID][0][0];
2827  }
2828 
2829 
2830  new_flux += scale; //1 or scaled
2831 
2832  double val = 0.;
2833  if (selection_ID == 4) {
2834  if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) == 0) {
2835  val = selected_hists[selection_ID]->GetBinCenter(1);
2836  }
2837  else if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) >
2838  selected_hists[selection_ID]->GetNbinsX()) {
2839  val = selected_hists[selection_ID]->GetBinCenter(
2840  selected_hists[selection_ID]->GetNbinsX());
2841  }
2842  else {
2843  val = reco_beam_endZ;
2844  }
2845  }
2846  else if (selection_ID > 4) {
2847  val = .5;
2848  }
2849  else if (reco_beam_incidentEnergies->size()) {
2850  for (size_t j = 0; j < reco_beam_incidentEnergies->size(); ++j) {
2851  incident_hist.Fill((*reco_beam_incidentEnergies)[j]);
2852  }
2853  if (selected_hists.find(selection_ID) != selected_hists.end()) {
2854  if (selection_ID != 4 && selection_ID != 5 && selection_ID != 6) {
2855  double energy = reco_beam_interactingEnergy;
2856  if (fDoEnergyFix) {
2857  for (size_t k = 1; k < reco_beam_incidentEnergies->size(); ++k) {
2858  double deltaE = ((*reco_beam_incidentEnergies)[k-1] -
2859  (*reco_beam_incidentEnergies)[k]);
2860  if (deltaE > fEnergyFix) {
2861  energy += deltaE;
2862  }
2863  }
2864  }
2865  if (selected_hists[selection_ID]->FindBin(energy) == 0) {
2866  val = selected_hists[selection_ID]->GetBinCenter(1);
2867  }
2868  else if (selected_hists[selection_ID]->FindBin(energy) >
2869  selected_hists[selection_ID]->GetNbinsX()) {
2870  val = selected_hists[selection_ID]->GetBinCenter(
2871  selected_hists[selection_ID]->GetNbinsX());
2872  }
2873  else {
2874  val = energy;
2875  }
2876  }
2877  }
2878  }
2879  else {
2880  val = selected_hists[selection_ID]->GetBinCenter(1);
2881  }
2882 
2883  selected_hists[selection_ID]->Fill(val, scale);
2884  std::vector<double> good_true_incEnergies = MakeTrueIncidentEnergies(
2885  *true_beam_traj_Z, *true_beam_traj_KE, *true_beam_slices,
2886  *true_beam_incidentEnergies);
2887  //if (fSliceMethod == "Traj") {
2888  // double next_slice_z = fTrajZStart;
2889  // int next_slice_num = 0;
2890  // for (size_t j = 1; j < true_beam_traj_Z->size() - 1; ++j) {
2891  // double z = (*true_beam_traj_Z)[j];
2892  // double ke = (*true_beam_traj_KE)[j];
2893 
2894  // if (z < fTrajZStart) {
2895  // //std::cout << "Skipping " << z << std::endl;
2896  // continue;
2897  // }
2898 
2899  // if (z >= next_slice_z) {
2900  // double temp_z = (*true_beam_traj_Z)[j-1];
2901  // double temp_e = (*true_beam_traj_KE)[j-1];
2902  //
2903  // while (next_slice_z < z && next_slice_num < fSliceCut) {
2904  // double sub_z = next_slice_z - temp_z;
2905  // double delta_e = (*true_beam_traj_KE)[j-1] - ke;
2906  // double delta_z = z - (*true_beam_traj_Z)[j-1]/* - z*/;
2907  // temp_e -= (sub_z/delta_z)*delta_e;
2908  // good_true_incEnergies.push_back(temp_e);
2909  // temp_z = next_slice_z;
2910  // next_slice_z += fPitch;
2911  // ++next_slice_num;
2912  // }
2913  // }
2914  // }
2915  //}
2916  //else if (fSliceMethod == "Default") {
2917  // for (size_t j = 0; j < true_beam_incidentEnergies->size(); ++j) {
2918  // int slice = (*true_beam_slices)[j];
2919  // if (slice > fSliceCut) continue;
2920  // good_true_incEnergies.push_back((*true_beam_incidentEnergies)[j]);
2921  // }
2922  //}
2923  this_sample->AddVariedFlux(scale);
2924  this_sample->AddIncidentEnergies(good_true_incEnergies, scale);
2925  }
2926 
2927  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
2928  for (size_t i = 0; i < it->second.size(); ++i) {
2929  if (it->second[i] > 0.) {
2930  it->second[i] /= nominal_samples[it->first][i];
2931  }
2932  else {
2933  it->second[i] = 1.;
2934  }
2935  it->second[i] *= (flux/new_flux);
2936  }
2937  }
2938 
2939  //std::cout << "Flux: " << flux << " new_flux: " << new_flux << std::endl;
2940 
2941  incident_hist.Scale(flux/new_flux);
2942  for (auto it = selected_hists.begin(); it != selected_hists.end(); ++it) {
2943  it->second->Scale(flux/new_flux);
2944  }
2945 }
2946 
2948  TTree * tree,
2949  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
2950  const std::map<int, bool> & signal_sample_checks,
2951  ThinSliceDataSet & data_set, double & flux,
2952  std::map<int, std::vector<double>> & sample_scales,
2953  int split_val) {
2954 
2955  //Build the map for fake data scales
2956  fhicl::ParameterSet g4rw_options
2957  = fExtraOptions.get<fhicl::ParameterSet>("FakeDataG4RW");
2958 
2959  int sample_ID, selection_ID;
2960  double true_beam_interactingEnergy, reco_beam_interactingEnergy;
2961  double true_beam_endP;
2962  std::vector<double> * reco_beam_incidentEnergies = 0x0;
2963  double reco_beam_endZ;
2964  std::vector<double> * g4rw_weight = 0x0;
2965  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
2966  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
2967  tree->SetBranchAddress("selection_ID", &selection_ID);
2968  tree->SetBranchAddress("true_beam_interactingEnergy",
2969  &true_beam_interactingEnergy);
2970  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
2971  tree->SetBranchAddress("reco_beam_interactingEnergy",
2972  &reco_beam_interactingEnergy);
2973  tree->SetBranchAddress("reco_beam_incidentEnergies",
2974  &reco_beam_incidentEnergies);
2975  std::vector<double> * true_beam_traj_Z = 0x0,
2976  * true_beam_traj_KE = 0x0;
2977  std::vector<int> * true_beam_slices = 0x0;
2978  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
2979  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
2980  tree->SetBranchAddress("true_beam_slices", &true_beam_slices);
2981  std::vector<double> * true_beam_incidentEnergies = 0x0;
2982  tree->SetBranchAddress("true_beam_incidentEnergies",
2983  &true_beam_incidentEnergies);
2984 
2985  if (g4rw_options.get<int>("Shift") > 0) {
2986  if (g4rw_options.get<bool>("Full")) {
2987  std::cout << "Full weight" << std::endl;
2988  tree->SetBranchAddress("g4rw_full_primary_plus_sigma_weight", &g4rw_weight);
2989  }
2990  else {
2991  tree->SetBranchAddress("g4rw_alt_primary_plus_sigma_weight", &g4rw_weight);
2992  }
2993  }
2994  else {
2995  if (g4rw_options.get<bool>("Full")) {
2996  std::cout << "Full weight" << std::endl;
2997  tree->SetBranchAddress("g4rw_full_primary_minus_sigma_weight", &g4rw_weight);
2998  }
2999  else {
3000  tree->SetBranchAddress("g4rw_alt_primary_minus_sigma_weight", &g4rw_weight);
3001  }
3002  }
3003 
3004  size_t g4rw_pos = g4rw_options.get<size_t>("Position");
3005 
3006  TH1D & incident_hist = data_set.GetIncidentHist();
3007  std::map<int, TH1 *> & selected_hists = data_set.GetSelectionHists();
3008 
3009  double new_flux = 0.;
3010  flux = tree->GetEntries() - split_val;
3011 
3012 
3013  std::map<int, std::vector<double>> nominal_samples;
3014  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
3015  nominal_samples[it->first] = std::vector<double>(it->second.size(), 0.);
3016  }
3017 
3018  for (int i = /*0*/split_val; i < tree->GetEntries(); ++i) {
3019  tree->GetEntry(i);
3020 
3021  if (samples.find(sample_ID) == samples.end())
3022  continue;
3023 
3024  double end_energy = true_beam_interactingEnergy;
3025  if (fSliceMethod == "Traj") {
3026  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
3027  }
3028  else if (fSliceMethod == "E") {
3029  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
3030  }
3031  else if (fSliceMethod == "Alt") {
3032  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z->back());
3033  if (bin > 0) {
3034  end_energy = fMeans.at(bin);
3035  }
3036  }
3037 
3038  double scale = 1.;
3039  if (g4rw_weight->size() > 0) {
3040  scale = g4rw_weight->at(g4rw_pos);
3041  }
3042 
3043  bool is_signal = signal_sample_checks.at(sample_ID);
3044  ThinSliceSample * this_sample = 0x0;
3045  if (is_signal) {
3046  std::vector<ThinSliceSample> & samples_vec = samples[sample_ID][0];
3047  //Get the samples vec from the first beam energy bin
3048  bool found = false;
3049  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
3050  ThinSliceSample & sample = samples_vec.at(j);
3051  if (sample.CheckInSignalRange(end_energy)) {
3052  found = true;
3053  sample_scales[sample_ID][j] += scale;
3054  nominal_samples[sample_ID][j] += 1.;
3055  this_sample = &sample;
3056  break;
3057  }
3058  }
3059  if (!found) {
3060  if (end_energy < samples_vec[1].RangeLowEnd()) {
3061  sample_scales[sample_ID][0] += scale;
3062  nominal_samples[sample_ID][0] += 1.;
3063  this_sample = &samples_vec[0];
3064  }
3065  else if (end_energy >
3066  samples_vec[samples_vec.size()-2].RangeHighEnd()) {
3067  this_sample = &samples_vec.back();
3068  sample_scales[sample_ID].back() += scale;
3069  nominal_samples[sample_ID].back() += 1.;
3070  }
3071  }
3072  }
3073  else {
3074  this_sample = &samples[sample_ID][0][0];
3075  sample_scales[sample_ID][0] += scale;
3076  nominal_samples[sample_ID][0] += 1.;
3077  }
3078 
3079  new_flux += scale; //1 or scaled
3080  double val = 0.;
3081  if (selection_ID == 4) {
3082  if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) == 0) {
3083  val = selected_hists[selection_ID]->GetBinCenter(1);
3084  }
3085  else if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) >
3086  selected_hists[selection_ID]->GetNbinsX()) {
3087  val = selected_hists[selection_ID]->GetBinCenter(
3088  selected_hists[selection_ID]->GetNbinsX());
3089  }
3090  else {
3091  val = reco_beam_endZ;
3092  }
3093  }
3094  else if (selection_ID > 4) {
3095  val = .5;
3096  }
3097  else if (reco_beam_incidentEnergies->size()) {
3098  for (size_t j = 0; j < reco_beam_incidentEnergies->size(); ++j) {
3099  incident_hist.Fill((*reco_beam_incidentEnergies)[j]);
3100  }
3101  if (selected_hists.find(selection_ID) != selected_hists.end()) {
3102  if (selection_ID != 4 && selection_ID != 5 && selection_ID != 6) {
3103  double energy = reco_beam_interactingEnergy;
3104  if (fDoEnergyFix) {
3105  for (size_t k = 1; k < reco_beam_incidentEnergies->size(); ++k) {
3106  double deltaE = ((*reco_beam_incidentEnergies)[k-1] -
3107  (*reco_beam_incidentEnergies)[k]);
3108  if (deltaE > fEnergyFix) {
3109  energy += deltaE;
3110  }
3111  }
3112  }
3113  if (selected_hists[selection_ID]->FindBin(energy) == 0) {
3114  val = selected_hists[selection_ID]->GetBinCenter(1);
3115  }
3116  else if (selected_hists[selection_ID]->FindBin(energy) >
3117  selected_hists[selection_ID]->GetNbinsX()) {
3118  val = selected_hists[selection_ID]->GetBinCenter(
3119  selected_hists[selection_ID]->GetNbinsX());
3120  }
3121  else {
3122  val = energy;
3123  }
3124  }
3125  }
3126  }
3127  else {
3128  val = selected_hists[selection_ID]->GetBinCenter(1);
3129  }
3130 
3131  selected_hists[selection_ID]->Fill(val, scale);
3132  this_sample->AddVariedFlux(scale);
3133  std::vector<double> good_true_incEnergies = MakeTrueIncidentEnergies(
3134  *true_beam_traj_Z, *true_beam_traj_KE, *true_beam_slices,
3135  *true_beam_incidentEnergies);
3136  //if (fSliceMethod == "Traj") {
3137  // double next_slice_z = fTrajZStart;
3138  // int next_slice_num = 0;
3139  // for (size_t j = 1; j < true_beam_traj_Z->size() - 1; ++j) {
3140  // double z = (*true_beam_traj_Z)[j];
3141  // double ke = (*true_beam_traj_KE)[j];
3142 
3143  // if (z < fTrajZStart) {
3144  // //std::cout << "Skipping " << z << std::endl;
3145  // continue;
3146  // }
3147 
3148  // if (z >= next_slice_z) {
3149  // double temp_z = (*true_beam_traj_Z)[j-1];
3150  // double temp_e = (*true_beam_traj_KE)[j-1];
3151  //
3152  // while (next_slice_z < z && next_slice_num < fSliceCut) {
3153  // double sub_z = next_slice_z - temp_z;
3154  // double delta_e = (*true_beam_traj_KE)[j-1] - ke;
3155  // double delta_z = z - (*true_beam_traj_Z)[j-1]/* - z*/;
3156  // temp_e -= (sub_z/delta_z)*delta_e;
3157  // good_true_incEnergies.push_back(temp_e);
3158  // temp_z = next_slice_z;
3159  // next_slice_z += fPitch;
3160  // ++next_slice_num;
3161  // }
3162  // }
3163  // }
3164  //}
3165  //else if (fSliceMethod == "Default") {
3166  // for (size_t j = 0; j < true_beam_incidentEnergies->size(); ++j) {
3167  // int slice = (*true_beam_slices)[j];
3168  // if (slice > fSliceCut) continue;
3169  // good_true_incEnergies.push_back((*true_beam_incidentEnergies)[j]);
3170  // }
3171  //}
3172  this_sample->AddIncidentEnergies(good_true_incEnergies, scale);
3173  }
3174 
3175  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
3176  for (size_t i = 0; i < it->second.size(); ++i) {
3177  if (it->second[i] > 0.) {
3178  it->second[i] /= nominal_samples[it->first][i];
3179  }
3180  else {
3181  it->second[i] = 1.;
3182  }
3183  it->second[i] *= (flux/new_flux);
3184  }
3185  }
3186 
3187  incident_hist.Scale(flux/new_flux);
3188  for (auto it = selected_hists.begin(); it != selected_hists.end(); ++it) {
3189  it->second->Scale(flux/new_flux);
3190  }
3191 
3192  //std::cout << "Fluxes: " << flux << " " << new_flux << std::endl;
3193 }
3194 
3196  TTree * tree,
3197  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
3198  const std::map<int, bool> & signal_sample_checks,
3199  ThinSliceDataSet & data_set, double & flux,
3200  std::map<int, std::vector<double>> & sample_scales,
3201  std::vector<double> & beam_energy_bins,
3202  int split_val) {
3203 
3204  //Build the map for fake data scales
3205  fhicl::ParameterSet g4rw_options
3206  = fExtraOptions.get<fhicl::ParameterSet>("FakeDataG4RWGrid");
3207 
3208  int sample_ID, selection_ID;
3209  double true_beam_interactingEnergy, reco_beam_interactingEnergy;
3210  double true_beam_startP, true_beam_endP;
3211  std::vector<double> * reco_beam_incidentEnergies = 0x0;
3212  double reco_beam_endZ;
3213  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
3214  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
3215  tree->SetBranchAddress("selection_ID", &selection_ID);
3216  tree->SetBranchAddress("true_beam_interactingEnergy",
3217  &true_beam_interactingEnergy);
3218  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
3219  tree->SetBranchAddress("reco_beam_interactingEnergy",
3220  &reco_beam_interactingEnergy);
3221  tree->SetBranchAddress("reco_beam_incidentEnergies",
3222  &reco_beam_incidentEnergies);
3223  tree->SetBranchAddress("true_beam_startP", &true_beam_startP);
3224  std::vector<double> * true_beam_traj_Z = 0x0,
3225  * true_beam_traj_KE = 0x0;
3226  std::vector<int> * true_beam_slices = 0x0;
3227  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
3228  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
3229  tree->SetBranchAddress("true_beam_slices", &true_beam_slices);
3230  std::vector<double> * true_beam_incidentEnergies = 0x0;
3231  tree->SetBranchAddress("true_beam_incidentEnergies",
3232  &true_beam_incidentEnergies);
3233 
3234  //std::vector<double> * g4rw_weight = 0x0;
3235  std::vector<std::vector<double>> * g4rw_full_grid_weights = 0x0;
3236  std::string branch = g4rw_options.get<std::string>("Branch");
3237  tree->SetBranchAddress(branch.c_str(), &g4rw_full_grid_weights);
3238 
3239  //size_t g4rw_pos = g4rw_options.get<size_t>("Position");
3240  //size_t g4rw_shift = g4rw_options.get<size_t>("Shift");
3241  std::vector<size_t> g4rw_pos = g4rw_options.get<std::vector<size_t>>("Position");
3242  std::vector<size_t> g4rw_shift = g4rw_options.get<std::vector<size_t>>("Shift");
3243 
3244  TH1D & incident_hist = data_set.GetIncidentHist();
3245  std::map<int, TH1 *> & selected_hists = data_set.GetSelectionHists();
3246 
3247  double new_flux = 0.;
3248  flux = tree->GetEntries() - split_val;
3249 
3250 
3251  std::map<int, std::vector<double>> nominal_samples;
3252  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
3253  nominal_samples[it->first] = std::vector<double>(it->second.size(), 0.);
3254  }
3255 
3256  for (int i = /*0*/split_val; i < tree->GetEntries(); ++i) {
3257  tree->GetEntry(i);
3258 
3259  if (samples.find(sample_ID) == samples.end())
3260  continue;
3261 
3262  double end_energy = true_beam_interactingEnergy;
3263  if (fSliceMethod == "Traj") {
3264  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
3265  }
3266  else if (fSliceMethod == "E") {
3267  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
3268  }
3269  else if (fSliceMethod == "Alt") {
3270  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z->back());
3271  if (bin > 0) {
3272  end_energy = fMeans.at(bin);
3273  }
3274  }
3275 
3276  double scale = 1.;
3277  //if (g4rw_weight->size() > 0) {
3278  //if (g4rw_full_grid_weights->size() > 0) {
3279  // if ((*g4rw_full_grid_weights)[g4rw_pos].size() > 0) {
3280  // scale = (*g4rw_full_grid_weights)[g4rw_pos][g4rw_shift];
3281  // }
3282  //}
3283 
3284  if (g4rw_full_grid_weights->size() > 0) {
3285  for (size_t j = 0; j < g4rw_pos.size(); ++j) {
3286  size_t pos = g4rw_pos[j];
3287  size_t shift = g4rw_shift[j];
3288  if ((*g4rw_full_grid_weights)[pos].size() > 0) {
3289  scale *= (*g4rw_full_grid_weights)[pos][shift];
3290  //std::cout << "Grid: " << j << " " << pos << " " << shift << " " <<
3291  // (*g4rw_full_grid_weights)[pos][shift] << std::endl;
3292  }
3293  }
3294  }
3295 
3296  //Look for the coinciding energy bin
3297  //int bin = -1;
3298  //for (size_t j = 1; j < beam_energy_bins.size(); ++j) {
3299  // if ((beam_energy_bins[j-1] <= 1.e3*true_beam_startP) &&
3300  // (1.e3*true_beam_startP < beam_energy_bins[j])) {
3301  // bin = j - 1;
3302  // break;
3303  // }
3304  //}
3305  //if (bin == -1) {
3306  // std::string message = "Could not find beam energy bin for " +
3307  // std::to_string(true_beam_startP);
3308  // throw std::runtime_error(message);
3309  //}
3310  int bin = GetBeamBin(beam_energy_bins, true_beam_startP);
3311 
3312  bool is_signal = signal_sample_checks.at(sample_ID);
3313  ThinSliceSample * this_sample = 0x0;
3314  if (is_signal) {
3315  std::vector<ThinSliceSample> & samples_vec = samples[sample_ID][bin];
3316  //Get the samples vec from the first beam energy bin
3317  bool found = false;
3318  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
3319  ThinSliceSample & sample = samples_vec.at(j);
3320  if (sample.CheckInSignalRange(end_energy)) {
3321  found = true;
3322  sample_scales[sample_ID][j] += scale;
3323  nominal_samples[sample_ID][j] += 1.;
3324  this_sample = &sample;
3325  break;
3326  }
3327  }
3328  if (!found) {
3329  if (end_energy < samples_vec[1].RangeLowEnd()) {
3330  sample_scales[sample_ID][0] += scale;
3331  nominal_samples[sample_ID][0] += 1.;
3332  this_sample = &samples_vec[0];
3333  }
3334  else if (end_energy >
3335  samples_vec[samples_vec.size()-2].RangeHighEnd()) {
3336  this_sample = &samples_vec.back();
3337  sample_scales[sample_ID].back() += scale;
3338  nominal_samples[sample_ID].back() += 1.;
3339  }
3340  else {
3341  std::cout << "Could not find the sample" << std::endl;
3342  }
3343  }
3344  }
3345  else {
3346  this_sample = &samples[sample_ID][bin][0];
3347  sample_scales[sample_ID][0] += scale;
3348  nominal_samples[sample_ID][0] += 1.;
3349  }
3350 
3351  new_flux += scale; //1 or scaled
3352  double val = 0.;
3353  if (selection_ID == 4) {
3354  if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) == 0) {
3355  val = selected_hists[selection_ID]->GetBinCenter(1);
3356  }
3357  else if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) >
3358  selected_hists[selection_ID]->GetNbinsX()) {
3359  val = selected_hists[selection_ID]->GetBinCenter(
3360  selected_hists[selection_ID]->GetNbinsX());
3361  }
3362  else {
3363  val = reco_beam_endZ;
3364  }
3365  }
3366  else if (selection_ID > 4) {
3367  val = .5;
3368  }
3369  else if (reco_beam_incidentEnergies->size()) {
3370  for (size_t j = 0; j < reco_beam_incidentEnergies->size(); ++j) {
3371  incident_hist.Fill((*reco_beam_incidentEnergies)[j]);
3372  }
3373  if (selected_hists.find(selection_ID) != selected_hists.end()) {
3374  if (selection_ID != 4 && selection_ID != 5 && selection_ID != 6) {
3375  double energy = reco_beam_interactingEnergy;
3376  if (fDoEnergyFix) {
3377  for (size_t k = 1; k < reco_beam_incidentEnergies->size(); ++k) {
3378  double deltaE = ((*reco_beam_incidentEnergies)[k-1] -
3379  (*reco_beam_incidentEnergies)[k]);
3380  if (deltaE > fEnergyFix) {
3381  energy += deltaE;
3382  }
3383  }
3384  }
3385  if (selected_hists[selection_ID]->FindBin(energy) == 0) {
3386  val = selected_hists[selection_ID]->GetBinCenter(1);
3387  }
3388  else if (selected_hists[selection_ID]->FindBin(energy) >
3389  selected_hists[selection_ID]->GetNbinsX()) {
3390  val = selected_hists[selection_ID]->GetBinCenter(
3391  selected_hists[selection_ID]->GetNbinsX());
3392  }
3393  else {
3394  val = energy;
3395  }
3396  }
3397  }
3398  }
3399  else {
3400  val = selected_hists[selection_ID]->GetBinCenter(1);
3401  }
3402 
3403  selected_hists[selection_ID]->Fill(val, scale);
3404  this_sample->AddVariedFlux(scale);
3405  std::vector<double> good_true_incEnergies = MakeTrueIncidentEnergies(
3406  *true_beam_traj_Z, *true_beam_traj_KE, *true_beam_slices,
3407  *true_beam_incidentEnergies);
3408  //if (fSliceMethod == "Traj") {
3409  // double next_slice_z = fTrajZStart;
3410  // int next_slice_num = 0;
3411  // for (size_t j = 1; j < true_beam_traj_Z->size() - 1; ++j) {
3412  // double z = (*true_beam_traj_Z)[j];
3413  // double ke = (*true_beam_traj_KE)[j];
3414 
3415  // if (z < fTrajZStart) {
3416  // //std::cout << "Skipping " << z << std::endl;
3417  // continue;
3418  // }
3419 
3420  // if (z >= next_slice_z) {
3421  // double temp_z = (*true_beam_traj_Z)[j-1];
3422  // double temp_e = (*true_beam_traj_KE)[j-1];
3423  //
3424  // while (next_slice_z < z && next_slice_num < fSliceCut) {
3425  // double sub_z = next_slice_z - temp_z;
3426  // double delta_e = (*true_beam_traj_KE)[j-1] - ke;
3427  // double delta_z = z - (*true_beam_traj_Z)[j-1]/* - z*/;
3428  // temp_e -= (sub_z/delta_z)*delta_e;
3429  // good_true_incEnergies.push_back(temp_e);
3430  // temp_z = next_slice_z;
3431  // next_slice_z += fPitch;
3432  // ++next_slice_num;
3433  // }
3434  // }
3435  // }
3436  //}
3437  //else if (fSliceMethod == "Default") {
3438  // for (size_t j = 0; j < true_beam_incidentEnergies->size(); ++j) {
3439  // int slice = (*true_beam_slices)[j];
3440  // if (slice > fSliceCut) continue;
3441  // good_true_incEnergies.push_back((*true_beam_incidentEnergies)[j]);
3442  // }
3443  //}
3444  this_sample->AddIncidentEnergies(good_true_incEnergies, scale);
3445  }
3446 
3447  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
3448  for (size_t i = 0; i < it->second.size(); ++i) {
3449  if (it->second[i] > 0.) {
3450  it->second[i] /= nominal_samples[it->first][i];
3451  }
3452  else {
3453  it->second[i] = 1.;
3454  }
3455  it->second[i] *= (flux/new_flux);
3456  //for (size_t j = 0; j < samples[it->first][i].size(); ++j) {
3457  // samples[it->first][i][j].SetFactorAndScale(flux/new_flux);
3458  //}
3459  }
3460  }
3461 
3462  incident_hist.Scale(flux/new_flux);
3463  for (auto it = selected_hists.begin(); it != selected_hists.end(); ++it) {
3464  it->second->Scale(flux/new_flux);
3465  }
3466 
3467  //std::cout << "Fluxes: " << flux << " " << new_flux << std::endl;
3468 }
3469 
3471  TTree * tree,
3472  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
3473  const std::map<int, bool> & signal_sample_checks,
3474  ThinSliceDataSet & data_set, double & flux,
3475  std::map<int, std::vector<double>> & sample_scales, int split_val) {
3476 
3477  //Build the map for fake data scales
3479  = fExtraOptions.get<fhicl::ParameterSet>("FakeDataPionAngle");
3480 
3481  int sample_ID, selection_ID;
3482  double true_beam_interactingEnergy, reco_beam_interactingEnergy;
3483  double true_beam_endP, true_beam_endPx, true_beam_endPy, true_beam_endPz;
3484  std::vector<double> * true_beam_daughter_startPx = 0x0,
3485  * true_beam_daughter_startPy = 0x0,
3486  * true_beam_daughter_startPz = 0x0,
3487  * true_beam_daughter_startP = 0x0;
3488  std::vector<double> * reco_beam_incidentEnergies = 0x0;
3489  double reco_beam_endZ;
3490  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
3491  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
3492  tree->SetBranchAddress("selection_ID", &selection_ID);
3493  tree->SetBranchAddress("true_beam_interactingEnergy",
3494  &true_beam_interactingEnergy);
3495  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
3496  tree->SetBranchAddress("true_beam_endPx", &true_beam_endPx);
3497  tree->SetBranchAddress("true_beam_endPy", &true_beam_endPy);
3498  tree->SetBranchAddress("true_beam_endPz", &true_beam_endPz);
3499  tree->SetBranchAddress("true_beam_daughter_startPx", &true_beam_daughter_startPx);
3500  tree->SetBranchAddress("true_beam_daughter_startPy", &true_beam_daughter_startPy);
3501  tree->SetBranchAddress("true_beam_daughter_startPz", &true_beam_daughter_startPz);
3502  tree->SetBranchAddress("true_beam_daughter_startP", &true_beam_daughter_startP);
3503  std::vector<int> * true_beam_daughter_PDG = 0x0;
3504  tree->SetBranchAddress("true_beam_daughter_PDG", &true_beam_daughter_PDG);
3505  tree->SetBranchAddress("reco_beam_interactingEnergy",
3506  &reco_beam_interactingEnergy);
3507  tree->SetBranchAddress("reco_beam_incidentEnergies",
3508  &reco_beam_incidentEnergies);
3509  std::vector<double> * true_beam_traj_Z = 0x0,
3510  * true_beam_traj_KE = 0x0;
3511  std::vector<int> * true_beam_slices = 0x0;
3512  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
3513  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
3514  tree->SetBranchAddress("true_beam_slices", &true_beam_slices);
3515  std::vector<double> * true_beam_incidentEnergies = 0x0;
3516  tree->SetBranchAddress("true_beam_incidentEnergies",
3517  &true_beam_incidentEnergies);
3518 
3519  TH1D & incident_hist = data_set.GetIncidentHist();
3520  std::map<int, TH1 *> & selected_hists = data_set.GetSelectionHists();
3521 
3522  TFile ratio_file(options.get<std::string>("RatioFile").c_str(), "OPEN");
3523  std::vector<std::string> ratio_names
3524  = options.get<std::vector<std::string>>("RatioNames");
3525 
3526  std::vector<TH1D *> ratios;
3527  for (auto n : ratio_names) {
3528  ratios.push_back((TH1D*)ratio_file.Get(n.c_str()));
3529  }
3530  std::vector<double> limits = options.get<std::vector<double>>("Limits");
3531 
3532  double new_flux = 0.;
3533  flux = tree->GetEntries() - split_val;
3534 
3535 
3536  std::map<int, std::vector<double>> nominal_samples;
3537  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
3538  nominal_samples[it->first] = std::vector<double>(it->second.size(), 0.);
3539  }
3540 
3541  for (int i = split_val; i < tree->GetEntries(); ++i) {
3542  tree->GetEntry(i);
3543 
3544  if (samples.find(sample_ID) == samples.end())
3545  continue;
3546 
3547  double end_energy = true_beam_interactingEnergy;
3548  if (fSliceMethod == "Traj") {
3549  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
3550  }
3551  else if (fSliceMethod == "E") {
3552  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
3553  }
3554  else if (fSliceMethod == "Alt") {
3555  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z->back());
3556  if (bin > 0) {
3557  end_energy = fMeans.at(bin);
3558  }
3559  }
3560 
3561  double scale = 1.;
3562  size_t n_piplus = 0, n_piminus = 0;
3563  for (size_t j = 0; j < true_beam_daughter_PDG->size(); ++j) {
3564  if (true_beam_daughter_PDG->at(j) == 211) {
3565  ++n_piplus;
3566  }
3567  else if (true_beam_daughter_PDG->at(j) == -211) {
3568  ++n_piminus;
3569  }
3570  }
3571 
3572  if (sample_ID == 3 && n_piplus == 1 && n_piminus == 0) {
3573  TH1D * h = 0x0;
3574  //std::cout << "end p: " << true_beam_endP << std::endl;
3575  if (true_beam_endP >= limits.back()) {
3576  h = ratios.back();
3577  //std::cout << limits.back() << " < " << true_beam_endP << std::endl;
3578  }
3579  else {
3580  for (size_t j = 1; j < limits.size(); ++j) {
3581  if (true_beam_endP >= limits[j-1] &&
3582  true_beam_endP < limits[j]) {
3583  h = ratios[j-1];
3584  //std::cout << limits[j-1] << " < " << true_beam_endP <<
3585  // " < " << limits[j] << std::endl;
3586  break;
3587  }
3588  }
3589  }
3590  //std::cout << "h: " << h << std::endl;
3591 
3592  for (size_t j = 0; j < true_beam_daughter_PDG->size(); ++j) {
3593  if (true_beam_daughter_PDG->at(j) == 211) {
3594  double costheta = (true_beam_endPx*true_beam_daughter_startPx->at(j) +
3595  true_beam_endPy*true_beam_daughter_startPy->at(j) +
3596  true_beam_endPz*true_beam_daughter_startPz->at(j))/
3597  (true_beam_endP*true_beam_daughter_startP->at(j));
3598 
3599  int bin = h->FindBin(costheta);
3600  scale *= h->GetBinContent(bin);
3601  }
3602  }
3603  }
3604 
3605  bool is_signal = signal_sample_checks.at(sample_ID);
3606  ThinSliceSample * this_sample = 0x0;
3607  if (is_signal) {
3608  std::vector<ThinSliceSample> & samples_vec = samples[sample_ID][0];
3609  //Get the samples vec from the first beam energy bin
3610  bool found = false;
3611  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
3612  ThinSliceSample & sample = samples_vec.at(j);
3613  if (sample.CheckInSignalRange(end_energy)) {
3614  found = true;
3615  sample_scales[sample_ID][j] += scale;
3616  nominal_samples[sample_ID][j] += 1.;
3617  this_sample = &sample;
3618  break;
3619  }
3620  }
3621  if (!found) {
3622  if (end_energy < samples_vec[1].RangeLowEnd()) {
3623  sample_scales[sample_ID][0] += scale;
3624  nominal_samples[sample_ID][0] += 1.;
3625  this_sample = &samples_vec[0];
3626  }
3627  else {
3628  this_sample = &samples_vec.back();
3629  sample_scales[sample_ID].back() += scale;
3630  nominal_samples[sample_ID].back() += 1.;
3631  }
3632  }
3633  }
3634  else {
3635  this_sample = &samples[sample_ID][0][0];
3636  sample_scales[sample_ID][0] += scale;
3637  nominal_samples[sample_ID][0] += 1.;
3638  }
3639 
3640  new_flux += scale; //1 or scaled
3641  double val = 0.;
3642  if (selection_ID == 4) {
3643  if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) == 0) {
3644  val = selected_hists[selection_ID]->GetBinCenter(1);
3645  }
3646  else if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) >
3647  selected_hists[selection_ID]->GetNbinsX()) {
3648  val = selected_hists[selection_ID]->GetBinCenter(
3649  selected_hists[selection_ID]->GetNbinsX());
3650  }
3651  else {
3652  val = reco_beam_endZ;
3653  }
3654  }
3655  else if (selection_ID > 4) {
3656  val = .5;
3657  }
3658  else if (reco_beam_incidentEnergies->size()) {
3659  for (size_t j = 0; j < reco_beam_incidentEnergies->size(); ++j) {
3660  incident_hist.Fill((*reco_beam_incidentEnergies)[j]);
3661  }
3662  if (selected_hists.find(selection_ID) != selected_hists.end()) {
3663  //if (selection_ID != 4 && selection_ID != 5 && selection_ID != 6) {
3664  if (selection_ID < 4) {
3665  double energy = reco_beam_interactingEnergy;
3666  if (fDoEnergyFix) {
3667  for (size_t k = 1; k < reco_beam_incidentEnergies->size(); ++k) {
3668  double deltaE = ((*reco_beam_incidentEnergies)[k-1] -
3669  (*reco_beam_incidentEnergies)[k]);
3670  if (deltaE > fEnergyFix) {
3671  energy += deltaE;
3672  }
3673  }
3674  }
3675  if (selected_hists[selection_ID]->FindBin(energy) == 0) {
3676  val = selected_hists[selection_ID]->GetBinCenter(1);
3677  }
3678  else if (selected_hists[selection_ID]->FindBin(energy) >
3679  selected_hists[selection_ID]->GetNbinsX()) {
3680  val = selected_hists[selection_ID]->GetBinCenter(
3681  selected_hists[selection_ID]->GetNbinsX());
3682  }
3683  else {
3684  val = energy;
3685  }
3686  }
3687  }
3688  }
3689  else {
3690  val = selected_hists[selection_ID]->GetBinCenter(1);
3691  }
3692 
3693  selected_hists[selection_ID]->Fill(val, scale);
3694  this_sample->AddVariedFlux(scale);
3695  std::vector<double> good_true_incEnergies = MakeTrueIncidentEnergies(
3696  *true_beam_traj_Z, *true_beam_traj_KE, *true_beam_slices,
3697  *true_beam_incidentEnergies);
3698  this_sample->AddIncidentEnergies(good_true_incEnergies, scale);
3699  }
3700 
3701  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
3702  for (size_t i = 0; i < it->second.size(); ++i) {
3703  if (it->second[i] > 0.) {
3704  it->second[i] /= nominal_samples[it->first][i];
3705  }
3706  else {
3707  it->second[i] = 1.;
3708  }
3709  it->second[i] *= (flux/new_flux);
3710  }
3711  }
3712 
3713  incident_hist.Scale(flux/new_flux);
3714  for (auto it = selected_hists.begin(); it != selected_hists.end(); ++it) {
3715  it->second->Scale(flux/new_flux);
3716  }
3717 }
3718 
3720  TTree * tree,
3721  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
3722  const std::map<int, bool> & signal_sample_checks,
3723  ThinSliceDataSet & data_set, double & flux,
3724  std::map<int, std::vector<double>> & sample_scales, int split_val) {
3725 
3726  //Build the map for fake data scales
3728  = fExtraOptions.get<fhicl::ParameterSet>("FakeDataAngleVar");
3729 
3730  int sample_ID, selection_ID;
3731  double true_beam_interactingEnergy, reco_beam_interactingEnergy;
3732  double true_beam_endP, true_beam_endPx, true_beam_endPy, true_beam_endPz;
3733  std::vector<double> * true_beam_daughter_startPx = 0x0,
3734  * true_beam_daughter_startPy = 0x0,
3735  * true_beam_daughter_startPz = 0x0,
3736  * true_beam_daughter_startP = 0x0;
3737  std::vector<double> * reco_beam_incidentEnergies = 0x0;
3738  double reco_beam_endZ;
3739  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
3740  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
3741  tree->SetBranchAddress("selection_ID", &selection_ID);
3742  tree->SetBranchAddress("true_beam_interactingEnergy",
3743  &true_beam_interactingEnergy);
3744  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
3745  tree->SetBranchAddress("true_beam_endPx", &true_beam_endPx);
3746  tree->SetBranchAddress("true_beam_endPy", &true_beam_endPy);
3747  tree->SetBranchAddress("true_beam_endPz", &true_beam_endPz);
3748  tree->SetBranchAddress("true_beam_daughter_startPx", &true_beam_daughter_startPx);
3749  tree->SetBranchAddress("true_beam_daughter_startPy", &true_beam_daughter_startPy);
3750  tree->SetBranchAddress("true_beam_daughter_startPz", &true_beam_daughter_startPz);
3751  tree->SetBranchAddress("true_beam_daughter_startP", &true_beam_daughter_startP);
3752  std::vector<int> * true_beam_daughter_PDG = 0x0;
3753  tree->SetBranchAddress("true_beam_daughter_PDG", &true_beam_daughter_PDG);
3754  tree->SetBranchAddress("reco_beam_interactingEnergy",
3755  &reco_beam_interactingEnergy);
3756  tree->SetBranchAddress("reco_beam_incidentEnergies",
3757  &reco_beam_incidentEnergies);
3758  std::vector<double> * true_beam_traj_Z = 0x0,
3759  * true_beam_traj_KE = 0x0;
3760  std::vector<int> * true_beam_slices = 0x0;
3761  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
3762  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
3763  tree->SetBranchAddress("true_beam_slices", &true_beam_slices);
3764  std::vector<double> * true_beam_incidentEnergies = 0x0;
3765  tree->SetBranchAddress("true_beam_incidentEnergies",
3766  &true_beam_incidentEnergies);
3767 
3768  double leading_costheta;
3769  int check_PDG = options.get<int>("PDG");
3770  if (check_PDG == 2212) {
3771  tree->SetBranchAddress("leading_p_costheta", &leading_costheta);
3772  }
3773  else if (check_PDG == 211) {
3774  tree->SetBranchAddress("leading_piplus_costheta", &leading_costheta);
3775  }
3776  else if (check_PDG == 111) {
3777  tree->SetBranchAddress("leading_pi0_costheta", &leading_costheta);
3778  }
3779 
3780  TH1D & incident_hist = data_set.GetIncidentHist();
3781  std::map<int, TH1 *> & selected_hists = data_set.GetSelectionHists();
3782 
3783  TFile ratio_file(options.get<std::string>("RatioFile").c_str(), "OPEN");
3784  //std::vector<std::string> ratio_names
3785  // = options.get<std::vector<std::string>>("RatioNames");
3786  auto temp_ratio_names
3787  = options.get<std::vector<std::pair<int, std::vector<std::string>>>>
3788  ("RatioNames");
3789  std::map<int, std::vector<std::string>> ratio_names(
3790  temp_ratio_names.begin(), temp_ratio_names.end());
3791 
3792  std::map<int, std::vector<TH1D *>> ratios;
3793  for (int i = 1; i < 4; ++i) {
3794  ratios[i] = std::vector<TH1D *>();
3795  for (auto n : ratio_names[i]) {
3796  std::string name = n + "_" + std::to_string(i);
3797  ratios[i].push_back((TH1D*)ratio_file.Get(name.c_str()));
3798  std::cout << i << " " << name << " " << ratios[i].back() << std::endl;
3799  }
3800  }
3801  auto temp_limits = options.get<std::vector<std::pair<int, std::vector<double>>>>("Limits");
3802  std::map<int, std::vector<double>> limits(temp_limits.begin(), temp_limits.end());
3803 
3804 
3805  double new_flux = 0.;
3806  flux = tree->GetEntries() - split_val;
3807 
3808 
3809  std::map<int, std::vector<double>> nominal_samples;
3810  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
3811  nominal_samples[it->first] = std::vector<double>(it->second.size(), 0.);
3812  }
3813 
3814  std::vector<double> all_scales;
3815  for (int i = split_val; i < tree->GetEntries(); ++i) {
3816  tree->GetEntry(i);
3817 
3818  if (samples.find(sample_ID) == samples.end())
3819  continue;
3820 
3821  double end_energy = true_beam_interactingEnergy;
3822  if (fSliceMethod == "Traj") {
3823  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
3824  }
3825  else if (fSliceMethod == "E") {
3826  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
3827  }
3828  else if (fSliceMethod == "Alt") {
3829  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z->back());
3830  if (bin > 0) {
3831  end_energy = fMeans.at(bin);
3832  }
3833  }
3834 
3835  double scale = 1.;
3836  size_t n_piplus = 0, n_pi0 = 0, n_p = 0;
3837  for (size_t j = 0; j < true_beam_daughter_PDG->size(); ++j) {
3838  if (true_beam_daughter_PDG->at(j) == 211) {
3839  ++n_piplus;
3840  }
3841  else if (true_beam_daughter_PDG->at(j) == 111) {
3842  ++n_pi0;
3843  }
3844  else if (true_beam_daughter_PDG->at(j) == 2212) {
3845  ++n_p;
3846  }
3847  }
3848 
3849  if (sample_ID < 4 &&
3850  ((check_PDG == 211 && n_piplus > 0) ||
3851  (check_PDG == 2212 && n_p > 0) ||
3852  (check_PDG == 111 && n_pi0 > 0))) {
3853  TH1D * h = 0x0;
3854  //std::cout << "end p: " << end_energy << std::endl;
3855  if (end_energy >= limits[sample_ID].back()) {
3856  h = ratios[sample_ID].back();
3857  //std::cout << limits[sample_ID].back() << " < " << end_energy << std::endl;
3858  }
3859  else {
3860  for (size_t j = 1; j < limits[sample_ID].size(); ++j) {
3861  if (end_energy >= limits[sample_ID][j-1] &&
3862  end_energy < limits[sample_ID][j]) {
3863  h = ratios[sample_ID][j-1];
3864  //std::cout << limits[sample_ID][j-1] << " < " << end_energy <<
3865  // " < " << limits[sample_ID][j] << std::endl;
3866  break;
3867  }
3868  }
3869  }
3870  //std::cout << "h: " << h << std::endl;
3871 
3872  int bin = h->FindBin(leading_costheta);
3873  scale *= h->GetBinContent(bin);
3874  }
3875  all_scales.push_back(scale);
3876 
3877  bool is_signal = signal_sample_checks.at(sample_ID);
3878  ThinSliceSample * this_sample = 0x0;
3879  if (is_signal) {
3880  std::vector<ThinSliceSample> & samples_vec = samples[sample_ID][0];
3881  //Get the samples vec from the first beam energy bin
3882  bool found = false;
3883  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
3884  ThinSliceSample & sample = samples_vec.at(j);
3885  if (sample.CheckInSignalRange(end_energy)) {
3886  found = true;
3887  sample_scales[sample_ID][j] += scale;
3888  nominal_samples[sample_ID][j] += 1.;
3889  this_sample = &sample;
3890  break;
3891  }
3892  }
3893  if (!found) {
3894  if (end_energy < samples_vec[1].RangeLowEnd()) {
3895  sample_scales[sample_ID][0] += scale;
3896  nominal_samples[sample_ID][0] += 1.;
3897  this_sample = &samples_vec[0];
3898  }
3899  else {
3900  this_sample = &samples_vec.back();
3901  sample_scales[sample_ID].back() += scale;
3902  nominal_samples[sample_ID].back() += 1.;
3903  }
3904  }
3905  }
3906  else {
3907  this_sample = &samples[sample_ID][0][0];
3908  sample_scales[sample_ID][0] += scale;
3909  nominal_samples[sample_ID][0] += 1.;
3910  }
3911 
3912  new_flux += scale; //1 or scaled
3913  double val = 0.;
3914  if (selection_ID == 4) {
3915  if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) == 0) {
3916  val = selected_hists[selection_ID]->GetBinCenter(1);
3917  }
3918  else if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) >
3919  selected_hists[selection_ID]->GetNbinsX()) {
3920  val = selected_hists[selection_ID]->GetBinCenter(
3921  selected_hists[selection_ID]->GetNbinsX());
3922  }
3923  else {
3924  val = reco_beam_endZ;
3925  }
3926  }
3927  else if (selection_ID > 4) {
3928  val = .5;
3929  }
3930  else if (reco_beam_incidentEnergies->size()) {
3931  for (size_t j = 0; j < reco_beam_incidentEnergies->size(); ++j) {
3932  incident_hist.Fill((*reco_beam_incidentEnergies)[j]);
3933  }
3934  if (selected_hists.find(selection_ID) != selected_hists.end()) {
3935  //if (selection_ID != 4 && selection_ID != 5 && selection_ID != 6) {
3936  if (selection_ID < 4) {
3937  double energy = reco_beam_interactingEnergy;
3938  if (fDoEnergyFix) {
3939  for (size_t k = 1; k < reco_beam_incidentEnergies->size(); ++k) {
3940  double deltaE = ((*reco_beam_incidentEnergies)[k-1] -
3941  (*reco_beam_incidentEnergies)[k]);
3942  if (deltaE > fEnergyFix) {
3943  energy += deltaE;
3944  }
3945  }
3946  }
3947  if (selected_hists[selection_ID]->FindBin(energy) == 0) {
3948  val = selected_hists[selection_ID]->GetBinCenter(1);
3949  }
3950  else if (selected_hists[selection_ID]->FindBin(energy) >
3951  selected_hists[selection_ID]->GetNbinsX()) {
3952  val = selected_hists[selection_ID]->GetBinCenter(
3953  selected_hists[selection_ID]->GetNbinsX());
3954  }
3955  else {
3956  val = energy;
3957  }
3958  }
3959  }
3960  }
3961  else {
3962  val = selected_hists[selection_ID]->GetBinCenter(1);
3963  }
3964 
3965  selected_hists[selection_ID]->Fill(val, scale);
3966  this_sample->AddVariedFlux(scale);
3967  std::vector<double> good_true_incEnergies = MakeTrueIncidentEnergies(
3968  *true_beam_traj_Z, *true_beam_traj_KE, *true_beam_slices,
3969  *true_beam_incidentEnergies);
3970  this_sample->AddIncidentEnergies(good_true_incEnergies, scale);
3971  }
3972 
3973  double mean = 0.;
3974  for (auto s : all_scales) mean += s;
3975  mean /= all_scales.size();
3976  std::cout << "Mean scale: " << mean << std::endl;
3977 
3978  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
3979  for (size_t i = 0; i < it->second.size(); ++i) {
3980  if (it->second[i] > 0.) {
3981  it->second[i] /= nominal_samples[it->first][i];
3982  }
3983  else {
3984  it->second[i] = 1.;
3985  }
3986  it->second[i] *= (flux/new_flux);
3987  }
3988  }
3989 
3990  incident_hist.Scale(flux/new_flux);
3991  for (auto it = selected_hists.begin(); it != selected_hists.end(); ++it) {
3992  it->second->Scale(flux/new_flux);
3993  }
3994 }
3995 
3996 
3998  TTree * tree,
3999  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
4000  const std::map<int, bool> & signal_sample_checks,
4001  ThinSliceDataSet & data_set, double & flux,
4002  std::map<int, std::vector<double>> & sample_scales, int split_val) {
4003 
4004  //Build the map for fake data scales
4006  = fExtraOptions.get<fhicl::ParameterSet>("FakeDataBeamWeight");
4007 
4008  int sample_ID, selection_ID;
4009  double true_beam_interactingEnergy, reco_beam_interactingEnergy;
4010  double true_beam_endP, true_beam_endPx, true_beam_endPy, true_beam_endPz;
4011  std::vector<double> * true_beam_daughter_startPx = 0x0,
4012  * true_beam_daughter_startPy = 0x0,
4013  * true_beam_daughter_startPz = 0x0,
4014  * true_beam_daughter_startP = 0x0;
4015  std::vector<double> * reco_beam_incidentEnergies = 0x0;
4016  double reco_beam_endZ;
4017  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
4018  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
4019  tree->SetBranchAddress("selection_ID", &selection_ID);
4020  tree->SetBranchAddress("true_beam_interactingEnergy",
4021  &true_beam_interactingEnergy);
4022  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
4023  tree->SetBranchAddress("true_beam_endPx", &true_beam_endPx);
4024  tree->SetBranchAddress("true_beam_endPy", &true_beam_endPy);
4025  tree->SetBranchAddress("true_beam_endPz", &true_beam_endPz);
4026  tree->SetBranchAddress("true_beam_daughter_startPx", &true_beam_daughter_startPx);
4027  tree->SetBranchAddress("true_beam_daughter_startPy", &true_beam_daughter_startPy);
4028  tree->SetBranchAddress("true_beam_daughter_startPz", &true_beam_daughter_startPz);
4029  tree->SetBranchAddress("true_beam_daughter_startP", &true_beam_daughter_startP);
4030  std::vector<int> * true_beam_daughter_PDG = 0x0;
4031  tree->SetBranchAddress("true_beam_daughter_PDG", &true_beam_daughter_PDG);
4032  tree->SetBranchAddress("reco_beam_interactingEnergy",
4033  &reco_beam_interactingEnergy);
4034  tree->SetBranchAddress("reco_beam_incidentEnergies",
4035  &reco_beam_incidentEnergies);
4036  std::vector<double> * true_beam_traj_Z = 0x0,
4037  * true_beam_traj_KE = 0x0;
4038  std::vector<int> * true_beam_slices = 0x0;
4039  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
4040  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
4041  tree->SetBranchAddress("true_beam_slices", &true_beam_slices);
4042  std::vector<double> * true_beam_incidentEnergies = 0x0;
4043  tree->SetBranchAddress("true_beam_incidentEnergies",
4044  &true_beam_incidentEnergies);
4045 
4046 
4047  double beam_inst_P;
4048  tree->SetBranchAddress("beam_inst_P", &beam_inst_P);
4049 
4050  TH1D & incident_hist = data_set.GetIncidentHist();
4051  std::map<int, TH1 *> & selected_hists = data_set.GetSelectionHists();
4052 
4053  TFile ratio_file(options.get<std::string>("RatioFile").c_str(), "OPEN");
4054  TH1D * ratio = (TH1D*)ratio_file.Get("r");
4055 
4056  double new_flux = 0.;
4057  flux = tree->GetEntries() - split_val;
4058 
4059  std::map<int, std::vector<double>> nominal_samples;
4060  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
4061  nominal_samples[it->first] = std::vector<double>(it->second.size(), 0.);
4062  }
4063 
4064  for (int i = split_val; i < tree->GetEntries(); ++i) {
4065  tree->GetEntry(i);
4066 
4067  if (samples.find(sample_ID) == samples.end())
4068  continue;
4069 
4070  double end_energy = true_beam_interactingEnergy;
4071  if (fSliceMethod == "Traj") {
4072  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
4073  }
4074  else if (fSliceMethod == "E") {
4075  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
4076  }
4077  else if (fSliceMethod == "Alt") {
4078  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z->back());
4079  if (bin > 0) {
4080  end_energy = fMeans.at(bin);
4081  }
4082  }
4083 
4084  int bin = ratio->FindBin(beam_inst_P);
4085  double scale = ratio->GetBinContent(bin);;
4086  bool is_signal = signal_sample_checks.at(sample_ID);
4087  ThinSliceSample * this_sample = 0x0;
4088  if (is_signal) {
4089  std::vector<ThinSliceSample> & samples_vec = samples[sample_ID][0];
4090  //Get the samples vec from the first beam energy bin
4091  bool found = false;
4092  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
4093  ThinSliceSample & sample = samples_vec.at(j);
4094  if (sample.CheckInSignalRange(end_energy)) {
4095  found = true;
4096  sample_scales[sample_ID][j] += scale;
4097  nominal_samples[sample_ID][j] += 1.;
4098  this_sample = &sample;
4099  break;
4100  }
4101  }
4102  if (!found) {
4103  if (end_energy < samples_vec[1].RangeLowEnd()) {
4104  sample_scales[sample_ID][0] += scale;
4105  nominal_samples[sample_ID][0] += 1.;
4106  this_sample = &samples_vec[0];
4107  }
4108  else {
4109  this_sample = &samples_vec.back();
4110  sample_scales[sample_ID].back() += scale;
4111  nominal_samples[sample_ID].back() += 1.;
4112  }
4113  }
4114  }
4115  else {
4116  this_sample = &samples[sample_ID][0][0];
4117  sample_scales[sample_ID][0] += scale;
4118  nominal_samples[sample_ID][0] += 1.;
4119  }
4120 
4121  new_flux += scale; //1 or scaled
4122  double val = 0.;
4123  if (selection_ID == 4) {
4124  if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) == 0) {
4125  val = selected_hists[selection_ID]->GetBinCenter(1);
4126  }
4127  else if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) >
4128  selected_hists[selection_ID]->GetNbinsX()) {
4129  val = selected_hists[selection_ID]->GetBinCenter(
4130  selected_hists[selection_ID]->GetNbinsX());
4131  }
4132  else {
4133  val = reco_beam_endZ;
4134  }
4135  }
4136  else if (selection_ID > 4) {
4137  val = .5;
4138  }
4139  else if (reco_beam_incidentEnergies->size()) {
4140  for (size_t j = 0; j < reco_beam_incidentEnergies->size(); ++j) {
4141  incident_hist.Fill((*reco_beam_incidentEnergies)[j]);
4142  }
4143  if (selected_hists.find(selection_ID) != selected_hists.end()) {
4144  //if (selection_ID != 4 && selection_ID != 5 && selection_ID != 6) {
4145  if (selection_ID < 4) {
4146  double energy = reco_beam_interactingEnergy;
4147  if (fDoEnergyFix) {
4148  for (size_t k = 1; k < reco_beam_incidentEnergies->size(); ++k) {
4149  double deltaE = ((*reco_beam_incidentEnergies)[k-1] -
4150  (*reco_beam_incidentEnergies)[k]);
4151  if (deltaE > fEnergyFix) {
4152  energy += deltaE;
4153  }
4154  }
4155  }
4156  if (selected_hists[selection_ID]->FindBin(energy) == 0) {
4157  val = selected_hists[selection_ID]->GetBinCenter(1);
4158  }
4159  else if (selected_hists[selection_ID]->FindBin(energy) >
4160  selected_hists[selection_ID]->GetNbinsX()) {
4161  val = selected_hists[selection_ID]->GetBinCenter(
4162  selected_hists[selection_ID]->GetNbinsX());
4163  }
4164  else {
4165  val = energy;
4166  }
4167  }
4168  }
4169  }
4170  else {
4171  val = selected_hists[selection_ID]->GetBinCenter(1);
4172  }
4173 
4174  selected_hists[selection_ID]->Fill(val, scale);
4175  this_sample->AddVariedFlux(scale);
4176  std::vector<double> good_true_incEnergies = MakeTrueIncidentEnergies(
4177  *true_beam_traj_Z, *true_beam_traj_KE, *true_beam_slices,
4178  *true_beam_incidentEnergies);
4179  this_sample->AddIncidentEnergies(good_true_incEnergies, scale);
4180  }
4181 
4182  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
4183  for (size_t i = 0; i < it->second.size(); ++i) {
4184  if (it->second[i] > 0.) {
4185  it->second[i] /= nominal_samples[it->first][i];
4186  }
4187  else {
4188  it->second[i] = 1.;
4189  }
4190  it->second[i] *= (flux/new_flux);
4191  }
4192  }
4193 
4194  incident_hist.Scale(flux/new_flux);
4195  for (auto it = selected_hists.begin(); it != selected_hists.end(); ++it) {
4196  it->second->Scale(flux/new_flux);
4197  }
4198 }
4199 
4201  TTree * tree,
4202  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
4203  const std::map<int, bool> & signal_sample_checks,
4204  ThinSliceDataSet & data_set, double & flux,
4205  std::map<int, std::vector<double>> & sample_scales, int split_val) {
4206 
4207  fhicl::ParameterSet dEdX_options
4208  = fExtraOptions.get<fhicl::ParameterSet>("FakeDatadEdX");
4209  fhicl::ParameterSet cal_set
4210  = dEdX_options.get<fhicl::ParameterSet>("Cal_set");
4211  double betaP = cal_set.get<double>("betap");
4212  double rho = cal_set.get<double>("Rho");
4213  double wion = cal_set.get<double>("Wion");
4214  double alpha = cal_set.get<double>("alpha");
4215 
4216  std::vector<fhicl::ParameterSet> PlanePars
4217  = cal_set.get<std::vector<fhicl::ParameterSet>>("PlaneParameters");
4218  bool found_collection = false;
4219  double nominal_CCal = 1.;
4220  for (auto & p : PlanePars) {
4221  if (p.get<int>("PlaneID") == 2) {
4222  nominal_CCal = p.get<double>("calib_factor");
4223  found_collection = true;
4224  break;
4225  }
4226  }
4227 
4228  if (!found_collection) {
4229  std::string message = "Could not find collection plane calibration factor";
4230  throw std::runtime_error(message);
4231  }
4232 
4233  //double nominal_CCal = dEdX_options.get<double>("NominalCCal");
4234  double varied_CCal = dEdX_options.get<double>("VariedCCal");
4235 
4236  int selection_ID, sample_ID;
4237  double beam_inst_P;
4238  double reco_beam_endZ;
4239  std::vector<double> * calibrated_dQdX = 0x0, * beam_EField = 0x0,
4240  * track_pitch = 0x0, * reco_beam_incidentEnergies = 0x0;
4241  tree->SetBranchAddress("selection_ID", &selection_ID);
4242  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
4243  tree->SetBranchAddress("reco_beam_calibrated_dQdX_SCE", &calibrated_dQdX);
4244  tree->SetBranchAddress("reco_beam_EField_SCE", &beam_EField);
4245  tree->SetBranchAddress("reco_beam_TrkPitch_SCE", &track_pitch);
4246  tree->SetBranchAddress("reco_beam_incidentEnergies",
4247  &reco_beam_incidentEnergies);
4248  tree->SetBranchAddress("beam_inst_P", &beam_inst_P);
4249  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
4250 
4251  std::vector<double> * true_beam_traj_Z = 0x0,
4252  * true_beam_traj_KE = 0x0;
4253  std::vector<int> * true_beam_slices = 0x0;
4254  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
4255  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
4256  tree->SetBranchAddress("true_beam_slices", &true_beam_slices);
4257  std::vector<double> * true_beam_incidentEnergies = 0x0;
4258  tree->SetBranchAddress("true_beam_incidentEnergies",
4259  &true_beam_incidentEnergies);
4260  double true_beam_endP;
4261  double true_beam_interactingEnergy;
4262  tree->SetBranchAddress("true_beam_interactingEnergy",
4263  &true_beam_interactingEnergy);
4264  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
4265 
4266  std::map<int, TH1 *> & selection_hists = data_set.GetSelectionHists();
4267  flux = tree->GetEntries() - split_val;
4268  for (int i = /*0*/split_val; i < tree->GetEntries(); ++i) {
4269  tree->GetEntry(i);
4270  TH1D * selection_hist = (TH1D*)selection_hists[selection_ID];
4271 
4272  double val = 1.;
4273  if (selection_ID == 4) {
4274  if (selection_hist->FindBin(reco_beam_endZ) == 0) {
4275  val = selection_hist->GetBinCenter(1);
4276  }
4277  else if (selection_hist->FindBin(reco_beam_endZ) >
4278  selection_hist->GetNbinsX()) {
4279  val = selection_hist->GetBinCenter(
4280  selection_hist->GetNbinsX());
4281  }
4282  else {
4283  val = reco_beam_endZ;
4284  }
4285  }
4286  else if (selection_ID > 4) {
4287  val = .5;
4288  }
4289  else if (reco_beam_incidentEnergies->size()) {
4290  double energy = sqrt(beam_inst_P*beam_inst_P*1.e6 + 139.57*139.57) -
4291  139.57;
4292  for (size_t k = 0; k < calibrated_dQdX->size()-1; ++k) {
4293  if ((*calibrated_dQdX)[k] < 0.) continue;
4294 
4295  double dedx = (nominal_CCal/varied_CCal);
4296  dedx *= (*calibrated_dQdX)[k];
4297  dedx *= (betaP / ( rho * (*beam_EField)[k] ) * wion);
4298  dedx = exp(dedx);
4299  dedx -= alpha;
4300  dedx *= ((rho*(*beam_EField)[k])/betaP);
4301 
4302  if (dedx*(*track_pitch)[k] > fEnergyFix)
4303  continue;
4304  energy -= dedx*(*track_pitch)[k];
4305  //std::cout << "Energy: " << energy[0] << " dedx: " << dedx <<
4306  // std::endl;
4307  }
4308  if (selection_hist->FindBin(energy) == 0) {
4309  val = selection_hist->GetBinCenter(1);
4310  }
4311  else if (selection_hist->FindBin(energy) >
4312  selection_hist->GetNbinsX()) {
4313  val = selection_hist->GetBinCenter(selection_hist->GetNbinsX());
4314  }
4315  else {
4316  val = energy;
4317  }
4318 
4319  }
4320  else {
4321  val = selection_hist->GetBinCenter(1);
4322  }
4323 
4324  double end_energy = true_beam_interactingEnergy;
4325  if (fSliceMethod == "Traj") {
4326  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
4327  }
4328  selection_hist->Fill(val);
4329  bool is_signal = signal_sample_checks.at(sample_ID);
4330  ThinSliceSample * this_sample = 0x0;
4331  if (is_signal) {
4332  std::vector<ThinSliceSample> & samples_vec = samples[sample_ID][0];
4333  //Get the samples vec from the first beam energy bin
4334  bool found = false;
4335  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
4336  ThinSliceSample & sample = samples_vec.at(j);
4337  if (sample.CheckInSignalRange(end_energy)) {
4338  this_sample = &sample;
4339  break;
4340  }
4341  }
4342  if (!found) {
4343  if (end_energy < samples_vec[1].RangeLowEnd()) {
4344  this_sample = &samples_vec[0];
4345  }
4346  else if (end_energy >
4347  samples_vec[samples_vec.size()-2].RangeHighEnd()) {
4348  this_sample = &samples_vec.back();
4349  }
4350  }
4351  }
4352  else {
4353  this_sample = &samples[sample_ID][0][0];
4354  }
4355  this_sample->AddVariedFlux();
4356  std::vector<double> good_true_incEnergies = MakeTrueIncidentEnergies(
4357  *true_beam_traj_Z, *true_beam_traj_KE, *true_beam_slices,
4358  *true_beam_incidentEnergies);
4359  //if (fSliceMethod == "Traj") {
4360  // double next_slice_z = fTrajZStart;
4361  // int next_slice_num = 0;
4362  // for (size_t j = 1; j < true_beam_traj_Z->size() - 1; ++j) {
4363  // double z = (*true_beam_traj_Z)[j];
4364  // double ke = (*true_beam_traj_KE)[j];
4365 
4366  // if (z < fTrajZStart) {
4367  // //std::cout << "Skipping " << z << std::endl;
4368  // continue;
4369  // }
4370 
4371  // if (z >= next_slice_z) {
4372  // double temp_z = (*true_beam_traj_Z)[j-1];
4373  // double temp_e = (*true_beam_traj_KE)[j-1];
4374  //
4375  // while (next_slice_z < z && next_slice_num < fSliceCut) {
4376  // double sub_z = next_slice_z - temp_z;
4377  // double delta_e = (*true_beam_traj_KE)[j-1] - ke;
4378  // double delta_z = z - (*true_beam_traj_Z)[j-1]/* - z*/;
4379  // temp_e -= (sub_z/delta_z)*delta_e;
4380  // good_true_incEnergies.push_back(temp_e);
4381  // temp_z = next_slice_z;
4382  // next_slice_z += fPitch;
4383  // ++next_slice_num;
4384  // }
4385  // }
4386  // }
4387  //}
4388  //else if (fSliceMethod == "Default") {
4389  // for (size_t j = 0; j < true_beam_incidentEnergies->size(); ++j) {
4390  // int slice = (*true_beam_slices)[j];
4391  // if (slice > fSliceCut) continue;
4392  // good_true_incEnergies.push_back((*true_beam_incidentEnergies)[j]);
4393  // }
4394  //}
4395  this_sample->AddIncidentEnergies(good_true_incEnergies);
4396 
4397  }
4398  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
4399  for (double & s : it->second) {
4400  s = 1.;
4401  }
4402  }
4403 }
4404 
4406  TTree * tree,
4407  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
4408  const std::map<int, bool> & signal_sample_checks,
4409  ThinSliceDataSet & data_set, double & flux,
4410  std::map<int, std::vector<double>> & sample_scales, int split_val) {
4411 
4412  //Build the map for fake data scales
4414  = fExtraOptions.get<fhicl::ParameterSet>("FakeDataEffVar");
4415 
4416  int sample_ID, selection_ID;
4417  double true_beam_interactingEnergy, reco_beam_interactingEnergy;
4418  double true_beam_endP;
4419  std::vector<double> * reco_beam_incidentEnergies = 0x0;
4420  double reco_beam_endZ;
4421  tree->SetBranchAddress("reco_beam_endZ", &reco_beam_endZ);
4422  tree->SetBranchAddress("new_interaction_topology", &sample_ID);
4423  tree->SetBranchAddress("selection_ID", &selection_ID);
4424  tree->SetBranchAddress("true_beam_interactingEnergy",
4425  &true_beam_interactingEnergy);
4426  tree->SetBranchAddress("true_beam_endP", &true_beam_endP);
4427  tree->SetBranchAddress("reco_beam_interactingEnergy",
4428  &reco_beam_interactingEnergy);
4429  tree->SetBranchAddress("reco_beam_incidentEnergies",
4430  &reco_beam_incidentEnergies);
4431  std::vector<double> * true_beam_traj_Z = 0x0,
4432  * true_beam_traj_KE = 0x0;
4433  std::vector<int> * true_beam_slices = 0x0;
4434  tree->SetBranchAddress("true_beam_traj_Z", &true_beam_traj_Z);
4435  tree->SetBranchAddress("true_beam_traj_KE", &true_beam_traj_KE);
4436  tree->SetBranchAddress("true_beam_slices", &true_beam_slices);
4437  std::vector<double> * true_beam_incidentEnergies = 0x0;
4438  tree->SetBranchAddress("true_beam_incidentEnergies",
4439  &true_beam_incidentEnergies);
4440 
4441  std::vector<double> * daughter_Theta = 0x0;
4442  tree->SetBranchAddress("reco_daughter_allTrack_Theta",
4443  &daughter_Theta);
4444  std::vector<int> * daughter_true_PDG = 0x0;
4445  tree->SetBranchAddress("reco_daughter_PFP_true_byHits_PDG",
4446  &daughter_true_PDG);
4447  std::vector<double> * daughter_track_score = 0x0;
4448  tree->SetBranchAddress("reco_daughter_PFP_trackScore_collection",
4449  &daughter_track_score);
4450 
4451  TH1D & incident_hist = data_set.GetIncidentHist();
4452  std::map<int, TH1 *> & selected_hists = data_set.GetSelectionHists();
4453 
4454  // double new_flux = 0.;
4455  flux = tree->GetEntries() - split_val;
4456 
4457 
4458  std::map<int, std::vector<double>> nominal_samples;
4459  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
4460  nominal_samples[it->first] = std::vector<double>(it->second.size(), 0.);
4461  }
4462 
4463  double check_val = options.get<double>("F");
4464  for (int i = /*0*/split_val; i < tree->GetEntries(); ++i) {
4465  tree->GetEntry(i);
4466 
4467  if (samples.find(sample_ID) == samples.end())
4468  continue;
4469 
4470  double end_energy = true_beam_interactingEnergy;
4471  if (fSliceMethod == "Traj") {
4472  end_energy = sqrt(true_beam_endP*true_beam_endP*1.e6 + 139.57*139.57) - 139.57;
4473  }
4474 
4475  double val = 0.;
4476  if (selection_ID == 4) {
4477  if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) == 0) {
4478  val = selected_hists[selection_ID]->GetBinCenter(1);
4479  }
4480  else if (selected_hists[selection_ID]->FindBin(reco_beam_endZ) >
4481  selected_hists[selection_ID]->GetNbinsX()) {
4482  val = selected_hists[selection_ID]->GetBinCenter(
4483  selected_hists[selection_ID]->GetNbinsX());
4484  }
4485  else {
4486  val = reco_beam_endZ;
4487  }
4488  }
4489  else if (selection_ID > 4) {
4490  val = .5;
4491  }
4492  else if (reco_beam_incidentEnergies->size()) {
4493  for (size_t j = 0; j < reco_beam_incidentEnergies->size(); ++j) {
4494  incident_hist.Fill((*reco_beam_incidentEnergies)[j]);
4495  }
4496  if (selected_hists.find(selection_ID) != selected_hists.end()) {
4497  if (selection_ID != 4 && selection_ID != 5 && selection_ID != 6) {
4498  double energy = reco_beam_interactingEnergy;
4499  if (fDoEnergyFix) {
4500  for (size_t k = 1; k < reco_beam_incidentEnergies->size(); ++k) {
4501  double deltaE = ((*reco_beam_incidentEnergies)[k-1] -
4502  (*reco_beam_incidentEnergies)[k]);
4503  if (deltaE > fEnergyFix) {
4504  energy += deltaE;
4505  }
4506  }
4507  }
4508  if (selected_hists[selection_ID]->FindBin(energy) == 0) {
4509  val = selected_hists[selection_ID]->GetBinCenter(1);
4510  }
4511  else if (selected_hists[selection_ID]->FindBin(energy) >
4512  selected_hists[selection_ID]->GetNbinsX()) {
4513  val = selected_hists[selection_ID]->GetBinCenter(
4514  selected_hists[selection_ID]->GetNbinsX());
4515  }
4516  else {
4517  val = energy;
4518  }
4519  }
4520  }
4521  }
4522  else {
4523  val = selected_hists[selection_ID]->GetBinCenter(1);
4524  }
4525 
4526  bool is_signal = signal_sample_checks.at(sample_ID);
4527  ThinSliceSample * this_sample = 0x0;
4528  if (is_signal) {
4529  std::vector<ThinSliceSample> & samples_vec = samples[sample_ID][0];
4530  //Get the samples vec from the first beam energy bin
4531  bool found = false;
4532  for (size_t j = 1; j < samples_vec.size()-1; ++j) {
4533  ThinSliceSample & sample = samples_vec.at(j);
4534  if (sample.CheckInSignalRange(end_energy)) {
4535  this_sample = &sample;
4536  break;
4537  }
4538  }
4539  if (!found) {
4540  if (end_energy < samples_vec[1].RangeLowEnd()) {
4541  this_sample = &samples_vec[0];
4542  }
4543  else if (end_energy >
4544  samples_vec[samples_vec.size()-2].RangeHighEnd()) {
4545  this_sample = &samples_vec.back();
4546  }
4547  }
4548  }
4549  else {
4550  this_sample = &samples[sample_ID][0][0];
4551  }
4552  this_sample->AddVariedFlux();
4553  std::vector<double> good_true_incEnergies;
4554  //if (fSliceMethod == "Traj") {
4555  // double next_slice_z = fTrajZStart;
4556  // int next_slice_num = 0;
4557  // for (size_t j = 1; j < true_beam_traj_Z->size() - 1; ++j) {
4558  // double z = (*true_beam_traj_Z)[j];
4559  // double ke = (*true_beam_traj_KE)[j];
4560 
4561  // if (z < fTrajZStart) {
4562  // //std::cout << "Skipping " << z << std::endl;
4563  // continue;
4564  // }
4565 
4566  // if (z >= next_slice_z) {
4567  // double temp_z = (*true_beam_traj_Z)[j-1];
4568  // double temp_e = (*true_beam_traj_KE)[j-1];
4569  //
4570  // while (next_slice_z < z && next_slice_num < fSliceCut) {
4571  // double sub_z = next_slice_z - temp_z;
4572  // double delta_e = (*true_beam_traj_KE)[j-1] - ke;
4573  // double delta_z = z - (*true_beam_traj_Z)[j-1]/* - z*/;
4574  // temp_e -= (sub_z/delta_z)*delta_e;
4575  // good_true_incEnergies.push_back(temp_e);
4576  // temp_z = next_slice_z;
4577  // next_slice_z += fPitch;
4578  // ++next_slice_num;
4579  // }
4580  // }
4581  // }
4582  //}
4583  //else if (fSliceMethod == "Default") {
4584  // for (size_t j = 0; j < true_beam_incidentEnergies->size(); ++j) {
4585  // int slice = (*true_beam_slices)[j];
4586  // if (slice > fSliceCut) continue;
4587  // good_true_incEnergies.push_back((*true_beam_incidentEnergies)[j]);
4588  // }
4589  //}
4590  this_sample->AddIncidentEnergies(good_true_incEnergies);
4591 
4592  if (selection_ID < 3) {
4593  int new_selection = selection_ID;
4594  for (size_t j = 0; j < daughter_Theta->size(); ++j) {
4595  if (/*(abs((*daughter_true_PDG)[j]) == 211) &&*/
4596  ((*daughter_track_score)[j] < 1. && (*daughter_track_score)[j] > .3) &&
4597  ((*daughter_Theta)[j] > -999) &&
4598  ((*daughter_Theta)[j]*180./TMath::Pi() < 20.)) {
4599  double r = fRNG.Uniform();
4600  if (r < check_val) {
4601  new_selection = 3;
4602  break;
4603  }
4604  }
4605  }
4606  selected_hists[new_selection]->Fill(val);
4607  }
4608  else {
4609  selected_hists[selection_ID]->Fill(val);
4610  }
4611  }
4612 
4613  for (auto it = sample_scales.begin(); it != sample_scales.end(); ++it) {
4614  for (size_t i = 0; i < it->second.size(); ++i) {
4615  it->second[i] = 1.;
4616  }
4617  }
4618 }
4619 
4620 std::pair<double, size_t> protoana::AbsCexDriver::CalculateChi2(
4621  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
4622  ThinSliceDataSet & data_set) {
4623 
4624  double chi2 = 0.;
4625  double alt_chi2 = 0.;
4626  size_t nPoints = 0;
4627  size_t alt_nPoints = 0;
4628 
4629  std::map<int, TH1 *> & selected_data_hists = data_set.GetSelectionHists();
4630  double total_data = 0., total_mc = 0.;
4631  double data_integral = 0.;
4632  for (auto it = selected_data_hists.begin();
4633  it != selected_data_hists.end(); ++it) {
4634  TH1D * data_hist = (TH1D*)it->second;
4635  int selection_ID = it->first;
4636  if (data_hist->GetBinContent(0) > 0.) {
4637  std::cout << "Warning: underflow bin of " << selection_ID <<
4638  " has " << data_hist->GetBinContent(0) << " events" <<
4639  std::endl;
4640  }
4641  else if (data_hist->GetBinContent(data_hist->GetNbinsX()+1) > 0.) {
4642  std::cout << "Warning: overflow bin of " << selection_ID <<
4643  " has " << data_hist->GetBinContent(data_hist->GetNbinsX()+1) <<
4644  " events" <<
4645  std::endl;
4646  }
4647 
4648 
4649  data_integral += data_hist->Integral();
4650  int start = (fSkipFirstLast ? 2 : 1);
4651  int end = data_hist->GetNbinsX();
4652  if (fSkipFirstLast) --end;
4653  for (int i = start; i <= end; ++i) {
4654  double data_val = data_hist->GetBinContent(i);
4655  //double data_err = data_hist->GetBinError(i);
4656 
4657  double mc_val = 0.;
4658  //Go through all the samples and get the values from mc
4659  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
4660  std::vector<std::vector<ThinSliceSample>> & samples_vec_2D = it2->second;
4661  for (size_t j = 0; j < samples_vec_2D.size(); ++j) {
4662  std::vector<ThinSliceSample> & samples_vec = samples_vec_2D[j];
4663  for (size_t k = 0; k < samples_vec.size(); ++k) {
4664  ThinSliceSample & sample = samples_vec[k];
4665  mc_val += sample.GetSelectionHist(selection_ID)->GetBinContent(i);
4666 
4667  TH1D * mc_hist = (TH1D*)sample.GetSelectionHist(selection_ID);
4668  if (mc_hist->GetBinContent(0) > 0.) {
4669  std::cout << "Warning: underflow bin of " << selection_ID <<
4670  " has " << mc_hist->GetBinContent(0) << " events" <<
4671  std::endl;
4672  }
4673  else if (mc_hist->GetBinContent(mc_hist->GetNbinsX()+1) > 0.) {
4674  std::cout << "Warning: overflow bin of " << selection_ID <<
4675  " has " << mc_hist->GetBinContent(mc_hist->GetNbinsX()+1) <<
4676  " events" <<
4677  std::endl;
4678  }
4679  }
4680  }
4681  }
4682  if (mc_val < 1.e-7) {
4683  std::cout << "Warning: " << selection_ID << " " << i << " mc_val " << mc_val << std::endl;
4684  }
4685  if (selection_ID < 5) {
4686  alt_chi2 += (std::pow((data_val - mc_val), 2) / mc_val);
4687  ++alt_nPoints;
4688  }
4689 
4690 
4691  /// Skip any bins with data == 0
4692  //
4693  //See PDG Stat Review:
4694  //https://pdg.lbl.gov/2018/reviews/rpp2018-rev-statistics.pdf
4695  //Page 6
4696  //
4697  if (data_val > 1.e-7)
4698  chi2 += 2*data_val*std::log(data_val/mc_val);
4699 
4700  //if (std::isnan(chi2) && fMultinomial) {
4701  // std::cout << "Warning: " << selection_ID << " " << i << " data_val " <<
4702  // data_val << " mc_val " << mc_val << " isnan" << std::endl;
4703  //}
4704  ++nPoints;
4705  total_mc += mc_val;
4706  total_data += data_val;
4707  }
4708  }
4709 
4710  //if (total_data != total_mc) {
4711  // std::cout << "WARNING: data does not match mc " << total_data << " " << total_mc << std::endl;
4712  //}
4713 
4714  //if (abs(chi2) < 1.e-7) chi2 = 0.;
4715  //std::cout << "totals (data, mc): " << total_data << " " << total_mc << std::endl;
4716  //if (chi2 < 0.) {
4717  // std::cout << "Warning: chi2 < 0. " << std::setprecision(20) << total_data << " " << total_mc <<
4718  // " " << chi2 << std::endl;
4719  // std::cout << "Data Integral " << data_integral << std::endl;
4720  //}
4721 
4722  //-1 for multinomial
4723  std::pair<double, size_t> chi2_nPoints = {chi2, nPoints-1};
4724  std::pair<double, size_t> alt_chi2_nPoints = {alt_chi2, nPoints};
4725  return (fMultinomial ? chi2_nPoints : alt_chi2_nPoints);
4726 }
4727 
4729  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
4730  ThinSliceDataSet & data_set, TFile & output_file,
4731  std::vector<std::pair<int, int>> plot_style,
4732  bool plot_rebinned,
4733  bool post_fit, int nPars,
4734  TDirectory * plot_dir) {
4735 
4736  plot_dir->cd();
4737  //output_file.cd();
4738  std::map<int, TH1*> data_hists
4739  = (plot_rebinned ?
4740  data_set.GetRebinnedSelectionHists() :
4741  data_set.GetSelectionHists());
4742  for (auto it = data_hists.begin(); it != data_hists.end(); ++it) {
4743  int selection_ID = it->first;
4744  TH1D * data_hist = (TH1D*)it->second;
4745  data_hist->SetLineColor(kBlack);
4746  data_hist->SetMarkerColor(kBlack);
4747  data_hist->SetMarkerStyle(20);
4748 
4749  std::string canvas_name_no_data = "c";
4750  canvas_name_no_data += (post_fit ? "PostFit" : "Nominal") +
4751  data_set.GetSelectionName(selection_ID) +
4752  "NoData";
4753  TCanvas cSelectionNoData(canvas_name_no_data.c_str(), "");
4754  cSelectionNoData.SetTicks();
4755 
4756  std::string canvas_name = "c";
4757  canvas_name += (post_fit ? "PostFit" : "Nominal") +
4758  data_set.GetSelectionName(selection_ID);
4759  TCanvas cSelection(canvas_name.c_str(), "");
4760  cSelection.SetTicks();
4761 
4762  std::map<int, std::vector<TH1D *>> temp_hists;
4763  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
4764  temp_hists[it2->first] = std::vector<TH1D *>();
4765  std::vector<ThinSliceSample> & vec = it2->second[0];
4766  for (size_t i = 0; i < vec.size(); ++i) {
4767  temp_hists[it2->first].push_back((TH1D*)(
4768  plot_rebinned ?
4769  vec[i].GetRebinnedSelectionHist(selection_ID) :
4770  vec[i].GetSelectionHist(selection_ID))->Clone());
4771  }
4772  for (size_t i = 1; i < it2->second.size(); ++i) {
4773  for (size_t j = 0; j < it2->second[i].size(); ++j) {
4774  temp_hists[it2->first][j]->Add((TH1D*)(
4775  plot_rebinned ?
4776  it2->second[i][j].GetRebinnedSelectionHist(selection_ID) :
4777  it2->second[i][j].GetSelectionHist(selection_ID)));
4778  }
4779  }
4780  }
4781  //Build the mc stack
4782  std::string stack_name = (post_fit ? "PostFit" : "Nominal") +
4783  data_set.GetSelectionName(selection_ID) +
4784  "Stack";
4785  THStack mc_stack(stack_name.c_str(), "");
4786  TLegend leg;
4787  std::vector<TH1D*> temp_vec;
4788  size_t iColor = 0;
4789  //need to add second loop with temp hists
4790  for (auto it2 = temp_hists.begin(); it2 != temp_hists.end(); ++it2) {
4791  for (size_t i = 0; i < it2->second.size(); ++i) {
4792  TH1D * sel_hist = it2->second.at(i);
4793  std::pair<int, int> color_fill = GetColorAndStyle(iColor, plot_style);
4794  sel_hist->SetFillColor(color_fill.first);
4795  sel_hist->SetFillStyle(color_fill.second);
4796  sel_hist->SetLineColor(kBlack);
4797  mc_stack.Add(sel_hist);
4798  temp_vec.push_back(sel_hist);
4799  ++iColor;
4800  }
4801  }
4802  mc_stack.Write();
4803 
4804  for (auto it = temp_vec.rbegin(); it != temp_vec.rend(); ++it) {
4805  leg.AddEntry(*it);
4806  }
4807 
4808  cSelectionNoData.cd();
4809  mc_stack.Draw("hist");
4810  std::string title_no_data = ";";
4811  title_no_data += data_hist->GetXaxis()->GetTitle();
4812  mc_stack.SetTitle(title_no_data.c_str());
4813  mc_stack.GetHistogram()->SetTitleSize(.04, "X");
4814  mc_stack.Draw("hist");
4815  if (it == data_hists.begin())
4816  leg.Write("leg_no_data");
4817  cSelectionNoData.Write();
4818  leg.Draw("same");
4819 
4820 
4821 
4822 
4823  leg.AddEntry(data_hist, "Data");
4824 
4825  std::pair<double, size_t> chi2 = CalculateChi2(samples, data_set);
4826  if (chi2.first < 0. && chi2.first > -1.e7) {
4827  chi2.first = 0.;
4828  }
4829  /*std::string chi2_str = "#chi^{2}/ndof = " +
4830  std::to_string(chi2.first) + "/" +
4831  std::to_string(chi2.second - nPars);*/
4832  TString chi2_str;
4833  chi2_str.Form("#chi^{2} = %.2f", chi2.first);
4834  leg.AddEntry((TObject*)0x0, chi2_str, "");
4835  //std::string chi2_str = "#chi^{2} = " + std::to_string(chi2.first);
4836  //leg.AddEntry((TObject*)0x0, chi2_str.c_str(), "");
4837 
4838  cSelection.cd();
4839  std::string title = data_set.GetSelectionName(selection_ID);
4840  title += ";";
4841  title += data_hist->GetXaxis()->GetTitle();
4842  mc_stack.SetTitle(title.c_str());
4843 
4844  mc_stack.Draw("hist");
4845  double max_mc = mc_stack.GetHistogram()->GetMaximum();
4846  int max_data_bin = data_hist->GetMaximumBin();
4847  double max_data = data_hist->GetBinContent(max_data_bin) +
4848  data_hist->GetBinError(max_data_bin);
4849  mc_stack.SetMaximum((max_data > max_mc ? max_data : max_mc));
4850  mc_stack.Draw("hist");
4851  data_hist->Draw("e1 same");
4852  leg.Draw("same");
4853 
4854  cSelection.Write();
4855 
4856  //Get the full incident hist from stack
4857  TList * l = (TList*)mc_stack.GetHists();
4858  TH1D * hMC = (TH1D*)l->At(0)->Clone();
4859  for (int i = 1; i < l->GetSize(); ++i) {
4860  hMC->Add((TH1D*)l->At(i));
4861  }
4862 
4863  std::string ratio_name = data_set.GetSelectionName(selection_ID) + "Ratio" +
4864  (post_fit ? "PostFit" : "Nominal");
4865  TH1D * hRatio
4866  = (TH1D*)data_hist->Clone(ratio_name.c_str());
4867  hRatio->Divide(hMC);
4868  hRatio->Write();
4869  std::string total_name = (post_fit ? "PostFit" : "Nominal") +
4870  data_set.GetSelectionName(selection_ID) +
4871  "Total";
4872  hMC->Write(total_name.c_str());
4873 
4874  canvas_name += "Ratio";
4875  TCanvas cRatio(canvas_name.c_str(), "");
4876  cRatio.SetTicks();
4877  TPad p1((canvas_name + "pad1").c_str(), "", 0, 0.3, 1., 1.);
4878  p1.SetBottomMargin(0.1);
4879  p1.Draw();
4880  p1.cd();
4881  mc_stack.Draw("hist");
4882  mc_stack.GetHistogram()->SetTitle("Abs;;");
4883  for (int i = 1; i < mc_stack.GetHistogram()->GetNbinsX(); ++i) {
4884  hRatio->GetXaxis()->SetBinLabel(
4885  i, mc_stack.GetHistogram()->GetXaxis()->GetBinLabel(i));
4886  mc_stack.GetHistogram()->GetXaxis()->SetBinLabel(i, "");
4887  }
4888  mc_stack.Draw("hist");
4889  data_hist->Draw("e1 same");
4890 
4891  cRatio.cd();
4892  TPad p2((canvas_name + "pad2").c_str(), "", 0, 0, 1., 0.3);
4893  p2.SetTopMargin(0.1);
4894  p2.SetBottomMargin(.2);
4895  p2.Draw();
4896  p2.cd();
4897  hRatio->Sumw2();
4898  std::string r_title = "";/*(selection_ID != 4 ?
4899  ";Reconstructed KE (MeV)" :
4900  ";Reconstructed End Z (cm)");*/
4901  //if (selection_ID == 4) {
4902  // r_title += ";Reconstructed End Z (cm)";
4903  //}
4904  //else if (selection_ID < 4) {
4905  // r_title += ";Reconstructed KE (MeV)";
4906  //}
4907  //r_title += ";Data/MC";
4908  //hRatio->SetTitle(r_title.c_str());
4909  hRatio->GetYaxis()->SetTitle("Data/MC");
4910  hRatio->SetTitleSize(.04, "XY");
4911  hRatio->Draw("ep");
4912 
4913  cRatio.Write();
4914 
4915 
4916  //Differences
4917  //Get the full incident hist from stack
4918  TH1D * hMC2 = (TH1D*)l->At(0)->Clone();
4919  for (int i = 1; i < l->GetSize(); ++i) {
4920  hMC2->Add((TH1D*)l->At(i));
4921  }
4922 
4923  std::string diff_name = data_set.GetSelectionName(selection_ID) + "Diff" +
4924  (post_fit ? "PostFit" : "Nominal");
4925  TH1D * hDiff
4926  = (TH1D*)data_hist->Clone(diff_name.c_str());
4927  hMC2->Scale(-1.);
4928  hDiff->Add(hMC2);
4929  hMC2->Scale(-1.);
4930  hDiff->Divide(hMC2);
4931  hDiff->Write();
4932 
4933  canvas_name += "Diff";
4934  TCanvas cDiff(canvas_name.c_str(), "");
4935  cDiff.SetTicks();
4936  /*TPad p1((canvas_name + "pad1").c_str(), "", 0, 0.3, 1., 1.);
4937  p1.SetBottomMargin(0.1);
4938  p1.Draw();
4939  p1.cd();
4940  mc_stack.Draw("hist");
4941  mc_stack.GetHistogram()->SetTitle("Abs;;");
4942  for (int i = 1; i < mc_stack.GetHistogram()->GetNbinsX(); ++i) {
4943  hDiff->GetXaxis()->SetBinLabel(
4944  i, mc_stack.GetHistogram()->GetXaxis()->GetBinLabel(i));
4945  mc_stack.GetHistogram()->GetXaxis()->SetBinLabel(i, "");
4946  }
4947  mc_stack.Draw("hist");
4948  data_hist->Draw("e1 same");*/
4949 
4950  cDiff.cd();
4951  /*TPad p3((canvas_name + "pad3").c_str(), "", 0, 0, 1., 0.3);
4952  p3.SetTopMargin(0.1);
4953  p3.SetBottomMargin(.2);
4954  p3.Draw();
4955  p3.cd();*/
4956  //hDiff->Sumw2();
4957  /*std::string r_title = "";*//*(selection_ID != 4 ?
4958  ";Reconstructed KE (MeV)" :
4959  ";Reconstructed End Z (cm)");*/
4960  //if (selection_ID == 4) {
4961  // r_title += ";Reconstructed End Z (cm)";
4962  //}
4963  //else if (selection_ID < 4) {
4964  // r_title += ";Reconstructed KE (MeV)";
4965  //}
4966  //r_title += ";Data/MC";
4967  //hDiff->SetTitle(r_title.c_str());
4968  hDiff->GetYaxis()->SetTitle("r");
4969  hDiff->SetTitleSize(.04, "XY");
4970  hDiff->Draw("ep");
4971 
4972  cDiff.Write();
4973 
4974  ///Write in NoStacks here
4975 
4976  }
4977 
4978  double total_muons = 0.;
4979  double total = 0.;
4980  for (auto it = samples.begin(); it != samples.end(); ++it) {
4981  for (size_t i = 0; i < it->second.size(); ++i) {
4982  for (size_t j = 0; j < it->second[i].size(); ++j) {
4983  if (it->first == 5) {
4984  total_muons += it->second[i][j].GetVariedFlux();
4985  }
4986  total += it->second[i][j].GetVariedFlux();
4987  }
4988  }
4989  }
4990 }
4991 
4993  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
4994  ThinSliceDataSet & data_set,
4995  std::map<int, std::vector<TH1*>> & throw_hists,
4996  bool plot_rebinned) {
4997 
4998  //Use data set as a template
4999  std::map<int, TH1*> data_hists
5000  = (plot_rebinned ?
5001  data_set.GetRebinnedSelectionHists() :
5002  data_set.GetSelectionHists());
5003 
5004  for (auto it = data_hists.begin(); it != data_hists.end(); ++it) {
5005  std::vector<double> bins;
5006  std::string name = data_set.GetSelectionName(it->first) + "Throw" +
5007  std::to_string(throw_hists[it->first].size());
5008 
5009  TH1D * temp_hist = (TH1D*)it->second->Clone(name.c_str());
5010  temp_hist->Reset();
5011  throw_hists[it->first].push_back(temp_hist);
5012  }
5013 
5014  //Iterate over samples
5015  for (auto it = throw_hists.begin(); it != throw_hists.end(); ++it) {
5016  int selection_ID = it->first;
5017  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
5018  std::vector<std::vector<ThinSliceSample>> & samples_vec_2D = it2->second;
5019  for (size_t j = 0; j < samples_vec_2D.size(); ++j) {
5020  std::vector<ThinSliceSample> & samples_vec = samples_vec_2D[j];
5021  for (size_t k = 0; k < samples_vec.size(); ++k) {
5022  ThinSliceSample & sample = samples_vec[k];
5023  for (int i = 1; i <= it->second.back()->GetNbinsX(); ++i) {
5024  it->second.back()->AddBinContent(i,
5025  sample.GetSelectionHist(selection_ID)->GetBinContent(i));
5026  }
5027  }
5028  }
5029  }
5030  }
5031 }
5032 
5034  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
5035  std::map<int, std::vector<TH1*>> & throw_hists,
5036  std::map<int, std::vector<TH1*>> & throw_inc_hists,
5037  std::map<int, std::vector<TH1*>> & throw_xsec_hists,
5038  const std::vector<int> & incident_samples,
5039  const std::map<int, std::vector<double>> & signal_bins) {
5040  //Loop over the samples
5041  for (auto it = samples.begin(); it != samples.end(); ++it) {
5042  //Get the number of bins from the first entry of the beam energy bins
5043  std::vector<std::vector<ThinSliceSample>> & samples_vec_2D = it->second;
5044  size_t nBins = samples_vec_2D[0].size();
5045  std::string name = it->second[0][0].GetName() + "Throw" +
5046  std::to_string(throw_hists[it->first].size());
5047  TH1D * temp_hist = new TH1D(name.c_str(), "", nBins, 0, nBins);
5048  for (size_t i = 0; i < samples_vec_2D.size(); ++i) {
5049  std::vector<ThinSliceSample> & samples_vec = samples_vec_2D[i];
5050  for (size_t j = 0; j < it->second[i].size(); ++j) {
5051  temp_hist->AddBinContent(j+1, samples_vec[j].GetVariedFlux());
5052  }
5053  }
5054  throw_hists[it->first].push_back(temp_hist);
5055  }
5056 
5057  for (auto it = throw_inc_hists.begin(); it != throw_inc_hists.end(); ++it) {
5058  int s = it->first;
5059  auto & samples_vec_2D = samples[s];
5060  const std::vector<double> & bins = signal_bins.at(s);
5061  std::string name = samples_vec_2D[0][0].GetName();
5062  name += "IncidentThrow" +
5063  std::to_string(throw_inc_hists[it->first].size());
5064  TH1D * temp_inc_hist = new TH1D(name.c_str(), "", bins.size() - 1, &bins[0]);
5065 
5066 
5067  name = samples_vec_2D[0][0].GetName();
5068  name += "XSecThrow" +
5069  std::to_string(throw_inc_hists[it->first].size());
5070  TH1D * temp_xsec_hist = new TH1D(name.c_str(), "", bins.size() - 1,
5071  &bins[0]);
5072  for (auto i_s : incident_samples) {
5073  auto & incident_vec_2D = samples[i_s];
5074  for (size_t i = 0; i < incident_vec_2D.size(); ++i) {
5075  for (size_t j = 0; j < incident_vec_2D[i].size(); ++j) {
5076  //if (fExtraOptions.get<std::string>("SliceMethod") == "E") {
5077  if (/*fExtraOptions.get<std::string>("SliceMethod")*/fSliceMethod == "E") {
5078  incident_vec_2D[i][j].FillESliceHist(*temp_inc_hist);
5079  }
5080  else {
5081  incident_vec_2D[i][j].FillHistFromIncidentEnergies(*temp_inc_hist);
5082  }
5083  }
5084  }
5085  }
5086  throw_inc_hists[s].push_back(temp_inc_hist);
5087 
5088  for (int i = 1; i <= temp_xsec_hist->GetNbinsX(); ++i) {
5089  temp_xsec_hist->SetBinContent(
5090  i, throw_hists[s].back()->GetBinContent(i+1));
5091  }
5092  temp_xsec_hist->Divide(temp_inc_hist);
5093  throw_xsec_hists[s].push_back(temp_xsec_hist);
5094  }
5095 }
5096 
5098  ThinSliceDataSet & data_set, std::map<int, std::vector<TH1*>> & throw_hists,
5099  std::map<int, std::vector<std::vector<ThinSliceSample>>> & samples,
5100  size_t nThrows,
5101  std::map<int, std::vector<TH1*>> & truth_throw_hists,
5102  std::map<int, std::vector<TH1*>> & truth_inc_hists,
5103  std::map<int, std::vector<TH1*>> & truth_xsec_hists,
5104  std::map<int, TH1*> & best_fit_incs,
5105  std::map<int, TH1*> & best_fit_xsecs,
5106  std::map<int, TH1*> & nominal_incs,
5107  std::map<int, TH1*> & nominal_xsecs,
5108  TFile & output_file, bool plot_rebinned,
5109  std::map<int, std::vector<double>> * sample_scales) {
5110  std::map<int, TH1*> data_hists
5111  = (plot_rebinned ?
5112  data_set.GetRebinnedSelectionHists() :
5113  data_set.GetSelectionHists());
5114 
5115  //Build best fit hists and get bins for covariance
5116  std::map<int, TH1D*> best_fit_selection_hists;
5117  int nBins = 0;
5118  for (auto it = data_hists.begin(); it != data_hists.end(); ++it ) {
5119  TH1D * best_fit_hist = (TH1D*)it->second->Clone();
5120  best_fit_hist->Reset();
5121  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
5122  for (size_t i = 0; i < it2->second.size(); ++i) {
5123  for (size_t j = 0; j < it2->second[i].size(); ++j) {
5124  it2->second[i][j].SetFactorToBestFit();
5125  best_fit_hist->Add(
5126  (TH1D*)(plot_rebinned ?
5127  it2->second[i][j].GetRebinnedSelectionHist(it->first) :
5128  it2->second[i][j].GetSelectionHist(it->first)));
5129  }
5130  }
5131  }
5132  best_fit_selection_hists[it->first] = best_fit_hist;
5133  nBins += best_fit_hist->GetNbinsX();
5134  }
5135 
5136  TH2D selection_cov("SelectionCov", "", nBins, 0, nBins, nBins, 0, nBins);
5137 
5138  nBins = 0;
5139  std::map<int, size_t> sample_bins;
5140  for (auto it = samples.begin(); it != samples.end(); ++it) {
5141  nBins += it->second[0].size();
5142  sample_bins[it->first] = it->second[0].size();
5143  }
5144 
5145  std::map<int, std::vector<double>> best_fit_truth;
5146  std::map<int, std::vector<double>> best_fit_errs;
5147 
5148  for (auto it = samples.begin(); it != samples.end(); ++it) {
5149  best_fit_truth[it->first]
5150  = std::vector<double>(sample_bins[it->first], 0.);
5151  best_fit_errs[it->first]
5152  = std::vector<double>(sample_bins[it->first], 0.);
5153 
5154  for (size_t i = 0; i < sample_bins[it->first]; ++i) {
5155  double best_fit_val_i = 0.;
5156  for (size_t j = 0; j < it->second.size(); ++j) {
5157  best_fit_val_i += it->second[j][i].GetVariedFlux();
5158  }
5159 
5160  best_fit_truth[it->first][i] = best_fit_val_i;
5161  }
5162  }
5163 
5164  TH2D interaction_cov("interaction_cov", "", nBins, 0, nBins, nBins, 0, nBins);
5165  std::map<int, std::vector<double>> best_fit_inc_truth;
5166  std::map<int, std::vector<double>> best_fit_xsec_truth;
5167  std::map<int, std::vector<double>> best_fit_inc_errs;
5168  std::map<int, std::vector<double>> best_fit_xsec_errs;
5169 
5170  nBins = 0;
5171  std::map<int, size_t> xsec_bins;
5172  for (auto it = best_fit_incs.begin(); it != best_fit_incs.end(); ++it) {
5173  int s = it->first;
5174  nBins += it->second->GetNbinsX();
5175  xsec_bins[s] = it->second->GetNbinsX();
5176 
5177  best_fit_inc_truth[s] = std::vector<double>(xsec_bins[s], 0.);
5178  best_fit_xsec_truth[s] = std::vector<double>(xsec_bins[s], 0.);
5179  best_fit_inc_errs[s] = std::vector<double>(xsec_bins[s], 0.);
5180  best_fit_xsec_errs[s] = std::vector<double>(xsec_bins[s], 0.);
5181 
5182  for (size_t i = 0; i < xsec_bins[s]; ++i) {
5183  best_fit_inc_truth[s][i] = it->second->GetBinContent(i+1);
5184  best_fit_xsec_truth[s][i] = best_fit_xsecs[s]->GetBinContent(i+1);
5185  }
5186  }
5187 
5188  //TH2D incident_cov("incident_cov", "", nBins, 0, nBins, nBins, 0, nBins);
5189  TH2D xsec_cov("xsec_cov", "", nBins, 0, nBins, nBins, 0, nBins);
5190 
5191  for (size_t z = 0; z < nThrows; ++z) {
5192  int bin_i = 1;
5193  for (auto it = best_fit_selection_hists.begin();
5194  it != best_fit_selection_hists.end(); ++it) {
5195  TH1D * best_fit = it->second;
5196  int selection_ID = it->first;
5197  std::vector<TH1*> & temp_throws = throw_hists[selection_ID];
5198  for (int i = 1; i <= best_fit->GetNbinsX(); ++i) {
5199  double best_fit_val_i = best_fit->GetBinContent(i);
5200  int bin_j = 1;
5201  for (auto it2 = best_fit_selection_hists.begin();
5202  it2 != best_fit_selection_hists.end(); ++it2) {
5203 
5204  TH1D * best_fit_2 = it2->second;
5205  int selection_ID_2 = it2->first;
5206  std::vector<TH1*> & temp_throws_2 = throw_hists[selection_ID_2];
5207  for (int j = 1; j <= best_fit_2->GetNbinsX(); ++j) {
5208  double best_fit_val_j = best_fit_2->GetBinContent(j);
5209  double val = (best_fit_val_i - temp_throws[z]->GetBinContent(i))*
5210  (best_fit_val_j - temp_throws_2[z]->GetBinContent(j));
5211  selection_cov.SetBinContent(
5212  bin_i, bin_j, (val/temp_throws.size() +
5213  selection_cov.GetBinContent(bin_i, bin_j)));
5214  ++bin_j;
5215  }
5216  }
5217  ++bin_i;
5218  }
5219  }
5220 
5221  bin_i = 1;
5222  for (auto it = samples.begin(); it != samples.end(); ++it) {
5223  std::vector<TH1 *> throw_hists_i = truth_throw_hists[it->first];
5224 
5225  for (size_t i = 0; i < sample_bins[it->first]; ++i) {
5226  double best_fit_val_i = best_fit_truth[it->first][i];
5227 
5228  int bin_j = 1;
5229  for (auto it2 = samples.begin(); it2 != samples.end(); ++it2) {
5230  std::vector<TH1 *> throw_hists_j = truth_throw_hists[it2->first];
5231  for (size_t j = 0; j < sample_bins[it2->first]; ++j) {
5232  double best_fit_val_j = best_fit_truth[it2->first][j];
5233 
5234  double val
5235  = (throw_hists_i[z]->GetBinContent(i+1) - best_fit_val_i)*
5236  (throw_hists_j[z]->GetBinContent(j+1) - best_fit_val_j);
5237  interaction_cov.SetBinContent(
5238  bin_i, bin_j,
5239  (interaction_cov.GetBinContent(bin_i, bin_j) +
5240  val/throw_hists_i.size()));
5241  if (bin_i == bin_j && (z == nThrows - 1)) {
5242  best_fit_errs[it->first][i]
5243  = sqrt(interaction_cov.GetBinContent(bin_i, bin_j));
5244  }
5245  ++bin_j;
5246  }
5247  }
5248 
5249  ++bin_i;
5250  }
5251  }
5252 
5253  bin_i = 1;
5254  for (auto it = truth_inc_hists.begin(); it != truth_inc_hists.end(); ++it) {
5255  //std::vector<TH1 *> inc_hists_i = it->second;
5256  std::vector<TH1 *> xsec_hists_i = truth_xsec_hists[it->first];
5257 
5258  for (size_t i = 0; i < xsec_bins[it->first]; ++i) {
5259  //double best_fit_inc_i = best_fit_inc_truth[it->first][i];
5260  double best_fit_xsec_i = best_fit_xsec_truth[it->first][i];
5261 
5262  int bin_j = 1;
5263  for (auto it2 = truth_inc_hists.begin(); it2 != truth_inc_hists.end();
5264  ++it2) {
5265  std::vector<TH1 *> xsec_hists_j = truth_xsec_hists[it2->first];
5266  for (size_t j = 0; j < xsec_bins[it2->first]; ++j) {
5267  double best_fit_xsec_j = best_fit_xsec_truth[it2->first][j];
5268 
5269  double val
5270  = (xsec_hists_i[z]->GetBinContent(i+1) - best_fit_xsec_i)*
5271  (xsec_hists_j[z]->GetBinContent(j+1) - best_fit_xsec_j);
5272  xsec_cov.SetBinContent(
5273  bin_i, bin_j,
5274  (xsec_cov.GetBinContent(bin_i, bin_j) +
5275  val/nThrows));
5276  if (bin_i == bin_j && (z == nThrows - 1)) {
5277  best_fit_xsec_errs[it->first][i]
5278  = sqrt(xsec_cov.GetBinContent(bin_i, bin_j));
5279  }
5280  }
5281  }
5282  }
5283  }
5284  }
5285 
5286 
5287  output_file.cd("Throws");
5288  selection_cov.Write();
5289  interaction_cov.Write();
5290  xsec_cov.Write();
5291 
5292  int bin_count = 0;
5293  for (auto it = data_hists.begin(); it != data_hists.end(); ++it) {
5294  int selection_ID = it->first;
5295  std::vector<TH1*> hists = throw_hists.at(selection_ID);
5296 
5297  std::string canvas_name = "cThrow" +
5298  data_set.GetSelectionName(selection_ID);
5299  TCanvas cThrow(canvas_name.c_str(), "");
5300  cThrow.SetTicks();
5301 
5302  std::string name = "Throw" + data_set.GetSelectionName(selection_ID);
5303  auto data_hist = it->second;
5304  std::vector<double> xs, xs_width;
5305  std::vector<double> ys, errs;
5306  for (int i = 1;
5307  i <= best_fit_selection_hists[it->first]->GetNbinsX(); ++i) {
5308  ys.push_back(
5309  best_fit_selection_hists[it->first]->GetBinContent(i));
5310  errs.push_back(
5311  sqrt(selection_cov.GetBinContent(bin_count+i, bin_count+i)));
5312  xs.push_back(data_hist->GetBinCenter(i));
5313  xs_width.push_back(data_hist->GetBinWidth(i)/2.);
5314  }
5315 
5316  TGraphAsymmErrors throw_gr(data_hist->GetNbinsX(),
5317  &xs[0], &ys[0],
5318  &xs_width[0], &xs_width[0], &errs[0], &errs[0]);
5319 
5320  throw_gr.SetFillStyle(3144);
5321  throw_gr.SetFillColor(kRed);
5322  throw_gr.Draw("a2");
5323  data_hist->Draw("same e1");
5324  output_file.cd("Throws");
5325  cThrow.Write();
5326 
5327  bin_count += data_hist->GetNbinsX();
5328  }
5329 
5330  bin_count = 0;
5331  for (auto it = truth_throw_hists.begin(); it != truth_throw_hists.end(); ++it) {
5332  int sample_ID = it->first;
5333 
5334  std::vector<double> xs, xs_width;
5335  for (size_t i = 0; i < sample_bins[it->first]; ++i) {
5336  xs.push_back(i + 0.5);
5337  xs_width.push_back(.5);
5338  }
5339 
5340  std::string name = "hNominal" + samples[sample_ID][0][0].GetName();
5341  TH1D temp_nominal(name.c_str(), "", xs.size(), 0, xs.size());
5342  std::vector<std::vector<ThinSliceSample>> & samples_vec_2D
5343  = samples[sample_ID];
5344  for (size_t i = 0; i < samples_vec_2D.size(); ++i) {
5345  for (size_t j = 0; j < samples_vec_2D[i].size(); ++j) {
5346  temp_nominal.AddBinContent(j+1, samples_vec_2D[i][j].GetNominalFlux());
5347  }
5348  }
5349 
5350  double max = -999.;
5351  for (size_t i = 0; i < sample_bins[it->first]; ++i) {
5352  if ((best_fit_truth[sample_ID][i] + best_fit_errs[sample_ID][i]) > max)
5353  max = (best_fit_truth[sample_ID][i] + best_fit_errs[sample_ID][i]);
5354 
5355  if (temp_nominal.GetBinContent(i+1) > max)
5356  max = temp_nominal.GetBinContent(i+1);
5357  }
5358 
5359  output_file.cd("Throws");
5360  std::string canvas_name = "cTruthThrow" + samples[sample_ID][0][0].GetName();
5361  TCanvas cThrow(canvas_name.c_str(), "");
5362  cThrow.SetTicks();
5363  TGraphAsymmErrors throw_gr(xs.size(),
5364  &xs[0], &best_fit_truth[it->first][0],
5365  &xs_width[0], &xs_width[0],
5366  &best_fit_errs[it->first][0],
5367  &best_fit_errs[it->first][0]);
5368  throw_gr.SetFillStyle(3144);
5369  throw_gr.SetFillColor(kRed);
5370  throw_gr.SetMinimum(0.);
5371  throw_gr.SetMaximum(1.5*max);
5372  throw_gr.Draw("a2");
5373  throw_gr.Draw("p");
5374 
5375  temp_nominal.SetMarkerColor(kBlue);
5376  temp_nominal.SetMarkerStyle(20);
5377  temp_nominal.Draw("same p");
5378 
5379  TLegend leg;
5380  leg.AddEntry(&throw_gr, "Throws", "lpf");
5381  leg.AddEntry(&temp_nominal, "Nominal", "p");
5382 
5383  if (sample_scales) {
5384  name = "hVaried" + samples[sample_ID][0][0].GetName();
5385  TH1D * temp_varied = (TH1D*)temp_nominal.Clone(name.c_str());
5386  for (size_t i = 0; i < xs.size(); ++i) {
5387  temp_varied->SetBinContent(
5388  i+1, temp_varied->GetBinContent(i+1)*(*sample_scales)[sample_ID][i]);
5389  }
5390  temp_varied->SetMarkerColor(kBlack);
5391  temp_varied->SetMarkerStyle(20);
5392  temp_varied->Draw("same p");
5393  leg.AddEntry(temp_varied, "Fake Data", "p");
5394  }
5395 
5396  leg.Draw();
5397  cThrow.Write();
5398 
5399  bin_count += xs.size();
5400  }
5401 
5402  for (auto it = best_fit_xsec_truth.begin(); it != best_fit_xsec_truth.end();
5403  ++it) {
5404  int sample_ID = it->first;
5405 
5406  std::vector<double> xs, xs_width;
5407  for (size_t i = 0; i < xsec_bins[sample_ID]; ++i) {
5408  xs.push_back(i + 0.5);
5409  xs_width.push_back(.5);
5410  }
5411 
5412  output_file.cd("Throws");
5413  std::string canvas_name = "cXSecThrow" + samples[sample_ID][0][0].GetName();
5414  TCanvas cThrow(canvas_name.c_str(), "");
5415  cThrow.SetTicks();
5416  TGraphAsymmErrors throw_gr(xs.size(),
5417  &xs[0], &best_fit_xsec_truth[it->first][0],
5418  &xs_width[0], &xs_width[0],
5419  &best_fit_xsec_errs[it->first][0],
5420  &best_fit_xsec_errs[it->first][0]);
5421  throw_gr.SetFillStyle(3144);
5422  throw_gr.SetFillColor(kRed);
5423  throw_gr.SetMinimum(0.);
5424  throw_gr.Draw("a2");
5425  throw_gr.Draw("p");
5426 
5427  cThrow.Write();
5428  }
5429 }
5430 
5432  const ThinSliceEvent & event,
5433  double C_cal,
5434  TProfile * prot_template) {
5435 
5436  if (event.GetSelectionID() > 3) {
5437  return event.GetSelectionID();
5438  }
5439 
5440  //Look for charged pions
5441  //bool has_pi0_shower = false;
5442  const std::vector<double> & track_scores = event.GetRecoDaughterTrackScores();
5443  for (size_t i = 0; i < track_scores.size(); ++i) {
5444 
5445  if (track_scores[i] > 0.3) {
5446  //Here: recalculate dEdX and truncated mean dEdX
5447  std::vector<double> new_dEdX, new_res_range;
5448  const std::vector<double> & calibrated_dQdX
5449  = event.GetRecoDaughterTrackdQdXs()[i];
5450  const std::vector<double> & daughter_EField
5451  = event.GetRecoDaughterEFields()[i];
5452  const std::vector<double> & res_range
5453  =event.GetRecoDaughterTrackResRanges()[i];
5454  for (size_t j = 0; j < calibrated_dQdX.size(); ++j) {
5455  //std::cout << C_cal << " " << (calibrated_dQdX)[j] << " " << fBetaP << " "
5456  // << fRho << " " << daughter_EField[j] << " " << fWion << " "
5457  // << fAlpha << std::endl;
5458  if (calibrated_dQdX[j] < 0)
5459  continue;
5460  //std::cout << "Warning dqdx < 0: " << calibrated_dQdX[j] << std::endl;
5461  double dedx = C_cal;//(1./*/(C_cal)*/);
5462  dedx *= (calibrated_dQdX)[j];
5463  dedx *= (fBetaP / ( fRho * (daughter_EField)[j] ) * fWion);
5464  dedx = exp(dedx);
5465  dedx -= fAlpha;
5466  dedx *= ((fRho*(daughter_EField)[j])/fBetaP);
5467  new_dEdX.push_back(dedx);
5468  new_res_range.push_back(res_range[j]);
5469 
5470  //std::cout << "Added " << dedx << std::endl;
5471  }
5472 
5473  double truncated_mean = TruncatedMean(new_dEdX);
5474  //std::cout << i << " trunc mean: " << truncated_mean << " ";
5475 
5476  if (truncated_mean < 2.8 && truncated_mean > 0.5) {
5477  // std::cout << std::endl;
5478  return 3;
5479  }
5480  else if (truncated_mean > 2.8 && truncated_mean < 3.4) {
5481  std::pair<double, int> pid_chi2_ndof
5482  = fTrackUtil.Chi2PID(
5483  new_dEdX, new_res_range, prot_template);
5484  // std::cout << pid_chi2_ndof.first/pid_chi2_ndof.second;
5485  if (pid_chi2_ndof.second > 0 &&
5486  pid_chi2_ndof.first/pid_chi2_ndof.second > 70.) {
5487  //if (event.GetSelectionID() != 3) {
5488  // std::cout << i << " chi2: " << pid_chi2_ndof.first/pid_chi2_ndof.second << " " << truncated_mean << std::endl;
5489  // std::cout << "\t" << new_dEdX.size() << " " << new_res_range.size() << std::endl;
5490  //}
5491  // std::cout << std::endl;
5492  return 3;
5493  }
5494  }
5495  // std::cout << std::endl;
5496  }
5497  }
5498 
5499  if (event.GetHasPi0Shower()) return 2;
5500 
5501  return 1;
5502 }
5503 
5504 double protoana::AbsCexDriver::TruncatedMean(const std::vector<double> & dEdX) {
5505  if (!dEdX.size()) return -999.;
5506  std::vector<double> temp_dEdX;
5507  for (auto d : dEdX) {
5508  if (d < 0) continue;
5509  temp_dEdX.push_back(d);
5510  }
5511  std::sort(temp_dEdX.begin(), temp_dEdX.end());
5512  size_t low = std::rint(temp_dEdX.size()*0.16);
5513  size_t high = std::rint(temp_dEdX.size()*0.84);
5514  std::vector<double> temp;
5515  for (size_t i = low; i < high; ++i) {
5516  temp.push_back(temp_dEdX[i]);
5517  }
5518  if (temp.empty()) return -999.;
5519  return std::accumulate(temp.begin(), temp.end(), 0.0)/temp.size();
5520 }
5521 
5523  const std::vector<double> & true_beam_traj_Z,
5524  const std::vector<double> & true_beam_traj_KE,
5525  const std::vector<int> & true_beam_slices,
5526  const std::vector<double> & true_beam_incidentEnergies) {
5527  std::vector<double> results;
5528  if (fSliceMethod == "Traj") {
5529  double next_slice_z = fTrajZStart;
5530  int next_slice_num = 0;
5531  for (size_t j = 1; j < true_beam_traj_Z.size() - 1; ++j) {
5532  double z = true_beam_traj_Z[j];
5533  double ke = true_beam_traj_KE[j];
5534 
5535  if (z < fTrajZStart) {
5536  continue;
5537  }
5538 
5539  if (z >= next_slice_z) {
5540  double temp_z = true_beam_traj_Z[j-1];
5541  double temp_e = true_beam_traj_KE[j-1];
5542 
5543  while (next_slice_z < z && next_slice_num < fSliceCut) {
5544  double sub_z = next_slice_z - temp_z;
5545  double delta_e = true_beam_traj_KE[j-1] - ke;
5546  double delta_z = z - true_beam_traj_Z[j-1];
5547  temp_e -= (sub_z/delta_z)*delta_e;
5548  results.push_back(temp_e);
5549  temp_z = next_slice_z;
5550  next_slice_z += fPitch;
5551  ++next_slice_num;
5552  }
5553  }
5554  }
5555  }
5556  else if (fSliceMethod == "Default") {
5557  for (size_t j = 0; j < true_beam_incidentEnergies.size(); ++j) {
5558  int slice = true_beam_slices[j];
5559  if (slice > fSliceCut) continue;
5560  results.push_back(true_beam_incidentEnergies[j]);
5561  }
5562  }
5563  else if (fSliceMethod == "Alt") {
5564  int bin = fEndSlices->GetXaxis()->FindBin(true_beam_traj_Z.back());
5565  for (int i = 1; i <= bin; ++i) {
5566  results.push_back(fMeans.at(i));
5567  }
5568  }
5569 
5570  return results;
5571 }
5572 
5574  const std::vector<double> & beam_energy_bins,
5575  const double & true_beam_startP) {
5576  int bin = -1;
5577  for (size_t j = 1; j < beam_energy_bins.size(); ++j) {
5578  if ((beam_energy_bins[j-1] <= 1.e3*true_beam_startP) &&
5579  (1.e3*true_beam_startP < beam_energy_bins[j])) {
5580  bin = j - 1;
5581  break;
5582  }
5583  }
5584  if (bin == -1) {
5585  std::string message = "Could not find beam energy bin for " +
5586  std::to_string(true_beam_startP);
5587  throw std::runtime_error(message);
5588  }
5589  return bin;
5590 }
static QCString name
Definition: declinfo.cpp:673
std::pair< double, double > fSystBeamShiftLimits
Definition: AbsCexDriver.h:300
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
double GetSystWeight_EffVar(const ThinSliceEvent &event, const std::map< std::string, ThinSliceSystematic > &pars)
void FakeDataG4RWGrid(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, std::vector< double > &beam_energy_bins, int split_val=0)
void SetupSyst_BeamShiftSpline2(const std::vector< ThinSliceEvent > &events, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< std::string, ThinSliceSystematic > &pars, TFile &output_file)
std::pair< int, int > GetColorAndStyle(size_t i, const std::vector< std::pair< int, int >> &plot_style)
void AddESliceEnergies(const std::pair< double, double > &vals, double weight=1.)
void GetCurrentHists(std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, ThinSliceDataSet &data_set, std::map< int, std::vector< TH1 * >> &throw_hists, bool plot_rebinned) override
std::string string
Definition: nybbler.cc:12
unsigned int ID
void SetupSysts(const std::vector< ThinSliceEvent > &events, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, std::vector< double > &beam_energy_bins, const std::map< std::string, ThinSliceSystematic > &pars, TFile &output_file) override
bool GetHasPi0Shower() const
void AddVariedFlux(double val=1.)
std::map< std::string, std::map< int, std::vector< TSpline3 * > > > fFullSelectionSplines
Definition: AbsCexDriver.h:304
char & at(uint i) const
Definition: qcstring.h:326
constexpr T pow(T x)
Definition: pow.h:72
double GetSystWeight_BeamEffs(const ThinSliceEvent &event, const std::map< std::string, ThinSliceSystematic > &pars)
struct vector vector
std::vector< double > MakeTrueIncidentEnergies(const std::vector< double > &true_beam_traj_Z, const std::vector< double > &true_beam_traj_KE, const std::vector< int > &true_beam_slices, const std::vector< double > &true_beam_incidentEnergies)
void FakeDataBeamWeight(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, int split_val=0)
void FakeDatadEdX(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, int split_val=0)
STL namespace.
std::map< int, TH1 * > & GetSelectionHists()
int GetBeamBin(const std::vector< double > &beam_energy_bins, const double &true_beam_startP)
std::map< int, double > fMeans
Definition: AbsCexDriver.h:267
int FindBin(double value, std::vector< double > binning)
uint size() const
Definition: qcstring.h:201
string dir
void FakeDataAngleVar(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, int split_val=0)
void FakeDataSampleScales(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, int split_val=0)
int RecalculateSelectionID(const ThinSliceEvent &event, double C_cal, TProfile *prot_template)
void SetupSyst_BeamEffsWeight(const std::map< std::string, ThinSliceSystematic > &pars)
double GetSystWeight_BeamShift(const ThinSliceEvent &event, const std::map< std::string, ThinSliceSystematic > &pars)
void SetupSyst_BeamShiftSpline(const std::vector< ThinSliceEvent > &events, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< std::string, ThinSliceSystematic > &pars, TFile &output_file)
static QStrList * l
Definition: config.cpp:1044
double GetSystWeight_EDiv(const ThinSliceEvent &event, const std::map< std::string, ThinSliceSystematic > &pars)
void WrapUpSysts(TFile &output_file) override
weight
Definition: test.py:257
double dEdX(double KE, const simb::MCParticle *part)
void AddIncidentEnergies(const std::vector< double > &vals, double weight=1.)
void SetupSyst_dEdX_Cal(const std::vector< ThinSliceEvent > &events, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< std::string, ThinSliceSystematic > &pars, TFile &output_file)
void FakeDataPionAngle(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, int split_val=0)
void SetupSyst_EffVarWeight(const std::map< std::string, ThinSliceSystematic > &pars)
void SetupSyst_EDivWeight(const std::map< std::string, ThinSliceSystematic > &pars)
void AddFlux(double val=1.)
const double e
double GetTrueStartP() const
std::vector< TSpline3 * > fBeamShiftRatioSplines
Definition: AbsCexDriver.h:327
double GetSplineWeight(std::string syst_name, double par_val, int selection_ID, double val) const
TH1 * GetSelectionHist(int id)
std::void_t< T > n
void BuildDataHists(TTree *tree, ThinSliceDataSet &data_set, double &flux, int split_val=0) override
T get(std::string const &key) const
Definition: ParameterSet.h:271
void FakeDataBinnedScales(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, int split_val=0)
double alpha
Definition: doAna.cpp:15
double GetSystWeight_NoTrack(const ThinSliceEvent &event, const std::map< std::string, ThinSliceSystematic > &pars)
p
Definition: test.py:223
const std::map< int, TH1 * > & GetSelectionHists() const
std::map< int, TH1 * > & GetRebinnedSelectionHists()
virtual void GetCurrentTruthHists(std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, std::map< int, std::vector< TH1 * >> &hists, std::map< int, std::vector< TH1 * >> &inc_hists, std::map< int, std::vector< TH1 * >> &xsec_hists, const std::vector< int > &incident_samples, const std::map< int, std::vector< double >> &signal_bins) override
ProtoDUNETrackUtils fTrackUtil
Definition: AbsCexDriver.h:313
void PlotThrows(ThinSliceDataSet &data_set, std::map< int, std::vector< TH1 * >> &throw_hists, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, size_t nThrows, std::map< int, std::vector< TH1 * >> &truth_throw_hists, std::map< int, std::vector< TH1 * >> &truth_inc_hists, std::map< int, std::vector< TH1 * >> &truth_xsec_hists, std::map< int, TH1 * > &best_fit_incs, std::map< int, TH1 * > &best_fit_xsecs, std::map< int, TH1 * > &nominal_incs, std::map< int, TH1 * > &nominal_xsecs, TFile &output_file, bool plot_rebinned, std::map< int, std::vector< double >> *sample_scales=0x0) override
double TruncatedMean(const std::vector< double > &dEdX)
static int max(int a, int b)
void BuildMCSamples(const std::vector< ThinSliceEvent > &events, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, std::map< int, double > &nominal_fluxes, std::map< int, std::vector< std::vector< double >>> &fluxes_by_sample, std::vector< double > &beam_energy_bins) override
double GetSystWeight_G4RW(const ThinSliceEvent &event, const std::map< std::string, ThinSliceSystematic > &pars, const ThinSliceSample &sample, int selection_ID, double val)
void FillSelectionHist(int id, double val, double weight=1.)
void SetupSyst_EffVar(const std::vector< ThinSliceEvent > &events, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< std::string, ThinSliceSystematic > &pars, TFile &output_file)
auto selection_ID
void FillTrueIncidentHist(const std::vector< double > &vals, double weight=1.)
std::pair< double, int > Chi2PID(const std::vector< double > &track_dedx, const std::vector< double > &range, TProfile *profile)
std::string fSliceMethod
Definition: AbsCexDriver.h:278
fhicl::ParameterSet fExtraOptions
std::map< std::string, std::map< int, std::vector< TH1D * > > > fFullSelectionVars
Definition: AbsCexDriver.h:303
std::vector< std::string > fActiveG4RWSysts
Definition: AbsCexDriver.h:308
int var
Definition: 018_def.c:9
const int & GetFluxType() const
void SetupSyst_NoTrackWeight(const std::map< std::string, ThinSliceSystematic > &pars)
std::string & GetSelectionName(int id)
QTextStream & bin(QTextStream &s)
bool CheckInSignalRange(double val)
void FakeDataEffVar(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, int split_val=0)
void SetupSyst_BeamShiftRatio(const std::vector< ThinSliceEvent > &events, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< std::string, ThinSliceSystematic > &pars, TFile &output_file)
void FillMCEvents(TTree *tree, std::vector< ThinSliceEvent > &events, std::vector< ThinSliceEvent > &fake_data_events, int &split_val, const bool &do_split) override
void FillSystematicShift(std::string syst_name, int selection_ID, const std::vector< double > &vals)
void FakeDataG4RW(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, int split_val=0)
#define DECLARE_THINSLICEDRIVER_FACTORY_NS(driver, nsname, driverbase)
void CompareSelections(std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, ThinSliceDataSet &data_set, TFile &output_file, std::vector< std::pair< int, int >> plot_style, bool plot_rebinned, bool post_fit, int nPars, TDirectory *plot_dir) override
void SetupSyst_BeamShift(const std::map< std::string, ThinSliceSystematic > &pars, TFile &output_file)
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
void SetupSyst_G4RW(const std::vector< ThinSliceEvent > &events, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, std::vector< double > &beam_energy_bins, const std::map< std::string, ThinSliceSystematic > &pars, TFile &output_file)
std::pair< double, size_t > CalculateChi2(std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, ThinSliceDataSet &data_set) override
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
void BuildFakeData(TTree *tree, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, ThinSliceDataSet &data_set, double &flux, std::map< int, std::vector< double >> &sample_scales, std::vector< double > &beam_energy_bins, int split_val=0) override
static constexpr double ys
Definition: Units.h:103
if(!yymsg) yymsg
TGraph2D * fSystBeamShiftMap
Definition: AbsCexDriver.h:297
int bool
Definition: qglobal.h:345
void RefillMCSamples(const std::vector< ThinSliceEvent > &events, std::map< int, std::vector< std::vector< ThinSliceSample >>> &samples, const std::map< int, bool > &signal_sample_checks, std::vector< double > &beam_energy_bins, const std::map< int, std::vector< double >> &signal_pars, const std::map< int, double > &flux_pars, const std::map< std::string, ThinSliceSystematic > &syst_pars, bool fit_under_over, bool fill_incident=false) override
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:16
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
static QCString * s
Definition: config.cpp:1042
AbsCexDriver(const fhicl::ParameterSet &extra_options)
QTextStream & endl(QTextStream &s)
Event finding and building.