All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ReweightableSpectrum.cxx
Go to the documentation of this file.
2 
9 
10 #include "TDirectory.h"
11 #include "TH2.h"
12 #include "TObjString.h"
13 
14 #include <cassert>
15 #include <iostream>
16 #include <memory>
17 
18 namespace ana
19 {
20  //----------------------------------------------------------------------
22  const HistAxis& recoAxis,
23  const HistAxis& trueAxis,
24  const Cut& cut,
25  const SystShifts& shift,
26  const Var& wei)
27  : ReweightableSpectrum(loader, recoAxis, trueAxis, kNoSpillCut, cut, shift, wei)
28  {
29  }
30 
31  //----------------------------------------------------------------------
33  const HistAxis& recoAxis,
34  const HistAxis& trueAxis,
35  const SpillCut& spillcut,
36  const SliceCut& slicecut,
37  const SystShifts& shift,
38  const Var& wei)
39  : ReweightableSpectrum(recoAxis.GetLabels(), recoAxis.GetBinnings(),
40  trueAxis.GetVars()[0])
41  {
42  assert(trueAxis.NDimensions() == 1);
43 
44  fTrueLabel = trueAxis.GetLabels()[0];
45 
46  DontAddDirectory guard;
47 
48  // Can't use HistCache here because y-axis is not necessarily
49  // TrueEnergyBinning. TODO - that should maybe be generalized.
50 
51  const std::string name = UniqueName();
52 
53  Binning xbins = fBins[0];
54  if(fBins.size() > 1){
55  int n = 1;
56  for(const Binning& b: fBins) n *= b.NBins();
57  xbins = Binning::Simple(n, 0, n);
58  }
59 
60  const Binning ybins = trueAxis.GetBinnings()[0];
61 
62 
63  // Ugh combinatorics
64  if(xbins.IsSimple() && ybins.IsSimple())
65  fHist = new TH2D(name.c_str(), "",
66  xbins.NBins(), xbins.Min(), xbins.Max(),
67  ybins.NBins(), ybins.Min(), ybins.Max());
68 
69  if(xbins.IsSimple() && !ybins.IsSimple())
70  fHist = new TH2D(name.c_str(), "",
71  xbins.NBins(), xbins.Min(), xbins.Max(),
72  ybins.NBins(), &ybins.Edges()[0]);
73 
74  if(!xbins.IsSimple() && ybins.IsSimple())
75  fHist = new TH2D(name.c_str(), "",
76  xbins.NBins(), &xbins.Edges()[0],
77  ybins.NBins(), ybins.Min(), ybins.Max());
78 
79  if(!xbins.IsSimple() && !ybins.IsSimple())
80  fHist = new TH2D(name.c_str(), "",
81  xbins.NBins(), &xbins.Edges()[0],
82  ybins.NBins(), &ybins.Edges()[0]);
83 
84  loader.AddReweightableSpectrum(*this, recoAxis.GetMultiDVar(), spillcut, slicecut, shift, wei);
85  }
86 
87  //----------------------------------------------------------------------
89  const std::string& xlabel, const std::string& ylabel,
90  double pot,
91  int nbinsx, double xmin, double xmax,
92  int nbinsy, double ymin, double ymax)
93  : ReweightableSpectrum(xlabel,
94  Binning::Simple(nbinsx, xmin, xmax),
95  rwVar)
96  {
97  DontAddDirectory guard;
98 
99  fHist = new TH2D(UniqueName().c_str(), "",
100  nbinsx, xmin, xmax, nbinsy, ymin, ymax);
101 
102  fTrueLabel = ylabel;
103 
104  // Ensure errors get accumulated properly
105  fHist->Sumw2();
106  }
107 
108  //----------------------------------------------------------------------
110  const std::vector<std::string>& labels,
111  const std::vector<Binning>& bins,
112  double pot, double livetime)
113  : ReweightableSpectrum(labels, bins, rwVar)
114  {
115  fPOT = pot;
116  fLivetime = livetime;
117 
118  if(!h){
119  fHist = 0;
120  return;
121  }
122 
123  DontAddDirectory guard;
124 
125  const TString className = h->ClassName();
126 
127  if(className == "TH2D"){
128  // Shortcut if types match
129  fHist = new TH2D(*((TH2D*)h));
130  }
131  else{
132  const TAxis* ax = h->GetXaxis();
133  const TAxis* ay = h->GetYaxis();
134  // Must have both or neither
135  assert(bool(ax->GetXbins()->GetArray()) == bool(ay->GetXbins()->GetArray()));
136 
137  if(ax->GetXbins()->GetArray()){
138  fHist = new TH2D(UniqueName().c_str(), "",
139  ax->GetNbins(), ax->GetXbins()->GetArray(),
140  ay->GetNbins(), ay->GetXbins()->GetArray());
141  }
142  else{
143  fHist = new TH2D(UniqueName().c_str(), "",
144  ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
145  ay->GetNbins(), ay->GetXmin(), ay->GetXmax());
146  }
147 
148  fHist->Add(h);
149  }
150 
151  fTrueLabel = h->GetYaxis()->GetTitle();
152  }
153 
154  //----------------------------------------------------------------------
156  std::unique_ptr<TH2D> h,
157  const std::vector<std::string>& labels,
158  const std::vector<Binning>& bins,
159  double pot, double livetime)
160  : ReweightableSpectrum(labels, bins, rwVar)
161  {
162  fHist = h.release();
163  fPOT = pot;
164  fLivetime = livetime;
165 
166  fTrueLabel = fHist->GetYaxis()->GetTitle();
167  }
168 
169  //----------------------------------------------------------------------
171  {
172  if(fHist && fHist->GetDirectory()){
173  static bool once = true;
174  if(once){
175  once = false;
176  std::cerr << "ReweightableSpectrum's fHist is associated with a directory. How did that happen?" << std::endl;
177  }
178  }
179 
180  // Can't use HistCache here because that expects all 2D spectra have the
181  // usual true energy binning on their y-axis. In the case that we're
182  // actually an OscillatableSpectrum that destructor will indeed take care
183  // of invoking HistCache.
184  delete fHist;
185  }
186 
187  //----------------------------------------------------------------------
189  : fRWVar(rhs.fRWVar), fLabels(rhs.fLabels), fBins(rhs.fBins)
190  {
191  DontAddDirectory guard;
192 
193  fHist = new TH2D(*rhs.fHist);
194 
195  fPOT = rhs.fPOT;
196  fLivetime = rhs.fLivetime;
197 
198  assert( rhs.fLoaderCount.empty() ); // Copying with pending loads is unexpected
199  }
200 
201  //----------------------------------------------------------------------
203  {
204  if(this == &rhs) return *this;
205 
206  DontAddDirectory guard;
207 
208  fRWVar = rhs.fRWVar;
209  fLabels = rhs.fLabels;
210  fBins = rhs.fBins;
211 
212  delete fHist;
213  fHist = new TH2D(*rhs.fHist);
214  fPOT = rhs.fPOT;
215  fLivetime = rhs.fLivetime;
216 
217  assert( fLoaderCount.empty() ); // Copying with pending loads is unexpected
218 
219  return *this;
220  }
221 
222  //----------------------------------------------------------------------
223  TH2D* ReweightableSpectrum::ToTH2(double pot) const
224  {
225  // Could have a file temporarily open
226  DontAddDirectory guard;
227 
228  TH2D* ret = new TH2D(*fHist);
229  ret->SetName(UniqueName().c_str());
230  if(fPOT){
231  ret->Scale(pot/fPOT);
232  }
233  else{
234  // How did it get events with no POT?
235  assert(ret->Integral() == 0);
236  }
237 
238 
239  std::string label;
240  for(const std::string& l: fLabels) label += l + " and ";
241  label.resize(label.size()-5); // drop the last "and"
242  ret->GetXaxis()->SetTitle(label.c_str());
243  ret->GetYaxis()->SetTitle(fTrueLabel.c_str());
244 
245  return ret;
246  }
247 
248  //----------------------------------------------------------------------
249  void ReweightableSpectrum::Fill(double x, double y, double w)
250  {
251  fHist->Fill(x, y, w);
252  }
253 
254  /// Helper for \ref Unweighted
255  void ProjectionX(TH2D* from, TH1D* to)
256  {
257  const int Nx = from->GetNbinsX();
258  const int Ny = from->GetNbinsY();
259 
260  // Direct access to the bins is faster
261  double* fromArr = from->GetArray();
262  double* toArr = to->GetArray();
263 
264  int fromBin = 0;
265  for(int y = 0; y < Ny+2; ++y){
266  for(int x = 0; x < Nx+2; ++x){
267  // Our loops go over the bins in the order they are internally in
268  // 'from', and we do overflows, so we keep up exactly. If you get
269  // paranoid, reenable this briefly.
270  // assert(fromBin == from->GetBin(x, y));
271 
272  const double z = fromArr[fromBin];
273  ++fromBin;
274 
275  toArr[x] += z;
276  }
277  }
278  }
279 
280  //----------------------------------------------------------------------
282  {
283  DontAddDirectory guard;
284 
285  // Create a suitably-sized space for the result
286  std::unique_ptr<TH1D> h(HistCache::New("", fHist->GetXaxis()));
287 
288  ProjectionX(fHist, h.get());
289 
290  return Spectrum(std::move(h), fLabels, fBins, fPOT, fLivetime);
291  }
292 
293  /// Helper for \ref WeightingVariable
294  void ProjectionY(TH2D* from, TH1D* to)
295  {
296  const int Nx = from->GetNbinsX();
297  const int Ny = from->GetNbinsY();
298 
299  // Direct access to the bins is faster
300  double* fromArr = from->GetArray();
301  double* toArr = to->GetArray();
302 
303  int fromBin = 0;
304  for(int y = 0; y < Ny+2; ++y){
305  for(int x = 0; x < Nx+2; ++x){
306  // Our loops go over the bins in the order they are internally in
307  // 'from', and we do overflows, so we keep up exactly. If you get
308  // paranoid, reenable this briefly.
309  // assert(fromBin == from->GetBin(x, y));
310 
311  const double z = fromArr[fromBin];
312  ++fromBin;
313 
314  toArr[y] += z;
315  }
316  }
317  }
318 
319  //----------------------------------------------------------------------
321  {
322  DontAddDirectory guard;
323 
324  // Create a suitably-sized space for the result
325  std::unique_ptr<TH1D> h(HistCache::New("", fHist->GetYaxis()));
326 
327  ProjectionY(fHist, h.get());
328 
329  return Spectrum(std::move(h), fLabels, fBins, fPOT, fLivetime);
330  }
331 
332  //----------------------------------------------------------------------
334  {
335  // This function is in the inner loop of oscillation fits, so some
336  // optimization has been done.
337 
338  DontAddDirectory guard;
339 
340  assert(ws->GetNbinsX() == fHist->GetNbinsY());
341 
342  TAxis* ax = fHist->GetXaxis();
343  TH1D* hRet = HistCache::New("", ax);
344 
345  const int X = fHist->GetNbinsX();
346  const int Y = fHist->GetNbinsY();
347 
348  // Direct access to the bins is faster
349  double* retArr = hRet->GetArray();
350  double* histArr = fHist->GetArray();
351 
352  int bin = 0;
353  for(int y = 0; y < Y+2; ++y){
354  const double w = ws->GetBinContent(y);
355  for(int x = 0; x < X+2; ++x){
356  // Our loops go over the bins in the order they are internally in
357  // fHist, and we do overflows, so we keep up exactly. If you get
358  // paranoid, reenable this briefly.
359 
360  // assert(bin == fHist->GetBin(x, y));
361 
362  retArr[x] += histArr[bin]*w;
363  ++bin;
364  }
365  }
366 
367  // TODO: can this all be more efficient?
368  return Spectrum(std::unique_ptr<TH1D>(hRet), fLabels, fBins, fPOT, fLivetime);
369  }
370 
371 
372  //----------------------------------------------------------------------
374  {
375  // This is a big component of what extrapolations do, so it has been
376  // optimized for speed
377 
378  Ratio corr(target, WeightingVariable());
379  std::unique_ptr<TH1D> hcorr(corr.ToTH1());
380 
381  assert(hcorr->GetNbinsX() == fHist->GetNbinsY());
382 
383  const int X = fHist->GetNbinsX();
384  const int Y = fHist->GetNbinsY();
385 
386  // Direct access to the bins is faster
387  double* histArr = fHist->GetArray();
388  double* corrArr = hcorr->GetArray();
389 
390  int bin = 0;
391  for(int y = 0; y < Y+2; ++y){
392  const double w = corrArr[y];
393  for(int x = 0; x < X+2; ++x){
394  // Our loops go over the bins in the order they are internally in
395  // fHist, and we do overflows, so we keep up exactly. If you get
396  // paranoid, reenable this briefly.
397 
398  // assert(bin == fHist->GetBin(x, y));
399 
400  histArr[bin] *= w;
401  ++bin;
402  }
403  }
404 
405  TH1D* todel = hcorr.release();
406  HistCache::Delete(todel);
407  }
408 
409  //----------------------------------------------------------------------
411  {
412  // This is a big component of what extrapolations do, so it has been
413  // optimized for speed
414 
415  Ratio corr(target, UnWeighted());
416  std::unique_ptr<TH1D> hcorr(corr.ToTH1());
417 
418  assert(hcorr->GetNbinsX() == fHist->GetNbinsX());
419 
420  const int X = fHist->GetNbinsX();
421  const int Y = fHist->GetNbinsY();
422 
423  // Direct access to the bins is faster
424  double* histArr = fHist->GetArray();
425  double* corrArr = hcorr->GetArray();
426 
427  int bin = 0;
428  for(int y = 0; y < Y+2; ++y){
429  for(int x = 0; x < X+2; ++x){
430  // Our loops go over the bins in the order they are internally in
431  // fHist, and we do overflows, so we keep up exactly. If you get
432  // paranoid, reenable this briefly.
433 
434  // assert(bin == fHist->GetBin(x, y));
435 
436  histArr[bin] *= corrArr[x];
437  ++bin;
438  }
439  }
440 
441  TH1D* todel = hcorr.release();
442  HistCache::Delete(todel);
443  }
444 
445  //----------------------------------------------------------------------
447  {
448  fHist->Reset();
449  }
450 
451  //----------------------------------------------------------------------
453  { fLoaderCount.erase(p); }
454 
455  //----------------------------------------------------------------------
457  { fLoaderCount.insert(p); }
458 
459  //----------------------------------------------------------------------
460  void ReweightableSpectrum::SaveTo(TDirectory* dir) const
461  {
462  TDirectory* tmp = gDirectory;
463  dir->cd();
464 
465  TObjString("ReweightableSpectrum").Write("type");
466 
467  fHist->GetYaxis()->SetTitle(fTrueLabel.c_str());
468  fHist->Write("hist");
469  TH1D hPot("", "", 1, 0, 1);
470  hPot.Fill(.5, fPOT);
471  hPot.Write("pot");
472  TH1D hLivetime("", "", 1, 0, 1);
473  hLivetime.Fill(.5, fLivetime);
474  hLivetime.Write("livetime");
475 
476  for(unsigned int i = 0; i < fBins.size(); ++i){
477  TObjString(fLabels[i].c_str()).Write(TString::Format("label%d", i).Data());
478  fBins[i].SaveTo(dir->mkdir(TString::Format("bins%d", i)));
479  }
480 
481  tmp->cd();
482  }
483 
484  //----------------------------------------------------------------------
485  std::unique_ptr<ReweightableSpectrum> ReweightableSpectrum::LoadFrom(TDirectory* dir)
486  {
487  TObjString* tag = (TObjString*)dir->Get("type");
488  assert(tag);
489  assert(tag->GetString() == "ReweightableSpectrum");
490 
491  TH2D* spect = (TH2D*)dir->Get("hist");
492  assert(spect);
493  TH1* hPot = (TH1*)dir->Get("pot");
494  assert(hPot);
495  TH1* hLivetime = (TH1*)dir->Get("livetime");
496  assert(hLivetime);
497 
498  std::vector<std::string> labels;
499  std::vector<Binning> bins;
500 
501  for(int i = 0; ; ++i){
502  TDirectory* subdir = dir->GetDirectory(TString::Format("bins%d", i));
503  if(!subdir) break;
504  bins.push_back(*Binning::LoadFrom(subdir));
505  TObjString* label = (TObjString*)dir->Get(TString::Format("label%d", i));
506  labels.push_back(label ? label->GetString().Data() : "");
507  }
508 
509  if(bins.empty() && labels.empty()){
510  // Must be an old file. Make an attempt at backwards compatibility.
511  bins.push_back(Binning::FromTAxis(spect->GetXaxis()));
512  labels.push_back(spect->GetXaxis()->GetTitle());
513  }
514 
515  return std::make_unique<ReweightableSpectrum>(kUnweighted,
516  spect,
517  labels, bins,
518  hPot->GetBinContent(1),
519  hLivetime->GetBinContent(1));
520  }
521 
522 }
process_name opflash particleana ie ie ie z
* labels
Represent the binning of a Spectrum&#39;s x-axis.
Definition: Binning.h:18
TH1D * ToTH1(Color_t col=kBlack, Style_t style=kSolid) const
Definition: Ratio.cxx:116
process_name opflash particleana ie x
BEGIN_PROLOG could also be cerr
void Fill(double x, double y, double w=1)
tuple loader
Definition: demo.py:7
Simple record of shifts applied to systematic parameters.
Definition: SystShifts.h:16
static Binning FromTAxis(const TAxis *ax)
Definition: Binning.cxx:122
Var fRWVar
What goes on the y axis?
pdgs p
Definition: selectors.fcl:22
Spectrum with the value of a second variable, allowing for reweighting
void ReweightToRecoSpectrum(const Spectrum &target)
Recale bins so that Unweighted will return target.
process_name opflashCryoW ana
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
shift
Definition: fcl_checks.sh:26
void ProjectionY(TH2D *from, TH1D *to)
Helper for WeightingVariable.
Representation of a spectrum in any variable, with associated POT.
Definition: Spectrum.h:30
void RemoveLoader(SpectrumLoaderBase *)
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
bool IsSimple() const
Definition: Binning.h:31
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
while getopts h
std::vector< Binning > GetBinnings() const
Definition: HistAxis.h:49
process_name opflash particleana ie ie y
double Min() const
Definition: Binning.h:28
unsigned int NDimensions() const
Definition: HistAxis.h:46
virtual void AddReweightableSpectrum(ReweightableSpectrum &spect, const Var &var, const Cut &cut, const SystShifts &shift, const Var &wei)
For use by the constructors of ReweightableSpectrum subclasses.
static void Delete(TH1D *&h)
Definition: HistCache.cxx:92
std::vector< std::string > GetLabels() const
Definition: HistAxis.h:48
void SaveTo(TDirectory *dir) const
std::set< SpectrumLoaderBase * > fLoaderCount
This count is maintained by SpectrumLoader, as a sanity check.
const SpillCut kNoSpillCut([](const caf::SRSpillProxy *){return true;})
The simplest possible cut: pass everything, used as a default.
std::vector< std::string > fLabels
void ProjectionX(TH2D *from, TH1D *to)
Helper for Unweighted.
fBins({binsX, binsY})
Represent the ratio between two spectra.
Definition: Ratio.h:8
const std::vector< double > & Edges() const
Definition: Binning.h:32
tuple dir
Definition: dropbox.py:28
Base class for the various types of spectrum loader.
T GetMultiDVar() const
Definition: HistAxis.cxx:66
double Max() const
Definition: Binning.h:29
ReweightableSpectrum & operator=(const ReweightableSpectrum &rhs)
const Var kUnweighted([](const caf::SRSliceProxy *){return 1;})
The simplest possible Var, always 1. Used as a default weight.
int NBins() const
Definition: Binning.h:27
Spectrum WeightedBy(const TH1 *weights) const
static std::unique_ptr< ReweightableSpectrum > LoadFrom(TDirectory *dir)
static TH1D * New(const std::string &title, const Binning &bins)
Definition: HistCache.cxx:21
std::vector< Binning > fBins
then echo fcl name
void ReweightToTrueSpectrum(const Spectrum &target)
Rescale bins so that WeightingVariable will return target.
ReweightableSpectrum(SpectrumLoaderBase &loader, const HistAxis &recoAxis, const HistAxis &trueAxis, const Cut &cut, const SystShifts &shift=kNoShift, const Var &wei=kUnweighted)
Prevent histograms being added to the current directory.
void AddLoader(SpectrumLoaderBase *)
static Binning Simple(int n, double lo, double hi, const std::vector< std::string > &labels={})
Definition: Binning.cxx:38
static std::unique_ptr< Binning > LoadFrom(TDirectory *dir)
Definition: Binning.cxx:229
std::string UniqueName()
Return a different string each time, for creating histograms.
TH2D * ToTH2(double pot) const