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