laura is hosted by Hepforge, IPPP Durham
Laura++  v1r0
A maximum likelihood fitting package for performing Dalitz-plot analysis.
Lau2DHistDPPdf.cc
Go to the documentation of this file.
1 
2 // Copyright University of Warwick 2004 - 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 // Authors:
7 // Thomas Latham
8 // John Back
9 // Paul Harrison
10 
15 #include <iostream>
16 
17 #include "TAxis.h"
18 #include "TH2.h"
19 #include "TRandom.h"
20 
21 #include "Lau2DHistDPPdf.hh"
22 #include "LauKinematics.hh"
23 #include "LauRandom.hh"
24 #include "LauVetoes.hh"
25 
26 ClassImp(Lau2DHistDPPdf)
27 
28 
29 Lau2DHistDPPdf::Lau2DHistDPPdf(const TH2* hist, LauKinematics* kinematics, const LauVetoes* vetoes,
30  Bool_t useInterpolation, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) :
31  hist_(hist ? dynamic_cast<TH2*>(hist->Clone()) : 0),
32  kinematics_(kinematics),
33  vetoes_(vetoes),
34  minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0),
35  binXWidth_(0.0), binYWidth_(0.0),
36  invBinXWidth_(0.0), invBinYWidth_(0.0),
37  maxHeight_(0.0),
38  nBinsX_(0), nBinsY_(0),
39  norm_(0.0),
40  useInterpolation_(useInterpolation),
41  upperHalf_(useUpperHalfOnly),
42  squareDP_(squareDP)
43 {
44  // For square Dalitz plots, the co-ordinates must be m', theta'
45  // The input data to the fit is still in m13^2, m23^2 co-ords, and a
46  // transformation is applied to go from one co-ordinate system to the
47  // other.
48 
49  // Save various attributes of the histogram
50  // (axis ranges, number of bins, areas)
51  if ( hist_ ) {
52  TAxis* xAxis = hist_->GetXaxis();
53  minX_ = xAxis->GetXmin();
54  maxX_ = xAxis->GetXmax();
55 
56  TAxis* yAxis = hist_->GetYaxis();
57  minY_ = yAxis->GetXmin();
58  maxY_ = yAxis->GetXmax();
59 
60  nBinsX_ = hist_->GetNbinsX();
61  nBinsY_ = hist_->GetNbinsY();
62  } else {
63  minX_ = kinematics_->getm13SqMin();
64  maxX_ = kinematics_->getm13SqMax();
65 
66  minY_ = kinematics_->getm23SqMin();
67  maxY_ = kinematics_->getm23SqMax();
68 
69  nBinsX_ = 1;
70  nBinsY_ = 1;
71  }
72 
73  rangeX_ = maxX_ - minX_;
74  rangeY_ = maxY_ - minY_;
75  if (nBinsX_ > 0) { binXWidth_ = TMath::Abs(rangeX_)/(nBinsX_*1.0); }
76  if (nBinsY_ > 0) { binYWidth_ = TMath::Abs(rangeY_)/(nBinsY_*1.0); }
77  if (binXWidth_ > 1e-10) { invBinXWidth_ = 1.0/binXWidth_; }
78  if (binYWidth_ > 1e-10) { invBinYWidth_ = 1.0/binYWidth_; }
79 
80  // If the bins are to be fluctuated then do so now before
81  // calculating anything that depends on the bin content.
82  if (fluctuateBins) {
83  this->doBinFluctuation();
84  }
85 
86  // Calculate the PDF normalisation.
87  this->calcHistNorm();
88 
89  // And check it is OK.
90  this->checkNormalisation();
91 
92  // Also obtain the maximum height
93  this->calcMaxHeight();
94 }
95 
97 {
98  // Destructor
99  delete hist_; hist_ = 0;
100 }
101 
103 {
104  // Get the maximum height of the 2D histogram
105  maxHeight_ = 0.0;
106  if ( hist_ ) {
107  Int_t maxBin = hist_->GetMaximumBin();
108  maxHeight_ = hist_->GetBinContent(maxBin);
109  }
110 
111  std::cout << "INFO in Lau2DHistDPPdf::calcMaxHeight : Max height = " << maxHeight_ << std::endl;
112 }
113 
115 {
116  // Calculate the histogram normalisation. We must integrate
117  // over the allowed kinematic DP region.
118 
119  // Loop over the total x and y range to get the total area
120  // under x and y. Just sum the contributions up using 1e-3 increments
121  // of the range in x and y. Multiply the end result by dx and dy.
122 
123  const Double_t axisMin = TMath::Min( minX_, minY_ );
124  const Double_t axisMax = TMath::Max( maxX_, maxY_ );
125  const Double_t axisRange = axisMax - axisMin;
126 
127  const Double_t dx(1e-3 * axisRange);
128  const Double_t dy(dx);
129 
130  Double_t area(0.0);
131 
132  Double_t x(axisMin + dx/2.0);
133  while (x < axisMax) {
134  Double_t y(axisMin + dy/2.0);
135  while (y < axisMax) {
136  area += this->interpolateXY(x,y);
137  y += dy;
138  } // y while loop
139  x += dx;
140  } // x while loop
141 
142  norm_ = area*dx*dy;
143 
144  std::cout << "INFO in Lau2DHistDPPdf::calcHistNorm : Norm = " << norm_ << ", bX*bY = " << binXWidth_ << "*" << binYWidth_ << " = " << binXWidth_*binYWidth_ << std::endl;
145 }
146 
147 Double_t Lau2DHistDPPdf::getBinHistValue(Int_t xBinNo, Int_t yBinNo) const
148 {
149  if (xBinNo < 0) {
150  xBinNo = 0;
151  } else if (xBinNo >= nBinsX_) {
152  return 0.0;
153  }
154 
155  if (yBinNo < 0) {
156  yBinNo = 0;
157  } else if (yBinNo >= nBinsY_) {
158  return 0.0;
159  }
160 
161  Double_t value = hist_->GetBinContent(xBinNo+1, yBinNo+1);
162  return value;
163 }
164 
165 Double_t Lau2DHistDPPdf::interpolateXYNorm(Double_t x, Double_t y) const
166 {
167  // Get the normalised interpolated value.
168  Double_t value = this->interpolateXY(x,y);
169  return value/norm_;
170 
171 }
172 
173 Double_t Lau2DHistDPPdf::interpolateXY(Double_t x, Double_t y) const
174 {
175  // This function returns the interpolated value of the histogram function
176  // for the given values of x and y by finding the adjacent bins and extrapolating
177  // using weights based on the inverse distance of the point from the adajcent
178  // bin centres.
179  // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates
180 
181  // If we're only using one half then flip co-ordinates
182  // appropriately for conventional or square DP
183  if ( upperHalf_ == kTRUE ) {
184  if ( squareDP_ == kFALSE && x > y ) {
185  Double_t temp = y;
186  y = x;
187  x = temp;
188  } else if ( squareDP_ == kTRUE && y > 0.5 ) {
189  y = 1.0 - y;
190  }
191  }
192 
193  // First ask whether the point is inside the kinematic region.
194  Bool_t withinDP(kFALSE);
195  if (squareDP_ == kTRUE) {
196  withinDP = kinematics_->withinSqDPLimits(x,y);
197  } else {
198  withinDP = kinematics_->withinDPLimits(x,y);
199  }
200  if (withinDP == kFALSE) {return 0.0;}
201 
202  // Update the kinematics to the position of interest.
203  if (squareDP_ == kTRUE) {
205  } else {
207  }
208 
209  // Check that we're not inside a veto
210  Bool_t vetoOK(kTRUE);
211  if (vetoes_) {
212  vetoOK = vetoes_->passVeto(kinematics_);
213  }
214  if (vetoOK == kFALSE) {return 0.0;}
215 
216  // Find the 2D histogram bin for x and y
217  Int_t i = TMath::FloorNint((x - minX_)*invBinXWidth_);
218  Int_t j = TMath::FloorNint((y - minY_)*invBinYWidth_);
219 
220  if (i >= nBinsX_) {i = nBinsX_ - 1;}
221  if (j >= nBinsY_) {j = nBinsY_ - 1;}
222 
223  // Ask whether we want to do the interpolation, since this method is
224  // not reliable for low statistics histograms.
225  if (useInterpolation_ == kFALSE) {
226  return this->getBinHistValue(i,j);
227  }
228 
229  // Find the bin centres (actual co-ordinate positions, not histogram indices)
230  Double_t cbinx = (i+0.5)*binXWidth_ + minX_;
231  Double_t cbiny = (j+0.5)*binYWidth_ + minY_;
232 
233  // If bin centres are outside kinematic region, do not extrapolate
234  if (squareDP_ == kTRUE) {
235  withinDP = kinematics_->withinSqDPLimits(cbinx, cbiny);
236  } else {
237  withinDP = kinematics_->withinDPLimits(cbinx, cbiny);
238  }
239  if (withinDP == kFALSE) {
240  return this->getBinHistValue(i,j);
241  }
242 
243  // Find the adjacent bins
244  Double_t deltax = x - cbinx;
245  Double_t deltay = y - cbiny;
246 
247  Int_t i_adj(0), j_adj(0);
248  if (deltax > 0.0) {
249  i_adj = i + 1;
250  } else {
251  i_adj = i - 1;
252  }
253  if (deltay > 0.0) {
254  j_adj = j + 1;
255  } else {
256  j_adj = j - 1;
257  }
258 
259  Bool_t isXBoundary(kFALSE), isYBoundary(kFALSE);
260 
261  Double_t value(0.0);
262 
263  if (i_adj >= nBinsX_ || i_adj < 0) {isYBoundary = kTRUE;}
264  if (j_adj >= nBinsY_ || j_adj < 0) {isXBoundary = kTRUE;}
265 
266  // In the corners, do no interpolation. Use entry in bin (i,j)
267  if (isXBoundary == kTRUE && isYBoundary == kTRUE) {
268 
269  value = this->getBinHistValue(i,j);
270 
271  } else if (isXBoundary == kTRUE && isYBoundary == kFALSE) {
272 
273  // Find the adjacent x bin centre
274  Double_t cbinx_adj = Double_t(i_adj+0.5)*binXWidth_ + minX_;
275 
276  if (squareDP_ == kTRUE) {
277  withinDP = kinematics_->withinSqDPLimits(cbinx_adj, y);
278  } else {
279  withinDP = kinematics_->withinDPLimits(cbinx_adj, y);
280  }
281 
282  if (withinDP == kFALSE) {
283 
284  // The adjacent bin is outside the DP range. Don't extrapolate.
285  value = this->getBinHistValue(i,j);
286 
287  } else {
288 
289  Double_t dx0 = TMath::Abs(x - cbinx);
290  Double_t dx1 = TMath::Abs(cbinx_adj - x);
291  Double_t inter_denom = dx0 + dx1;
292 
293  Double_t value1 = this->getBinHistValue(i,j);
294  Double_t value2 = this->getBinHistValue(i_adj,j);
295 
296  value = (value1*dx1 + value2*dx0)/inter_denom;
297 
298  }
299 
300  } else if (isYBoundary == kTRUE && isXBoundary == kFALSE) {
301 
302  // Find the adjacent y bin centre
303  Double_t cbiny_adj = Double_t(j_adj+0.5)*binYWidth_ + minY_;
304 
305  if (squareDP_ == kTRUE) {
306  withinDP = kinematics_->withinSqDPLimits(x, cbiny_adj);
307  } else {
308  withinDP = kinematics_->withinDPLimits(x, cbiny_adj);
309  }
310 
311  if (withinDP == kFALSE) {
312 
313  // The adjacent bin is outside the DP range. Don't extrapolate.
314  value = this->getBinHistValue(i,j);
315 
316  } else {
317 
318  Double_t dy0 = TMath::Abs(y - cbiny);
319  Double_t dy1 = TMath::Abs(cbiny_adj - y);
320  Double_t inter_denom = dy0 + dy1;
321 
322  Double_t value1 = this->getBinHistValue(i,j);
323  Double_t value2 = this->getBinHistValue(i,j_adj);
324 
325  value = (value1*dy1 + value2*dy0)/inter_denom;
326 
327  }
328 
329  } else {
330 
331  // 2D linear interpolation using inverse distance as weights.
332  // Find the adjacent x and y bin centres
333  Double_t cbinx_adj = Double_t(i_adj+0.5)*binXWidth_ + minX_;
334  Double_t cbiny_adj = Double_t(j_adj+0.5)*binYWidth_ + minY_;
335 
336  if (squareDP_ == kTRUE) {
337  withinDP = kinematics_->withinSqDPLimits(cbinx_adj, cbiny_adj);
338  } else {
339  withinDP = kinematics_->withinDPLimits(cbinx_adj, cbiny_adj);
340  }
341 
342  if (withinDP == kFALSE) {
343 
344  // The adjacent bin is outside the DP range. Don't extrapolate.
345  value = this->getBinHistValue(i,j);
346 
347  } else {
348 
349  Double_t dx0 = TMath::Abs(x - cbinx);
350  Double_t dx1 = TMath::Abs(cbinx_adj - x);
351  Double_t dy0 = TMath::Abs(y - cbiny);
352  Double_t dy1 = TMath::Abs(cbiny_adj - y);
353 
354  Double_t inter_denom = (dx0 + dx1)*(dy0 + dy1);
355 
356  Double_t value1 = this->getBinHistValue(i,j);
357  Double_t value2 = this->getBinHistValue(i_adj,j);
358  Double_t value3 = this->getBinHistValue(i,j_adj);
359  Double_t value4 = this->getBinHistValue(i_adj,j_adj);
360 
361  value = value1*dx1*dy1 + value2*dx0*dy1 + value3*dx1*dy0 + value4*dx0*dy0;
362  value /= inter_denom;
363  }
364 
365  }
366 
367  return value;
368 
369 }
370 
372 {
373  // Loop over the total x and y range to get the total area
374  // under x and y. Just sum the contributions up using 1e-3 increments
375  // of the range in x and y. Multiply the end result by dx and dy.
376 
377  const Double_t axisMin = TMath::Min( minX_, minY_ );
378  const Double_t axisMax = TMath::Max( maxX_, maxY_ );
379  const Double_t axisRange = axisMax - axisMin;
380 
381  const Double_t dx(1e-3 * axisRange);
382  const Double_t dy(dx);
383 
384  Double_t area(0.0);
385  Double_t areaNoNorm(0.0);
386 
387  // Preserve the value of a variable we change temporarily
388  Bool_t interpolate = useInterpolation_;
389 
390  Double_t x(axisMin + dx/2.0);
391  while (x < axisMax) {
392  Double_t y(axisMin + dy/2.0);
393  while (y < axisMax) {
394  area += this->interpolateXYNorm(x,y);
395  useInterpolation_ = kFALSE;
396  areaNoNorm += this->interpolateXY(x,y);
397  useInterpolation_ = kTRUE;
398  y += dy;
399  } // y while loop
400  x += dx;
401  } // x while loop
402  Double_t norm = area*dx*dy;
403 
404  useInterpolation_ = interpolate; //Restore old value
405 
406  std::cout << "INFO in Lau2DHistDPPdf::checkNormalisation : Area = " << area << ", dx = " << dx << ", dy = " << dy << ", dx*dy = " << dx*dy << std::endl;
407  std::cout << " : Area with no norm = " << areaNoNorm << "*dx*dy = " << areaNoNorm*dx*dy << std::endl;
408  std::cout << " : The total area of the normalised histogram PDF is " << norm << std::endl;
409 }
410 
412 {
413  if ( !hist_ ) {
414  return;
415  }
416 
417  TRandom* random = LauRandom::zeroSeedRandom();
418  for (Int_t i(0); i<nBinsX_; i++) {
419  for (Int_t j(0); j<nBinsY_; j++) {
420  Double_t currentContent = hist_->GetBinContent(i+1,j+1);
421  Double_t currentError = hist_->GetBinError(i+1,j+1);
422  Double_t newContent = random->Gaus(currentContent,currentError);
423  if (newContent<0.0) {
424  hist_->SetBinContent(i+1,j+1,0.0);
425  } else {
426  hist_->SetBinContent(i+1,j+1,newContent);
427  }
428  }
429  }
430 }
431 
Double_t minY_
The histogram y-axis minimum.
Double_t maxHeight_
The maximum height of 2D histogram.
TRandom * zeroSeedRandom()
Access the singleton random number generator with seed set from machine clock time (within +-1 sec)...
Definition: LauRandom.cc:30
const LauVetoes * vetoes_
Vetos within DP.
Double_t norm_
The histogram normalisation.
void updateSqDPKinematics(Double_t mPrime, Double_t thetaPrime)
Update all kinematic quantities based on the square DP co-ordinates m&#39; and theta&#39;.
Double_t invBinYWidth_
The histogram y-axis inverse bin width.
Bool_t upperHalf_
Boolean for using the upper half of DP.
Double_t maxX_
The histogram x-axis maximum.
Double_t interpolateXYNorm(Double_t x, Double_t y) const
Perform the interpolation and divide by the normalisation.
Class for defining a 2D DP histogram PDF.
Int_t nBinsX_
The number of bins on the x-axis of the histogram.
File containing declaration of Lau2DHistDPPdf class.
Double_t binXWidth_
The histogram x-axis bin width.
File containing declaration of LauKinematics class.
TH2 * hist_
The underlying histogram.
void updateKinematics(Double_t m13Sq, Double_t m23Sq)
Update all kinematic quantities based on the DP co-ordinates m13Sq and m23Sq.
void checkNormalisation()
Check the normalisation calculation.
Double_t minX_
The histogram x-axis minimum.
Bool_t withinSqDPLimits(Double_t mPrime, Double_t thetaPrime) const
Check whether a given (m&#39;,theta&#39;) point is within the kinematic limits of the Dalitz plot...
Bool_t withinDPLimits(Double_t m13Sq, Double_t m23Sq) const
Check whether a given (m13Sq,m23Sq) point is within the kinematic limits of the Dalitz plot...
virtual ~Lau2DHistDPPdf()
Destructor.
Bool_t useInterpolation_
Control boolean for using the linear interpolation.
File containing LauRandom namespace.
Double_t invBinXWidth_
The histogram x-axis inverse bin width.
Bool_t passVeto(Double_t &m12Sq, Double_t &m23Sq, Double_t &m13Sq) const
Check whether the specified Dalitz plot point passes the vetoes.
Definition: LauVetoes.cc:109
void doBinFluctuation()
Fluctuate the histogram bin contents in accordance with their errors.
Double_t getBinHistValue(Int_t xBinNo, Int_t yBinNo) const
Get the bin content from the histogram.
Class for calculating 3-body kinematic quantities.
Double_t value() const
The value of the parameter.
File containing declaration of LauVetoes class.
Bool_t squareDP_
Boolean for using square DP variables.
Double_t maxY_
The histogram y-axis maximum.
void calcHistNorm()
Calculate the PDF normalisation.
Double_t binYWidth_
The histogram y-axis bin width.
Int_t nBinsY_
The number of bins on the y-axis of the histogram.
Double_t interpolateXY(Double_t x, Double_t y) const
Perform the interpolation (unnormalised)
Class for defining vetoes within the Dalitz plot.
Definition: LauVetoes.hh:33
LauKinematics * kinematics_
DP kinematics.
void calcMaxHeight()
Calculate maximum height.