All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Covariance.cxx
Go to the documentation of this file.
1 #include <string>
2 #include <vector>
3 #include <TChain.h>
4 #include <TTree.h>
5 #include "Covariance.h"
6 
7 #include <map>
8 #include <cmath>
9 #include <iostream>
10 #include <ctime>
11 #include <cassert>
12 
13 #include <TFile.h>
14 #include <TVector3.h>
15 #include <TH1D.h>
16 #include <TH2D.h>
17 #include <TH3D.h>
18 #include <THStack.h>
19 #include <TROOT.h>
20 #include <TCanvas.h>
21 #include <TMath.h>
22 #include <TCanvas.h>
23 #include <core/Event.hh>
24 
25 namespace ana {
26 namespace SBNOsc {
27 
28 Covariance::EventSample::EventSample(const fhicl::ParameterSet &config, unsigned nUniverses, unsigned nVariations) {
29  // get configuration stuff
30  fBins = config.get<std::vector<double> >("binlims");
31  fName = config.get<std::string>("name", "");
32  fScalePOT = config.get<double>("ScalePOT", -1);
33  fScaleCC = config.get<double>("ScaleCC", 1);
34  fScaleNC = config.get<double>("ScaleNC", 1);
35  fScaleEnergy = config.get<double>("ScaleEnergy", 1);
36  fPOT = 0.;
37  fEnergyBinScale = config.get<std::vector<double>>("energy_bin_scale", {});
38  if (fEnergyBinScale.size() == 0) {
39  fEnergyBinScale = std::vector<double>(fBins.size() - 1, 1.0);
40  }
41  else assert(fEnergyBinScale.size() == fBins.size() - 1);
42 
43  // setup histograms
44  std::string cv_title = fName + " Central Value";
45  fCentralValue = new TH1D(cv_title.c_str(), cv_title.c_str(), fBins.size() - 1, &fBins[0]);
46 
47  for (unsigned var_i = 0; var_i < nVariations; var_i++) {
48  fUniverses.emplace_back();
49  for (unsigned i = 0; i < nUniverses; i++) {
50  std::string uni_title = fName + " Variation " + std::to_string(var_i) + " Universe " + std::to_string(i);
51  fUniverses[var_i].push_back(
52  new TH1D(uni_title.c_str(), uni_title.c_str(), fBins.size() - 1, &fBins[0])
53  );
54  }
55  }
56 
57 }
58 
59 
60 // Gets scale factors (weights) for different universes
61 std::vector <float> GetUniWeights(const std::map <std::string, std::vector <float> > &weights, const std::vector<std::string> &keys, int n_unis, int uni_offset) {
62  std::vector <float> uweights;
63  for (int u = 0; u < n_unis; u++) {
64  float weight = 1.;
65  for (auto const &key: keys) {
66  const std::vector<float>& this_weights = weights.at(key);
67  int wind = u + uni_offset;
68  weight *= this_weights.at(wind);
69  }
70  uweights.push_back(weight);
71  }
72  return uweights;
73 }
74 
75 
76 void Covariance::Initialize(fhicl::ParameterSet* config) {
77  // must have config
78  assert(config != NULL);
79  // Weight and universe stuff
80  // WeightKey can either be the name of a single weight, or a name signifying a list of weights,
81  // or a list of weights to be oscillated
82 
83  fhicl::ParameterSet pconfig = config->get<fhicl::ParameterSet>("Covariance");
84 
85  fWeightKeys = pconfig.get<std::vector<std::vector<std::string>>>("WeightKey");
86  fWeightKeysCC = pconfig.get<std::vector<std::vector<std::string>>>("WeightKeyCC", {});
87  fWeightKeysNC = pconfig.get<std::vector<std::vector<std::string>>>("WeightKeyNC", {});
88  fNVariations = fWeightKeys.size();
89 
90  // all should have the same size
91  assert(fWeightKeysCC.size() == 0 || fWeightKeysCC.size() == fWeightKeys.size());
92  assert(fWeightKeysNC.size() == 0 || fWeightKeysNC.size() == fWeightKeys.size());
93 
94  // merge weight keys into CC/NC keys
95  if (fWeightKeysCC.size() == 0) {
96  fWeightKeysCC = fWeightKeys;
97  }
98  else {
99  for (unsigned i = 0; i < fNVariations; i++) {
100  fWeightKeysCC[i].insert(fWeightKeysCC[i].end(), fWeightKeys[i].begin(), fWeightKeys[i].end());
101  }
102  }
103  if (fWeightKeysNC.size() == 0) {
104  fWeightKeysNC = fWeightKeys;
105  }
106  else {
107  for (unsigned i = 0; i < fNVariations; i++) {
108  fWeightKeysNC[i].insert(fWeightKeysNC[i].end(), fWeightKeys[i].begin(), fWeightKeys[i].end());
109  }
110  }
111 
112  // number of universes to be used
113  fNumAltUnis = pconfig.get<int>("NumAltUnis", 0);
114  // and offset into the eventweight vector
115  fAltUniOffset = pconfig.get<int>("AltUniOffset", 0);
116 
117  // Type of energy
118  fEnergyType = pconfig.get<std::string>("EnergyType", "Reco");
119 
120  // Further selection and rejection 'efficiencies'
121  fSelectionEfficiency = pconfig.get<double>("SelectionEfficiency", 1.0);
122  fBackgroundRejection = pconfig.get<double>("BackgroundRejection", 0.0);
123 
124  // maximum weight for covariance calculation
125  // If an event has any weight larger than this value, it will be
126  // thrown away for the purposes of covariance construction
127  fWeightMax = pconfig.get<double>("WeightMax", -1.);
128 
129  // get event samples
130  std::vector<fhicl::ParameterSet> configEventSamples = \
131  config->get<std::vector<fhicl::ParameterSet> >("EventSamples");
132  for (const fhicl::ParameterSet& sample : configEventSamples) {
133  fEventSamples.emplace_back(sample, fNumAltUnis, fNVariations);
134  }
135 
136  // set output directory
137  fOutputFile = pconfig.get<std::string>("OutputFile", "");
138 
139  // whether to save things
140  fSaveCentralValue = pconfig.get<bool>("SaveCentralValue", false);
141  fSaveUniverses = pconfig.get<bool>("SaveUniverses", false);
142 
143  // start out at the zeroth sample
144  fSampleIndex = 0;
145 }
146 
147 void Covariance::ProcessSubRun(const SubRun *subrun) {
148  fEventSamples[fSampleIndex].fPOT += subrun->totgoodpot;
149 }
150 
152  // iterate over each interaction in the event
153  for (int n = 0; n < event->reco.size(); n++) {
154  unsigned truth_ind = event->reco[n].truth_index;
155 
156  // Get energy
157  int idx = event->reco[n].truth_index;
158  if (idx < 0 || idx > event->truth.size()) {
159  continue;
160  }
161  double true_nuE = event->truth[idx].neutrino.energy;
162  double nuE;
163  if (fEnergyType == "CCQE") {
164  nuE = event->truth[truth_ind].neutrino.eccqe;
165  } else if (fEnergyType == "True") {
166  nuE = true_nuE;
167  } else if (fEnergyType == "Reco") {
168  nuE = event->reco[n].reco_energy;
169  }
170  nuE *= fEventSamples[fSampleIndex].fScaleEnergy;
171 
172  // Apply selection (or rejection) efficiencies
173  int isCC = event->truth[truth_ind].neutrino.iscc;
174  // double wgt = isCC*(fSelectionEfficiency) + (1-isCC)*(1 - fBackgroundRejection);
175  // apply scaling from fScaleFactor
176  // wgt *= fEventSamples[fSampleIndex].fScaleFactor;
177  // apply uniform weights
178  // for (auto const &key: fUniformWeights) {
179  // wgt *= event->truth[truth_ind].weights.at(key)[0];
180  // }
181  double wgt = event->reco[n].weight;
182  // apply POT scaling if configured
183  if (fEventSamples[fSampleIndex].fScalePOT > 0) {
184  wgt *= fEventSamples[fSampleIndex].fScalePOT / fEventSamples[fSampleIndex].fPOT;
185  }
186 
187  if (event->truth[truth_ind].neutrino.iscc) {
188  wgt *= fEventSamples[fSampleIndex].fScaleCC;
189  }
190  else {
191  wgt *= fEventSamples[fSampleIndex].fScaleNC;
192  }
193 
194  std::vector<std::vector <float>> uweights;
195  // Get weights for each alternative universe
196  if (isCC) {
197  for (std::vector<std::string> &weight_keys: fWeightKeysCC) {
198  uweights.push_back(
199  GetUniWeights(event->truth[truth_ind].weights, weight_keys, fNumAltUnis, fAltUniOffset)
200  );
201  }
202  }
203  else {
204  for (std::vector<std::string> &weight_keys: fWeightKeysNC) {
205  uweights.push_back(
206  GetUniWeights(event->truth[truth_ind].weights, weight_keys, fNumAltUnis, fAltUniOffset)
207  );
208  }
209  }
210 
211  // see if weight is too big
212  if (fWeightMax > 0) {
213  double max_weight = 0;
214  for (std::vector<float> &weights: uweights) {
215  float this_max_weight = *std::max_element(weights.begin(), weights.end());
216  if (this_max_weight > max_weight) max_weight = this_max_weight;
217  }
218  if (max_weight > fWeightMax) {
219  std::cout << "Weight (" << max_weight << ") over cap (" << fWeightMax <<
220  ") for event with energy (" << nuE << ") in sample " << fEventSamples[fSampleIndex].fName << std::endl;
221  continue;
222  }
223  }
224 
225  // Add to base and bkg count histogram
226  fEventSamples[fSampleIndex].fCentralValue->Fill(nuE, wgt);
227 
228  // Fill alternative universe histograms
229  for (unsigned variation = 0; variation < uweights.size(); variation++) {
230  for (int u = 0; u < uweights[variation].size(); u++) {
231  fEventSamples[fSampleIndex].fUniverses[variation][u]->Fill(nuE, wgt*uweights[variation][u]);
232  }
233  }
234  }
235 }
236 
238  for (int sample_i = 0; sample_i < fEventSamples.size(); sample_i++) {
239  for (int i = 1; i < fEventSamples[sample_i].fCentralValue->GetNbinsX()+1; i++) {
240  //std::cout << "pre sample: " << sample_i << " bin content: " << fEventSamples[sample_i].fCentralValue->GetBinContent(i);
241  fEventSamples[sample_i].fCentralValue->SetBinContent(i,
242  fEventSamples[sample_i].fEnergyBinScale[i-1] * fEventSamples[sample_i].fCentralValue->GetBinContent(i));
243  //std::cout << "post sample: " << sample_i << " bin content: " << fEventSamples[sample_i].fCentralValue->GetBinContent(i);
244  }
245  for (int variation = 0; variation < fNVariations; variation++) {
246  for (int uni = 0; uni < fNumAltUnis; uni++) {
247  for (int i = 1; i < fEventSamples[sample_i].fUniverses[variation][uni]->GetNbinsX(); i++) {
248  double content = fEventSamples[sample_i].fUniverses[variation][uni]->GetBinContent(i);
249  fEventSamples[sample_i].fUniverses[variation][uni]->SetBinContent(i, content * fEventSamples[sample_i].fEnergyBinScale[i-1]);
250  }
251  }
252  }
253  }
254 }
255 
256 
257 void Covariance::FileCleanup(TTree *eventTree) {
258  // onto the next sample
259  fSampleIndex ++;
260 }
261 
263  for (unsigned i = 0; i < fNVariations; i++) GetCovPerVariation(i);
264 }
265 
266 void Covariance::GetCovPerVariation(unsigned variation) {
267 
268  //// Get covariances, fractional covariances and correlation coefficients
269  //// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
270 
271  std::cout << std::endl << "Getting covs..." << std::endl;
272 
273  // get the total number of bins across all samples
274  unsigned num_bins = 0;
275  for (auto const &sample: fEventSamples) {
276  num_bins += sample.fCentralValue->GetNbinsX();
277  }
278 
279 
280  std::string covariance_name = "Covariance " + std::to_string(variation);
281  std::string fractional_covariance_name = "Fractional Covariance " + std::to_string(variation);
282  // Covariance and fractional covariance
283  cov.emplace_back(covariance_name.c_str(), covariance_name.c_str(), num_bins, 0, num_bins, num_bins, 0, num_bins);
284  fcov.emplace_back(fractional_covariance_name.c_str(), fractional_covariance_name.c_str(), num_bins, 0, num_bins, num_bins, 0, num_bins);
285 
286  // indexes into covariance
287  unsigned cov_i = 0;
288  unsigned cov_j = 0;
289  // iterate over samples and bins
290  for (auto const &sample_i: fEventSamples) {
291  for (unsigned sample_i_bin_index = 0; sample_i_bin_index < sample_i.fCentralValue->GetNbinsX(); sample_i_bin_index++) {
292  // Get Central Value
293  float i_central = sample_i.fCentralValue->GetBinContent(sample_i_bin_index+1);
294  for (auto const &sample_j: fEventSamples) {
295  for (unsigned sample_j_bin_index = 0; sample_j_bin_index < sample_j.fCentralValue->GetNbinsX(); sample_j_bin_index++) {
296  // Get Central Value
297  float j_central = sample_j.fCentralValue->GetBinContent(sample_j_bin_index+1);
298  // calculate covariance
299  float cov_value = 0.;
300  for (int u = 0; u < fNumAltUnis; u++) {
301  // get variations
302  float i_variation = sample_i.fUniverses[variation][u]->GetBinContent(sample_i_bin_index+1);
303  float j_variation = sample_j.fUniverses[variation][u]->GetBinContent(sample_j_bin_index+1);
304  cov_value += (i_central - i_variation) * (j_central - j_variation);
305  }
306  // average
307  if (fNumAltUnis != 0) cov_value /= fNumAltUnis;
308 
309  // calculate fractional covariance
310  float fcov_value;
311  if (i_central * j_central < 1e-6) {
312  fcov_value = 0.;
313  }
314  else {
315  fcov_value = cov_value / (i_central * j_central);
316  }
317 
318  // save values
319  cov[variation].SetBinContent(cov_i + 1, cov_j + 1, cov_value);
320  fcov[variation].SetBinContent(cov_i + 1, cov_j + 1, fcov_value);
321  // update covariance position
322  cov_j ++;
323  }
324  }
325  // update covariance position
326  cov_i ++;
327  // reset j
328  cov_j = 0;
329  }
330  }
331 
332  std::string correlation_name = "Correlation " + std::to_string(variation);
333 
334  // Pearson Correlation Coefficients
335  corr.emplace_back(correlation_name.c_str(), correlation_name.c_str(), num_bins, 0, num_bins, num_bins, 0, num_bins);
336 
337  for (int i = 0; i < num_bins; i++) {
338  float covii = cov[variation].GetBinContent(i+1, i+1);
339  for (int j = 0; j < num_bins; j++) {
340  float covjj = cov[variation].GetBinContent(j+1, j+1);
341  float covij = cov[variation].GetBinContent(i+1, j+1);
342 
343  float corrij;
344  // handle case where covariance is 0
345  if (covii*covjj < 1e-6) {
346  corrij = 0.;
347  }
348  else {
349  corrij = covij / TMath::Sqrt(covii*covjj);
350  }
351  corr[variation].SetBinContent(i+1, j+1, corrij);
352  }
353  }
354 
355  // Add bin labels
356  std::vector <TH2D*> hists = {&cov[variation], &fcov[variation], &corr[variation]};
357  unsigned bin = 0;
358  for (auto const &sample: fEventSamples) {
359  // Set label
360  for (TH2D* hist : hists) {
361  hist->GetXaxis()->SetBinLabel(1+bin, sample.fName.c_str());
362  hist->GetYaxis()->SetBinLabel(1+bin, sample.fName.c_str());
363  }
364  // update bin positions
365  bin += sample.fBins.size() - 1;
366 
367  }
368 
369  for (TH2D* hist : hists) { hist->GetXaxis()->LabelsOption("h"); hist->GetYaxis()->LabelsOption("v"); }
370 
371  std::cout << std::endl << " Got covs." << std::endl;
372 
373 }
374 
376  // if output file not set, don't write
377  if (fOutputFile == "") return;
378 
379  // Write Covariances
380  TFile *output = TFile::Open(fOutputFile.c_str(), "recreate");
381  assert(output && output->IsOpen());
382 
383  for (TH2D &h: cov) h.Write();
384  for (TH2D &h: fcov) h.Write();
385  for (TH2D &h: corr) h.Write();
386 
387  // write histos
388  if (fSaveCentralValue) {
389  for (auto const &sample: fEventSamples) {
390  sample.fCentralValue->Write();
391  }
392  }
393  if (fSaveUniverses) {
394  for (auto const &sample: fEventSamples) {
395  for (unsigned i =0; i < fNVariations; i++) {
396  for (TH1D *h: sample.fUniverses[i]) {
397  h->Write();
398  }
399  }
400  }
401  }
402  // close file
403  output->Close();
404 }
405 
406 // Turn the covariance TH2D into a matrix -- include stat uncertainty
408  TMatrixDSym E_mat(cov[0].GetNbinsX());
409  for (int i = 0; i < cov[0].GetNbinsX(); i++) {
410  for (int j = 0; j < cov[0].GetNbinsY(); j++) {
411  E_mat[i][j] = 0.; // zero-initialize
412  for (TH2D &cov_histo: cov) E_mat[i][j] += cov_histo.GetBinContent(i+1, j+1); // add all systematics
413  // add statistical uncertainty
414  if (i == j) {
415  unsigned stat_ind = i;
416  float stat_uncertainty;
417  // get index into CV bin to get stat uncertainty
418  for (auto const &sample: fEventSamples) {
419  if (stat_ind < sample.fCentralValue->GetNbinsX()) {
420  stat_uncertainty = sample.fCentralValue->GetBinContent(1+stat_ind);
421  break;
422  }
423  else stat_ind -= sample.fCentralValue->GetNbinsX();
424  }
425  E_mat[i][i] += stat_uncertainty;
426  }
427  }
428  }
429  return E_mat;
430 }
431 
432 } // namespace SBNOsc
433 } // namespace ana
434 
436 
std::vector< TH2D > cov
Covariance Matrix per variation.
Definition: Covariance.h:51
double fScalePOT
Factor for POT (etc.) scaling.
Definition: Covariance.h:66
TH1D * fCentralValue
central value histogram
Definition: Covariance.h:68
std::string fName
Name for the sample.
Definition: Covariance.h:71
std::vector< std::vector< std::string > > fWeightKeysNC
Definition: Covariance.h:79
TMatrixDSym CovarianceMatrix()
Definition: Covariance.cxx:407
std::string fOutputFile
Definition: Covariance.h:89
void Initialize(fhicl::ParameterSet *config)
Definition: Covariance.cxx:76
std::vector< TH2D > fcov
Fractional Covariance Matrix per variation.
Definition: Covariance.h:52
std::vector< std::vector< std::string > > fWeightKeysCC
Definition: Covariance.h:78
process_name opflashCryoW ana
std::vector< std::vector< std::string > > fWeightKeys
Definition: Covariance.h:77
std::vector< double > fEnergyBinScale
Definition: Covariance.h:72
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
std::vector< std::vector< TH1D * > > fUniverses
List of histogram per systematic universe.
Definition: Covariance.h:69
std::vector< TH2D > corr
Correlation Matrix per variation.
Definition: Covariance.h:53
while getopts h
std::string fEnergyType
Definition: Covariance.h:82
#define DECLARE_SBN_POSTPROCESSOR(classname)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
float totgoodpot
Definition: SubRun.hh:40
The standard subrun data definition.
Definition: SubRun.hh:23
void GetCovPerVariation(unsigned variation)
Definition: Covariance.cxx:266
void ProcessSubRun(const SubRun *subrun)
Definition: Covariance.cxx:147
The standard event data definition.
Definition: Event.hh:228
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
Var Sqrt(const Var &v)
Use to take sqrt of a var.
Definition: Var.cxx:172
std::string to_string(WindowPattern const &pattern)
BEGIN_PROLOG sequence::SlidingWindowTriggerPatternsOppositeWindows END_PROLOG simSlidingORM6O6 effSlidingORW output
EventSample(const fhicl::ParameterSet &config, unsigned nUniverses, unsigned nVariations)
Definition: Covariance.cxx:28
std::vector< EventSample > fEventSamples
Definition: Covariance.h:101
do i e
void FileCleanup(TTree *eventTree)
Definition: Covariance.cxx:257
void ProcessEvent(const event::Event *event)
Definition: Covariance.cxx:151
BEGIN_PROLOG could also be cout
std::vector< double > fBins
Energy bin limits.
Definition: Covariance.h:67
std::vector< float > GetUniWeights(const std::map< std::string, std::vector< float > > &weights, const std::vector< std::string > &keys, int n_unis, int uni_offset)
Definition: Covariance.cxx:61
std::vector< Interaction > truth
All truth interactions.
Definition: Event.hh:232