laura is hosted by Hepforge, IPPP Durham
Laura++  v3r5
A maximum likelihood fitting package for performing Dalitz-plot analysis.
Lau2DHistDPPdf.cc
Go to the documentation of this file.
1 
2 /*
3 Copyright 2004 University of Warwick
4 
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 */
17 
18 /*
19 Laura++ package authors:
20 John Back
21 Paul Harrison
22 Thomas Latham
23 */
24 
29 #include <iostream>
30 
31 #include "TAxis.h"
32 #include "TH2.h"
33 #include "TRandom.h"
34 
35 #include "Lau2DHistDPPdf.hh"
36 #include "LauKinematics.hh"
37 #include "LauRandom.hh"
38 #include "LauVetoes.hh"
39 
41 
42 
43 Lau2DHistDPPdf::Lau2DHistDPPdf(const TH2* hist, LauKinematics* kinematics, const LauVetoes* vetoes,
44  Bool_t useInterpolation, Bool_t fluctuateBins, Bool_t useUpperHalfOnly, Bool_t squareDP) :
45  Lau2DAbsHistDPPdf(kinematics,vetoes,useUpperHalfOnly,squareDP),
46  hist_(hist ? dynamic_cast<TH2*>(hist->Clone()) : 0),
47  minX_(0.0), maxX_(0.0), minY_(0.0), maxY_(0.0), rangeX_(0.0), rangeY_(0.0),
48  binXWidth_(0.0), binYWidth_(0.0),
49  invBinXWidth_(0.0), invBinYWidth_(0.0),
50  nBinsX_(0), nBinsY_(0),
51  norm_(0.0),
52  useInterpolation_(useInterpolation)
53 {
54  // For square Dalitz plots, the co-ordinates must be m', theta'
55  // The input data to the fit is still in m13^2, m23^2 co-ords, and a
56  // transformation is applied to go from one co-ordinate system to the
57  // other.
58 
59  // Save various attributes of the histogram
60  // (axis ranges, number of bins, areas)
61  if ( hist_ ) {
62  TAxis* xAxis = hist_->GetXaxis();
63  minX_ = xAxis->GetXmin();
64  maxX_ = xAxis->GetXmax();
65 
66  TAxis* yAxis = hist_->GetYaxis();
67  minY_ = yAxis->GetXmin();
68  maxY_ = yAxis->GetXmax();
69 
70  nBinsX_ = hist_->GetNbinsX();
71  nBinsY_ = hist_->GetNbinsY();
72  } else {
73  minX_ = getKinematics()->getm13SqMin();
74  maxX_ = getKinematics()->getm13SqMax();
75 
76  minY_ = getKinematics()->getm23SqMin();
77  maxY_ = getKinematics()->getm23SqMax();
78 
79  nBinsX_ = 1;
80  nBinsY_ = 1;
81  }
82 
83  rangeX_ = maxX_ - minX_;
84  rangeY_ = maxY_ - minY_;
85  if (nBinsX_ > 0) { binXWidth_ = TMath::Abs(rangeX_)/(nBinsX_*1.0); }
86  if (nBinsY_ > 0) { binYWidth_ = TMath::Abs(rangeY_)/(nBinsY_*1.0); }
87  if (binXWidth_ > 1e-10) { invBinXWidth_ = 1.0/binXWidth_; }
88  if (binYWidth_ > 1e-10) { invBinYWidth_ = 1.0/binYWidth_; }
89 
90  // If the bins are to be fluctuated then do so now before
91  // calculating anything that depends on the bin content.
92  if (fluctuateBins) {
93  this->doBinFluctuation(hist_);
94  }
95 
96  // Calculate the PDF normalisation.
97  this->calcHistNorm();
98 
99  // And check it is OK.
100  this->checkNormalisation();
101 
102  // Also obtain the maximum height
103  this->calcMaxHeight(hist_);
104 }
105 
107 {
108  // Destructor
109  delete hist_; hist_ = 0;
110 }
111 
113 {
114  // Calculate the histogram normalisation. We must integrate
115  // over the allowed kinematic DP region.
116 
117  // Loop over the total x and y range to get the total area
118  // under x and y. Just sum the contributions up using 1e-3 increments
119  // of the range in x and y. Multiply the end result by dx and dy.
120 
121  const Double_t axisMin = TMath::Min( minX_, minY_ );
122  const Double_t axisMax = TMath::Max( maxX_, maxY_ );
123  const Double_t axisRange = axisMax - axisMin;
124 
125  const Double_t dx(1e-3 * axisRange);
126  const Double_t dy(dx);
127 
128  Double_t area(0.0);
129 
130  Double_t x(axisMin + dx/2.0);
131  while (x < axisMax) {
132  Double_t y(axisMin + dy/2.0);
133  while (y < axisMax) {
134  area += this->interpolateXY(x,y);
135  y += dy;
136  } // y while loop
137  x += dx;
138  } // x while loop
139 
140  norm_ = area*dx*dy;
141 
142  std::cout << "INFO in Lau2DHistDPPdf::calcHistNorm : Norm = " << norm_ << ", bX*bY = " << binXWidth_ << "*" << binYWidth_ << " = " << binXWidth_*binYWidth_ << std::endl;
143 }
144 
145 Double_t Lau2DHistDPPdf::getBinHistValue(Int_t xBinNo, Int_t yBinNo) const
146 {
147  if (xBinNo < 0) {
148  xBinNo = 0;
149  } else if (xBinNo >= nBinsX_) {
150  return 0.0;
151  }
152 
153  if (yBinNo < 0) {
154  yBinNo = 0;
155  } else if (yBinNo >= nBinsY_) {
156  return 0.0;
157  }
158 
159  if ( hist_ == 0 ) {
160  return 1.0;
161  }
162 
163  Double_t value = hist_->GetBinContent(xBinNo+1, yBinNo+1);
164  return value;
165 }
166 
167 Double_t Lau2DHistDPPdf::interpolateXYNorm(Double_t x, Double_t y) const
168 {
169  // Get the normalised interpolated value.
170  Double_t value = this->interpolateXY(x,y);
171  return value/norm_;
172 
173 }
174 
175 Double_t Lau2DHistDPPdf::interpolateXY(Double_t x, Double_t y) const
176 {
177  // This function returns the interpolated value of the histogram function
178  // for the given values of x and y by finding the adjacent bins and extrapolating
179  // using weights based on the inverse distance of the point from the adajcent
180  // bin centres.
181  // Here, x = m13^2, y = m23^2, or m', theta' for square DP co-ordinates
182 
183  // If we're only using one half then flip co-ordinates
184  // appropriately for conventional or square DP
185  getUpperHalf(x,y);
186 
187  // First ask whether the point is inside the kinematic region.
188  if (withinDPBoundaries(x,y) == kFALSE) {return 0.0;}
189 
190  // Update the kinematics to the position of interest.
191  updateKinematics(x,y);
192 
193  // Check that we're not inside a veto
194  Bool_t vetoOK(kTRUE);
195  if (getVetoes()) {
196  vetoOK = getVetoes()->passVeto(getKinematics());
197  }
198  if (vetoOK == kFALSE) {return 0.0;}
199 
200  // Find the 2D histogram bin for x and y
201  Int_t i = TMath::FloorNint((x - minX_)*invBinXWidth_);
202  Int_t j = TMath::FloorNint((y - minY_)*invBinYWidth_);
203 
204  if (i >= nBinsX_) {i = nBinsX_ - 1;}
205  if (j >= nBinsY_) {j = nBinsY_ - 1;}
206 
207  // Ask whether we want to do the interpolation, since this method is
208  // not reliable for low statistics histograms.
209  if (useInterpolation_ == kFALSE) {
210  return this->getBinHistValue(i,j);
211  }
212 
213  // Find the bin centres (actual co-ordinate positions, not histogram indices)
214  Double_t cbinx = (i+0.5)*binXWidth_ + minX_;
215  Double_t cbiny = (j+0.5)*binYWidth_ + minY_;
216 
217  // If bin centres are outside kinematic region, do not extrapolate
218  if (withinDPBoundaries(cbinx, cbiny) == kFALSE) {
219  return this->getBinHistValue(i,j);
220  }
221 
222  // Find the adjacent bins
223  Double_t deltax = x - cbinx;
224  Double_t deltay = y - cbiny;
225 
226  Int_t i_adj(0), j_adj(0);
227  if (deltax > 0.0) {
228  i_adj = i + 1;
229  } else {
230  i_adj = i - 1;
231  }
232  if (deltay > 0.0) {
233  j_adj = j + 1;
234  } else {
235  j_adj = j - 1;
236  }
237 
238  Bool_t isXBoundary(kFALSE), isYBoundary(kFALSE);
239 
240  Double_t value(0.0);
241 
242  if (i_adj >= nBinsX_ || i_adj < 0) {isYBoundary = kTRUE;}
243  if (j_adj >= nBinsY_ || j_adj < 0) {isXBoundary = kTRUE;}
244 
245  // In the corners, do no interpolation. Use entry in bin (i,j)
246  if (isXBoundary == kTRUE && isYBoundary == kTRUE) {
247 
248  value = this->getBinHistValue(i,j);
249 
250  } else if (isXBoundary == kTRUE && isYBoundary == kFALSE) {
251 
252  // Find the adjacent x bin centre
253  Double_t cbinx_adj = Double_t(i_adj+0.5)*binXWidth_ + minX_;
254 
255  if (withinDPBoundaries(cbinx_adj, y) == kFALSE) {
256 
257  // The adjacent bin is outside the DP range. Don't extrapolate.
258  value = this->getBinHistValue(i,j);
259 
260  } else {
261 
262  Double_t dx0 = TMath::Abs(x - cbinx);
263  Double_t dx1 = TMath::Abs(cbinx_adj - x);
264  Double_t inter_denom = dx0 + dx1;
265 
266  Double_t value1 = this->getBinHistValue(i,j);
267  Double_t value2 = this->getBinHistValue(i_adj,j);
268 
269  value = (value1*dx1 + value2*dx0)/inter_denom;
270 
271  }
272 
273  } else if (isYBoundary == kTRUE && isXBoundary == kFALSE) {
274 
275  // Find the adjacent y bin centre
276  Double_t cbiny_adj = Double_t(j_adj+0.5)*binYWidth_ + minY_;
277 
278  if (withinDPBoundaries(x, cbiny_adj) == kFALSE) {
279 
280  // The adjacent bin is outside the DP range. Don't extrapolate.
281  value = this->getBinHistValue(i,j);
282 
283  } else {
284 
285  Double_t dy0 = TMath::Abs(y - cbiny);
286  Double_t dy1 = TMath::Abs(cbiny_adj - y);
287  Double_t inter_denom = dy0 + dy1;
288 
289  Double_t value1 = this->getBinHistValue(i,j);
290  Double_t value2 = this->getBinHistValue(i,j_adj);
291 
292  value = (value1*dy1 + value2*dy0)/inter_denom;
293 
294  }
295 
296  } else {
297 
298  // 2D linear interpolation using inverse distance as weights.
299  // Find the adjacent x and y bin centres
300  Double_t cbinx_adj = Double_t(i_adj+0.5)*binXWidth_ + minX_;
301  Double_t cbiny_adj = Double_t(j_adj+0.5)*binYWidth_ + minY_;
302 
303  if (withinDPBoundaries(cbinx_adj, cbiny_adj) == kFALSE) {
304 
305  // The adjacent bin is outside the DP range. Don't extrapolate.
306  value = this->getBinHistValue(i,j);
307 
308  } else {
309 
310  Double_t dx0 = TMath::Abs(x - cbinx);
311  Double_t dx1 = TMath::Abs(cbinx_adj - x);
312  Double_t dy0 = TMath::Abs(y - cbiny);
313  Double_t dy1 = TMath::Abs(cbiny_adj - y);
314 
315  Double_t inter_denom = (dx0 + dx1)*(dy0 + dy1);
316 
317  Double_t value1 = this->getBinHistValue(i,j);
318  Double_t value2 = this->getBinHistValue(i_adj,j);
319  Double_t value3 = this->getBinHistValue(i,j_adj);
320  Double_t value4 = this->getBinHistValue(i_adj,j_adj);
321 
322  value = value1*dx1*dy1 + value2*dx0*dy1 + value3*dx1*dy0 + value4*dx0*dy0;
323  value /= inter_denom;
324  }
325 
326  }
327 
328  return value;
329 
330 }
331 
333 {
334  // Loop over the total x and y range to get the total area
335  // under x and y. Just sum the contributions up using 1e-3 increments
336  // of the range in x and y. Multiply the end result by dx and dy.
337 
338  const Double_t axisMin = TMath::Min( minX_, minY_ );
339  const Double_t axisMax = TMath::Max( maxX_, maxY_ );
340  const Double_t axisRange = axisMax - axisMin;
341 
342  const Double_t dx(1e-3 * axisRange);
343  const Double_t dy(dx);
344 
345  Double_t area(0.0);
346  Double_t areaNoNorm(0.0);
347 
348  // Preserve the value of a variable we change temporarily
349  Bool_t interpolate = useInterpolation_;
350 
351  Double_t x(axisMin + dx/2.0);
352  while (x < axisMax) {
353  Double_t y(axisMin + dy/2.0);
354  while (y < axisMax) {
355  area += this->interpolateXYNorm(x,y);
356  useInterpolation_ = kFALSE;
357  areaNoNorm += this->interpolateXY(x,y);
358  useInterpolation_ = kTRUE;
359  y += dy;
360  } // y while loop
361  x += dx;
362  } // x while loop
363  Double_t norm = area*dx*dy;
364 
365  useInterpolation_ = interpolate; //Restore old value
366 
367  std::cout << "INFO in Lau2DHistDPPdf::checkNormalisation : Area = " << area << ", dx = " << dx << ", dy = " << dy << ", dx*dy = " << dx*dy << std::endl;
368  std::cout << " : Area with no norm = " << areaNoNorm << "*dx*dy = " << areaNoNorm*dx*dy << std::endl;
369  std::cout << " : The total area of the normalised histogram PDF is " << norm << std::endl;
370 }
371 
Double_t minY_
The histogram y-axis minimum.
Bool_t passVeto(const LauKinematics *kinematics) const
Check whether the specified Dalitz plot point passes the vetoes.
Definition: LauVetoes.cc:118
Double_t norm_
The histogram normalisation.
Double_t invBinYWidth_
The histogram y-axis inverse bin width.
ClassImp(LauAbsCoeffSet)
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.
Abstract base class for defining a variation across a 2D DP based on a histogram. ...
Bool_t withinDPBoundaries(Double_t x, Double_t y) const
Check whether the given co-ordinates are within the kinematic boundary.
Class for defining a 2D DP histogram PDF.
const LauVetoes * getVetoes() const
Get the vetoes object.
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 checkNormalisation()
Check the normalisation calculation.
Double_t minX_
The histogram x-axis minimum.
void getUpperHalf(Double_t &x, Double_t &y) const
If only using the upper half of the (symmetric) DP then transform into the correct half...
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.
Double_t getBinHistValue(Int_t xBinNo, Int_t yBinNo) const
Get the bin content from the histogram.
const LauKinematics * getKinematics() const
Get the kinematics object.
Class for calculating 3-body kinematic quantities.
Double_t value() const
The value of the parameter.
void updateKinematics(Double_t x, Double_t y) const
Update the current co-ordinates in the kinematic space.
File containing declaration of LauVetoes class.
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:50