meerkat is hosted by Hepforge, IPPP Durham
Meerkat  v1r3
Multidimensional kernel density estimation package
AbsDensity.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <vector>
3 
4 #include "TMath.h"
5 #include "TH1F.h"
6 #include "TH2F.h"
7 #include "TNtuple.h"
8 
9 #include "AbsPhaseSpace.hh"
10 #include "AbsDensity.hh"
11 
12 #include "Logger.hh"
13 
14 AbsDensity::AbsDensity(const char* pdfName) {
15  m_maxTries = 100000;
16  m_majorant = 0. ;
17  strncpy(m_name, pdfName, 255);
18  m_name[255] = 0;
19 }
20 
22 
23 }
24 
25 void AbsDensity::slice(std::vector<Double_t> &x, UInt_t num, TH1F* hist) {
26 
27  std::vector<Double_t> point = x;
28 
29  UInt_t bins = hist->GetNbinsX();
30 
31  Logger::print(0, "%20.20s INFO: filling 1D slice in variable %d, hist \"%s\" (%d bins)\n",
32  m_name, num, hist->GetName(), bins );
33 
34  UInt_t i;
36  for (i=1; i<=bins; i++) {
37  if (Logger::timer(1)) Logger::print(0, "%20.20s INFO: filling bin %d\n", m_name, i);
38  Double_t xi = hist->GetBinCenter(i);
39  point[num] = xi;
40  Double_t d = 0;
41  if (phaseSpace()->withinLimits(point))
42  d = density(point);
43  if (d<0) d = 0;
44  hist->SetBinContent(i, d);
45  }
46 }
47 
48 void AbsDensity::slice(std::vector<Double_t> &x, UInt_t numx, UInt_t numy, TH2F* hist, Bool_t inPhaseSpace) {
49 
50  std::vector<Double_t> point = x;
51 
52  UInt_t xbins = hist->GetNbinsX();
53  UInt_t ybins = hist->GetNbinsY();
54 
55  Logger::print(0, "%20.20s INFO: filling 2D slice in variables %d and %d, hist \"%s\" (%dx%d bins)\n",
56  m_name, numx, numy, hist->GetName(), xbins, ybins );
57 
58  UInt_t ix, iy;
60  for (ix=1; ix<=xbins; ix++) {
61  if (Logger::timer(1)) Logger::print(0, "%20.20s INFO: filling row %d\n", m_name, ix);
62  for (iy=1; iy<=ybins; iy++) {
63  Double_t xi = hist->GetXaxis()->GetBinCenter(ix);
64  Double_t yi = hist->GetYaxis()->GetBinCenter(iy);
65  point[numx] = xi;
66  point[numy] = yi;
67  Double_t d = 0;
68  if (!inPhaseSpace || phaseSpace()->withinLimits(point))
69  d = density(point);
70  if (d<0) d = 0;
71  hist->SetBinContent(ix, iy, d);
72  }
73  }
74 }
75 
76 void AbsDensity::project(TH1F* hist) {
77  if (phaseSpace()->dimensionality() != 1) {
78  Logger::print(2, "%20.20s ERROR: Projection of %dD density to 1D histogram is not supported\n", m_name,
79  phaseSpace()->dimensionality());
80  abort();
81  }
82  std::vector<Double_t> x(1);
83  x[0] = 0;
84  slice(x, 0, hist);
85 }
86 
87 void AbsDensity::project(TH2F* hist, Bool_t inPhaseSpace) {
88  if (phaseSpace()->dimensionality() != 2) {
89  Logger::print(0, "%20.20s ERROR: Projection of %dD density to 2D histogram is not supported\n", m_name,
90  phaseSpace()->dimensionality());
91  abort();
92  }
93  std::vector<Double_t> x(2);
94  x[0] = 0;
95  x[1] = 0;
96  slice(x, 0, 1, hist, inPhaseSpace);
97 }
98 
99 Double_t AbsDensity::generate(std::vector<Double_t> &x) {
100 
101  Bool_t success = 0;
102  Double_t d = 0;
103 
104  UInt_t dimensionality = phaseSpace()->dimensionality();
105  UInt_t t;
106 
107  Bool_t estimateMajorant = (m_majorant <= 0);
108  if (estimateMajorant) {
109  Logger::print(0, "%20.20s INFO: Generating toy MC distribution\n", m_name);
110  Logger::print(0, "%20.20s INFO: Majorant will be estimated with %d tries\n", m_name, m_maxTries);
111  }
112 
113  for (t = 0; t < m_maxTries; t++) {
114 
115  // Generate random point
116  UInt_t var;
117  for (var = 0; var < dimensionality; var++) {
118  Double_t lowerLimit = phaseSpace()->lowerLimit(var);
119  Double_t upperLimit = phaseSpace()->upperLimit(var);
120  x[var] = lowerLimit + m_rnd.Rndm()*(upperLimit-lowerLimit);
121  }
122 
123  Bool_t inPhsp = phaseSpace()->withinLimits(x);
124  if (inPhsp) {
125  Double_t y = m_majorant*m_rnd.Rndm();
126  d = density(x);
127  if (d > m_majorant) {
128  if (!estimateMajorant)
129  Logger::print(0, "%20.20s WARNING: Updating majorant: %f -> %f\n", m_name, m_majorant, 1.1*d);
130  m_majorant = 1.1*d;
131  }
132  if (d > y) {
133  success = 1;
134  if (!estimateMajorant) break;
135  }
136  }
137  }
138  if (!success) {
139  Logger::print(1, "%20.20s WARNING: failed to generate a point within phase space after %d tries\n", m_name, m_maxTries);
140  return 0;
141  }
142 
143  if (estimateMajorant) {
144  Logger::print(0, "%20.20s INFO: Estimated majorant = %f\n", m_name, m_majorant);
145  }
146 
147  return d;
148 }
149 
150 void AbsDensity::generate(TNtuple* tree, UInt_t numEvents) {
151 
152  Float_t array[11];
153  UInt_t dimensionality = phaseSpace()->dimensionality();
154 
155  if (dimensionality > 10) {
156  Logger::print(2, "%20.20s ERROR: Generation is not supported for more than 10 dimensions\n", m_name);
157  abort();
158  }
159 
160  std::vector<Double_t> x(dimensionality);
161  UInt_t i;
162  Logger::setTimer();
163  for (i=0; i<numEvents; i++) {
164  Double_t eff = generate(x);
165 
166  UInt_t n;
167  for (n=0; n<dimensionality; n++) array[n] = x[n];
168  array[dimensionality] = eff;
169 
170  tree->Fill(array);
171 
172  if (i % 100 == 0 && Logger::timer(2)) Logger::print(0, "%20.20s INFO: Ntuple event %d/%d (%f%%)\n",
173  m_name, i, numEvents, 100.*(Double_t)i/(Double_t)numEvents);
174  }
175  tree->Write();
176 
177 }
178 
179 double AbsDensity::transform(TH1F* hist1, TH1F* hist2, double x) {
180 
181  int i;
182  int nbins = hist1->GetNbinsX();
183  if (hist2->GetNbinsX() != nbins) {
184  Logger::print(2, "%20.20s ERROR: In transform - numbers of bins in two histograms do not match\n", m_name);
185  abort();
186  }
187 
188  TAxis* xaxis = hist1->GetXaxis();
189 
190  double xmin = xaxis->GetXmin();
191  double xmax = xaxis->GetXmax();
192 
193  if (x <= xmin) return xmin;
194  if (x >= xmax) return xmax;
195 
196  double sum1 = 0;
197  double sum2 = 0;
198  double partsum1 = 0.;
199  double xb = xmin;
200  int xbin = 1;
201  for (i=1; i<=nbins; i++) {
202  xb = xaxis->GetBinUpEdge(i);
203  double h1 = hist1->GetBinContent(i);
204  double h2 = hist2->GetBinContent(i);
205  sum1 += h1;
206  sum2 += h2;
207  if (xb < x) {
208  partsum1 += h1;
209  xbin = i+1;
210  }
211  }
212 
213  if (sum1 == 0 || sum2 == 0) return x; // No correction is the histogram is empty
214 
215  double frac0 = partsum1/sum1;
216 
217 // int xbin = xaxis->FindBin(x);
218 // double frac0 = intarr1[xbin-1];
219  double dfrac = (x-xaxis->GetBinLowEdge(xbin))/xaxis->GetBinWidth(xbin)*hist1->GetBinContent(xbin)/sum1;
220 
221 // int ibin2 = TMath::BinarySearch(nbins,intarr2,frac);
222 
223 // int xbin = xaxis->FindBin(x);
224 
225 // double frac = (hist1->Integral(1, xbin-1) + hist1->GetBinContent(xbin)*(x-xaxis->GetBinLowEdge(xbin)/xaxis->GetBinWidth(xbin)))/integ1;
226 
227 // double frac0 = hist1->Integral(1, xbin-1)/integ1;
228 // double dfrac = hist1->GetBinContent(xbin)*(x-xaxis->GetBinLowEdge(xbin)/xaxis->GetBinWidth(xbin))/integ1;
229 
230  double frac = frac0 + dfrac;
231 
232  double partsum2 = 0;
233  for (i=1; i<=nbins; i++) {
234  double h2 = hist2->GetBinContent(i);
235  if ( (partsum2 + h2)/sum2 > frac) break;
236  partsum2 += h2;
237  }
238 
239 // double x2 = xaxis->GetBinLowEdge(i) + xaxis->GetBinWidth(i)*(frac - sum/integ2)/hist2->GetBinContent(i);
240  double x20 = xaxis->GetBinLowEdge(i);
241  if (hist2->GetBinContent(i) == 0) return x;
242  double dx2 = xaxis->GetBinWidth(i)*(frac*sum2 - partsum2)/hist2->GetBinContent(i);
243 
244  double x2 = x20 + dx2;
245 
246  if ( !(x2<0) && !(x2>=0.) ) // If nan
247  Logger::print(0, "x=%f, int1=%f, int2=%f, xbin=%d, xbin2=%d, dx/w=%f, h1=%f, frac0=%f, dfrac=%f, frac=%f, sum=%f, x20=%f, dx2=%f, x2=%f\n",
248  x, sum1, sum2, xbin, i, (x-xaxis->GetBinLowEdge(xbin))/xaxis->GetBinWidth(xbin), hist1->GetBinContent(xbin), frac0, dfrac, frac, partsum2, x20, dx2, x2);
249 
250  return x2;
251 
252 }
void project(TH1F *hist)
Calculate projection of the 1D PDF.
Definition: AbsDensity.cpp:76
double transform(TH1F *hist1, TH1F *hist2, double x)
Definition: AbsDensity.cpp:179
virtual Double_t upperLimit(UInt_t var)=0
Return upper allowed limit of the variable.
virtual AbsPhaseSpace * phaseSpace()=0
Return phase space definition for this PDF.
virtual ~AbsDensity()
Destructor.
Definition: AbsDensity.cpp:21
void print(int level, const char *format,...)
Definition: Logger.cpp:27
char m_name[256]
PDF name.
Definition: AbsDensity.hh:118
TRandom3 m_rnd
Random number generator.
Definition: AbsDensity.hh:127
virtual UInt_t dimensionality()=0
Get dimensionality of phase space.
UInt_t m_maxTries
Maximum number of tries for accept-reject method.
Definition: AbsDensity.hh:124
AbsDensity(const char *pdfName)
Constructor.
Definition: AbsDensity.cpp:14
void setTimer(void)
Reset time counter.
Definition: Logger.cpp:9
virtual Double_t lowerLimit(UInt_t var)=0
Return lower allowed limit of the variable.
int timer(int secs)
Return 1 if more than a certain number of seconds have passed since the last call of this function or...
Definition: Logger.cpp:13
Double_t generate(std::vector< Double_t > &x)
Generate a single point within the phase space according to the PDF using accept-reject method...
Definition: AbsDensity.cpp:99
virtual Bool_t withinLimits(std::vector< Double_t > &x)=0
Check if the point is within phase space limits.
virtual Double_t density(std::vector< Double_t > &x)=0
Calculate PDF value at the given point.
Double_t m_majorant
PDF majorant (maximum PDF value needed for accept-reject).
Definition: AbsDensity.hh:121
void slice(std::vector< Double_t > &x, UInt_t num, TH1F *hist)
Calculate 1D slice of the PDF.
Definition: AbsDensity.cpp:25