laura is hosted by Hepforge, IPPP Durham
Laura++  3.6.0
A maximum likelihood fitting package for performing Dalitz-plot analysis.
LauIsobarDynamics.cc
Go to the documentation of this file.
1 
2 /*
3 Copyright 2005 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 "LauIsobarDynamics.hh"
30 
31 #include "LauASqMaxFinder.hh"
32 #include "LauAbsEffModel.hh"
33 #include "LauAbsIncohRes.hh"
34 #include "LauAbsResonance.hh"
35 #include "LauBelleNR.hh"
36 #include "LauBelleSymNR.hh"
37 #include "LauCacheData.hh"
38 #include "LauConstants.hh"
40 #include "LauDaughters.hh"
41 #include "LauFitDataTree.hh"
42 #include "LauKMatrixProdPole.hh"
43 #include "LauKMatrixProdSVP.hh"
44 #include "LauKMatrixPropFactory.hh"
45 #include "LauKMatrixPropagator.hh"
46 #include "LauKinematics.hh"
47 #include "LauNRAmplitude.hh"
48 #include "LauPrint.hh"
49 #include "LauRandom.hh"
50 #include "LauResonanceInfo.hh"
51 #include "LauResonanceMaker.hh"
52 #include "LauRhoOmegaMix.hh"
53 
54 #include "TFile.h"
55 #include "TRandom.h"
56 #include "TSystem.h"
57 
58 #include <fstream>
59 #include <iomanip>
60 #include <iostream>
61 #include <set>
62 #include <vector>
63 
64 // for Kpipi: only one scfFraction 2D histogram is needed
66  LauAbsEffModel* effModel,
67  LauAbsEffModel* scfFractionModel ) :
68  daughters_( daughters ),
69  kinematics_( daughters_ ? daughters_->getKinematics() : 0 ),
70  effModel_( effModel ),
71  nAmp_( 0 ),
72  nIncohAmp_( 0 ),
73  DPNorm_( 0.0 ),
74  DPRate_( "DPRate", 0.0, 0.0, 1000.0 ),
75  meanDPEff_( "meanDPEff", 0.0, 0.0, 1.0 ),
76  currentEvent_( 0 ),
77  symmetricalDP_( kFALSE ),
78  fullySymmetricDP_( kFALSE ),
79  flavConjDP_( kFALSE ),
80  integralsDone_( kFALSE ),
81  normalizationSchemeDone_( kFALSE ),
82  forceSymmetriseIntegration_( kFALSE ),
83  intFileName_( "integ.dat" ),
84  m13BinWidth_( 0.005 ),
85  m23BinWidth_( 0.005 ),
86  mPrimeBinWidth_( 0.001 ),
87  thPrimeBinWidth_( 0.001 ),
88  narrowWidth_( 0.020 ),
89  binningFactor_( 100.0 ),
90  m13Sq_( 0.0 ),
91  m23Sq_( 0.0 ),
92  mPrime_( 0.0 ),
93  thPrime_( 0.0 ),
94  tagCat_( -1 ),
95  eff_( 1.0 ),
96  scfFraction_( 0.0 ),
97  jacobian_( 0.0 ),
98  ASq_( 0.0 ),
99  evtLike_( 0.0 ),
100  iterationsMax_( 100000 ),
101  nSigGenLoop_( 0 ),
102  aSqMaxSet_( 1.25 ),
103  aSqMaxVar_( 0.0 ),
104  flipHelicity_( kTRUE ),
105  recalcNormalisation_( kFALSE ),
106  calculateRhoOmegaFitFractions_( kFALSE )
107 {
108  if ( daughters != 0 ) {
109  symmetricalDP_ = daughters->gotSymmetricalDP();
110  fullySymmetricDP_ = daughters->gotFullySymmetricDP();
111  flavConjDP_ = daughters->gotFlavourConjugateDP();
112  typDaug_.push_back( daughters->getTypeDaug1() );
113  typDaug_.push_back( daughters->getTypeDaug2() );
114  typDaug_.push_back( daughters->getTypeDaug3() );
115  }
116 
117  if ( scfFractionModel != 0 ) {
118  scfFractionModel_[0] = scfFractionModel;
119  }
120 
121  sigResonances_.clear();
122  sigIncohResonances_.clear();
123  kMatrixPropagators_.clear();
124  kMatrixPropSet_.clear();
125  extraParameters_.clear();
126 }
127 
128 // for Kspipi, we need a scfFraction 2D histogram for each tagging category. They are provided by the map.
129 // Also, we need to know the place that the tagging category of the current event occupies in the data structure inputFitTree
131  LauAbsEffModel* effModel,
132  LauTagCatScfFractionModelMap scfFractionModel ) :
133  daughters_( daughters ),
134  kinematics_( daughters_ ? daughters_->getKinematics() : 0 ),
135  effModel_( effModel ),
136  scfFractionModel_( scfFractionModel ),
137  nAmp_( 0 ),
138  nIncohAmp_( 0 ),
139  DPNorm_( 0.0 ),
140  DPRate_( "DPRate", 0.0, 0.0, 1000.0 ),
141  meanDPEff_( "meanDPEff", 0.0, 0.0, 1.0 ),
142  currentEvent_( 0 ),
143  symmetricalDP_( kFALSE ),
144  fullySymmetricDP_( kFALSE ),
145  flavConjDP_( kFALSE ),
146  integralsDone_( kFALSE ),
147  normalizationSchemeDone_( kFALSE ),
148  forceSymmetriseIntegration_( kFALSE ),
149  intFileName_( "integ.dat" ),
150  m13BinWidth_( 0.005 ),
151  m23BinWidth_( 0.005 ),
152  mPrimeBinWidth_( 0.001 ),
153  thPrimeBinWidth_( 0.001 ),
154  narrowWidth_( 0.020 ),
155  binningFactor_( 100.0 ),
156  m13Sq_( 0.0 ),
157  m23Sq_( 0.0 ),
158  mPrime_( 0.0 ),
159  thPrime_( 0.0 ),
160  tagCat_( -1 ),
161  eff_( 1.0 ),
162  scfFraction_( 0.0 ),
163  jacobian_( 0.0 ),
164  ASq_( 0.0 ),
165  evtLike_( 0.0 ),
166  iterationsMax_( 100000 ),
167  nSigGenLoop_( 0 ),
168  aSqMaxSet_( 1.25 ),
169  aSqMaxVar_( 0.0 ),
170  flipHelicity_( kTRUE ),
171  recalcNormalisation_( kFALSE ),
172  calculateRhoOmegaFitFractions_( kFALSE )
173 {
174  // Constructor for the isobar signal model
175  if ( daughters != 0 ) {
176  symmetricalDP_ = daughters->gotSymmetricalDP();
177  fullySymmetricDP_ = daughters->gotFullySymmetricDP();
178  flavConjDP_ = daughters->gotFlavourConjugateDP();
179  typDaug_.push_back( daughters->getTypeDaug1() );
180  typDaug_.push_back( daughters->getTypeDaug2() );
181  typDaug_.push_back( daughters->getTypeDaug3() );
182  }
183 
184  sigResonances_.clear();
185  sigIncohResonances_.clear();
186  kMatrixPropagators_.clear();
187  kMatrixPropSet_.clear();
188  extraParameters_.clear();
189 }
190 
192 {
193  extraParameters_.clear();
194 
195  for ( std::vector<LauCacheData*>::iterator iter = data_.begin(); iter != data_.end(); ++iter ) {
196  delete ( *iter );
197  }
198  data_.clear();
199 
200  for ( std::vector<LauDPPartialIntegralInfo*>::iterator it = dpPartialIntegralInfo_.begin();
201  it != dpPartialIntegralInfo_.end();
202  ++it ) {
203  delete ( *it );
204  }
205  dpPartialIntegralInfo_.clear();
206 }
207 
209 {
210  for ( UInt_t i = 0; i < nAmp_; i++ ) {
211 
212  fSqSum_[i] = 0.0;
213  fSqEffSum_[i] = 0.0;
214  fNorm_[i] = 0.0;
215  ff_[i].zero();
216 
217  for ( UInt_t j = 0; j < nAmp_; j++ ) {
218 
219  fifjEffSum_[i][j].zero();
220  fifjSum_[i][j].zero();
221  }
222  }
223 
224  for ( UInt_t i = 0; i < nIncohAmp_; i++ ) {
225  fSqSum_[i + nAmp_] = 0.0;
226  fSqEffSum_[i + nAmp_] = 0.0;
227  fNorm_[i + nAmp_] = 0.0;
228  incohInten_[i] = 0.0;
229  }
230 }
231 
233 {
234  if ( recalcNormalisation_ == kFALSE ) {
235  return;
236  }
237 
238  // We need to calculate the normalisation constants for the
239  // Dalitz plot generation/fitting.
240 
241  integralsDone_ = kFALSE;
242 
243  this->resetNormVectors();
245  this->calcDPNormalisation();
246 
247  integralsDone_ = kTRUE;
248 }
249 
251 {
252  // Loop through the resonance parameters and see which ones have changed
253  // For those that have changed mark the corresponding resonance(s) as needing to be re-evaluated
254 
255  integralsToBeCalculated_.clear();
256 
257  const UInt_t nResPars = resonancePars_.size();
258  for ( UInt_t iPar( 0 ); iPar < nResPars; ++iPar ) {
259  const Double_t newValue = resonancePars_[iPar]->value();
260  if ( newValue != resonanceParValues_[iPar] ) {
261  resonanceParValues_[iPar] = newValue;
262 
263  const std::vector<UInt_t>& indices = resonanceParResIndex_[iPar];
264  std::vector<UInt_t>::const_iterator indexIter = indices.begin();
265  const std::vector<UInt_t>::const_iterator indexEnd = indices.end();
266  for ( ; indexIter != indexEnd; ++indexIter ) {
267  integralsToBeCalculated_.insert( *indexIter );
268  }
269  }
270  }
271 }
272 
274 {
275  // Initialise all resonance models
276  resonancePars_.clear();
277  resonanceParValues_.clear();
278  resonanceParResIndex_.clear();
279 
280  std::set<LauParameter*> uniqueResPars;
281  UInt_t resIndex( 0 );
282  for ( std::vector<LauAbsResonance*>::iterator resIter = sigResonances_.begin();
283  resIter != sigResonances_.end();
284  ++resIter ) {
285  ( *resIter )->initialise();
286 
287  // Check if this resonance has floating parameters
288  // Append all unique parameters to our list
289  const std::vector<LauParameter*>& resPars = ( *resIter )->getFloatingParameters();
290 
291  for ( std::vector<LauParameter*>::const_iterator parIter = resPars.begin();
292  parIter != resPars.end();
293  ++parIter ) {
294  if ( uniqueResPars.insert( *parIter ).second ) {
295  // This parameter has not already been added to
296  // the list of unique ones. Add it, its value
297  // and its associated resonance ID to the
298  // appropriate lists.
299  resonancePars_.push_back( *parIter );
300  resonanceParValues_.push_back( ( *parIter )->value() );
301  std::vector<UInt_t> resIndices( 1, resIndex );
302  resonanceParResIndex_.push_back( resIndices );
303  } else {
304  // This parameter has already been added to the
305  // list of unique ones. However, we still need
306  // to indicate that this resonance should be
307  // associated with it.
308  std::vector<LauParameter*>::const_iterator uniqueParIter = resonancePars_.begin();
309  std::vector<std::vector<UInt_t>>::iterator indicesIter = resonanceParResIndex_.begin();
310  while ( ( *uniqueParIter ) != ( *parIter ) ) {
311  ++uniqueParIter;
312  ++indicesIter;
313  }
314  ( *indicesIter ).push_back( resIndex );
315  }
316  }
317 
318  ++resIndex;
319  }
320 
321  for ( std::vector<LauAbsIncohRes*>::iterator resIter = sigIncohResonances_.begin();
322  resIter != sigIncohResonances_.end();
323  ++resIter ) {
324  ( *resIter )->initialise();
325 
326  // Check if this resonance has floating parameters
327  // Append all unique parameters to our list
328  const std::vector<LauParameter*>& resPars = ( *resIter )->getFloatingParameters();
329 
330  for ( std::vector<LauParameter*>::const_iterator parIter = resPars.begin();
331  parIter != resPars.end();
332  ++parIter ) {
333  if ( uniqueResPars.insert( *parIter ).second ) {
334  // This parameter has not already been added to
335  // the list of unique ones. Add it, its value
336  // and its associated resonance ID to the
337  // appropriate lists.
338  resonancePars_.push_back( *parIter );
339  resonanceParValues_.push_back( ( *parIter )->value() );
340  std::vector<UInt_t> resIndices( 1, resIndex );
341  resonanceParResIndex_.push_back( resIndices );
342  } else {
343  // This parameter has already been added to the
344  // list of unique ones. However, we still need
345  // to indicate that this resonance should be
346  // associated with it.
347  std::vector<LauParameter*>::const_iterator uniqueParIter = resonancePars_.begin();
348  std::vector<std::vector<UInt_t>>::iterator indicesIter = resonanceParResIndex_.begin();
349  while ( ( *uniqueParIter ) != ( *parIter ) ) {
350  ++uniqueParIter;
351  ++indicesIter;
352  }
353  ( *indicesIter ).push_back( resIndex );
354  }
355  }
356 
357  ++resIndex;
358  }
359 }
360 
361 void LauIsobarDynamics::initialise( const std::vector<LauComplex>& coeffs )
362 {
363  // Check whether we have a valid set of integration constants for
364  // the normalisation of the signal likelihood function.
365  this->initialiseVectors();
366 
367  // Mark the DP integrals as undetermined
368  integralsDone_ = kFALSE;
369 
371 
372  if ( resonancePars_.empty() ) {
373  recalcNormalisation_ = kFALSE;
374  } else {
375  recalcNormalisation_ = kTRUE;
376  }
377 
378  // Print summary of what we have so far to screen
379  this->initSummary();
380 
381  if ( nAmp_ + nIncohAmp_ == 0 ) {
382  std::cout << "INFO in LauIsobarDynamics::initialise : No contributions to DP model, not performing normalisation integrals."
383  << std::endl;
384  } else {
385 
386  // We need to calculate the normalisation constants for the Dalitz plot generation/fitting.
387 
388  std::cout << "INFO in LauIsobarDynamics::initialise : Starting special run to generate the integrals for normalising the PDF..."
389  << std::endl;
390 
391  // Since this is the initialisation, we need to calculate everything for every resonance
392  integralsToBeCalculated_.clear();
393  for ( UInt_t i( 0 ); i < nAmp_ + nIncohAmp_; ++i ) {
394  integralsToBeCalculated_.insert( i );
395  }
396 
397  // Calculate and cache the normalisations of each resonance _dynamic_ amplitude
398  // (e.g. Breit-Wigner contribution, not from the complex coefficients).
399  // These are stored in fNorm_[i].
400  // fSqSum[i] is the total of the dynamical amplitude squared for a given resonance, i.
401  // We require that:
402  // |fNorm_[i]|^2 * |fSqSum[i]|^2 = 1,
403  // i.e. fNorm_[i] normalises each resonance contribution to give the same number of
404  // events in the DP, accounting for the total DP area and the dynamics of the resonance.
405  this->calcDPNormalisation();
406 
407  // Write the integrals to a file (mainly for debugging purposes)
408  this->writeIntegralsFile();
409  }
410 
411  integralsDone_ = kTRUE;
412 
413  std::cout << std::setprecision( 10 );
414 
415  std::cout << "INFO in LauIsobarDynamics::initialise : Summary of the integrals:" << std::endl;
416 
417  for ( UInt_t i = 0; i < nAmp_ + nIncohAmp_; i++ ) {
418  std::cout << " fNorm[" << i << "] = " << fNorm_[i] << std::endl;
419  std::cout << " fSqSum[" << i << "] = " << fSqSum_[i] << std::endl;
420  std::cout << " fSqEffSum[" << i << "] = " << fSqEffSum_[i] << std::endl;
421  }
422 
423  for ( UInt_t i = 0; i < nAmp_; i++ ) {
424  for ( UInt_t j = 0; j < nAmp_; j++ ) {
425  std::cout << " fifjEffSum[" << i << "][" << j << "] = " << fifjEffSum_[i][j];
426  }
427  std::cout << std::endl;
428  }
429 
430  for ( UInt_t i = 0; i < nAmp_; i++ ) {
431  for ( UInt_t j = 0; j < nAmp_; j++ ) {
432  std::cout << " fifjSum[" << i << "][" << j << "] = " << fifjSum_[i][j];
433  }
434  std::cout << std::endl;
435  }
436 
437  // Calculate the initial fit fractions (for later comparison with Toy MC, if required)
438  this->updateCoeffs( coeffs );
439  this->calcExtraInfo( kTRUE );
440 
441  for ( UInt_t i = 0; i < nAmp_; i++ ) {
442  for ( UInt_t j = i; j < nAmp_; j++ ) {
443  std::cout << "INFO in LauIsobarDynamics::initialise : Initial fit fraction for amplitude ("
444  << i << "," << j << ") = " << fitFrac_[i][j].genValue() << std::endl;
445  }
446  }
447 
448  for ( UInt_t i = 0; i < nIncohAmp_; i++ ) {
449  std::cout << "INFO in LauIsobarDynamics::initialise : Initial fit fraction for incoherent amplitude ("
450  << i << "," << i << ") = " << fitFrac_[i + nAmp_][i + nAmp_].genValue()
451  << std::endl;
452  }
453 
454  std::cout << "INFO in LauIsobarDynamics::initialise : Initial efficiency = "
455  << meanDPEff_.initValue() << std::endl;
456 
457  std::cout << "INFO in LauIsobarDynamics::initialise : Initial DPRate = " << DPRate_.initValue()
458  << std::endl;
459 }
460 
462 {
463 
464  UInt_t i( 0 );
465  TString nameP = daughters_->getNameParent();
466  TString name1 = daughters_->getNameDaug1();
467  TString name2 = daughters_->getNameDaug2();
468  TString name3 = daughters_->getNameDaug3();
469 
470  std::cout << "INFO in LauIsobarDynamics::initSummary : We are going to do a DP with " << nameP
471  << " going to " << name1 << " " << name2 << " " << name3 << std::endl;
472 
473  std::cout << " : For the following resonance combinations:"
474  << std::endl;
475 
476  std::cout << " : In tracks 2 and 3:" << std::endl;
477  for ( i = 0; i < nAmp_; i++ ) {
478  if ( resPairAmp_[i] == 1 ) {
479  std::cout << " : A" << i << ": "
480  << resTypAmp_[i] << " to " << name2 << ", " << name3 << std::endl;
481  }
482  }
483 
484  for ( i = 0; i < nIncohAmp_; i++ ) {
485  if ( incohResPairAmp_[i] == 1 ) {
486  std::cout << " : A" << nAmp_ + i << ": "
487  << incohResTypAmp_[i] << " (incoherent) to " << name2 << ", " << name3
488  << std::endl;
489  }
490  }
491 
492  std::cout << " : In tracks 1 and 3:" << std::endl;
493  for ( i = 0; i < nAmp_; i++ ) {
494  if ( resPairAmp_[i] == 2 ) {
495  std::cout << " : A" << i << ": "
496  << resTypAmp_[i] << " to " << name1 << ", " << name3 << std::endl;
497  }
498  }
499 
500  for ( i = 0; i < nIncohAmp_; i++ ) {
501  if ( incohResPairAmp_[i] == 2 ) {
502  std::cout << " : A" << nAmp_ + i << ": "
503  << incohResTypAmp_[i] << " (incoherent) to " << name1 << ", " << name3
504  << std::endl;
505  }
506  }
507 
508  std::cout << " : In tracks 1 and 2:" << std::endl;
509  for ( i = 0; i < nAmp_; i++ ) {
510  if ( resPairAmp_[i] == 3 ) {
511  std::cout << " : A" << i << ": "
512  << resTypAmp_[i] << " to " << name1 << ", " << name2 << std::endl;
513  }
514  }
515 
516  for ( i = 0; i < nIncohAmp_; i++ ) {
517  if ( incohResPairAmp_[i] == 3 ) {
518  std::cout << " : A" << nAmp_ + i << ": "
519  << incohResTypAmp_[i] << " (incoherent) to " << name1 << ", " << name2
520  << std::endl;
521  }
522  }
523 
524  for ( i = 0; i < nAmp_; i++ ) {
525  if ( resPairAmp_[i] == 0 ) {
526  std::cout << " : and a non-resonant amplitude:"
527  << std::endl;
528  std::cout << " : A" << i << std::endl;
529  }
530  }
531 
532  std::cout << std::endl;
533 }
534 
536 {
537  fSqSum_.clear();
538  fSqSum_.resize( nAmp_ + nIncohAmp_ );
539  fSqEffSum_.clear();
540  fSqEffSum_.resize( nAmp_ + nIncohAmp_ );
541  fifjEffSum_.clear();
542  fifjEffSum_.resize( nAmp_ );
543  fifjSum_.clear();
544  fifjSum_.resize( nAmp_ );
545  ff_.clear();
546  ff_.resize( nAmp_ );
547  incohInten_.clear();
548  incohInten_.resize( nIncohAmp_ );
549  fNorm_.clear();
550  fNorm_.resize( nAmp_ + nIncohAmp_ );
551  fitFrac_.clear();
552  fitFrac_.resize( nAmp_ + nIncohAmp_ );
553  fitFracEffUnCorr_.clear();
554  fitFracEffUnCorr_.resize( nAmp_ + nIncohAmp_ );
555 
556  LauComplex null( 0.0, 0.0 );
557 
558  for ( UInt_t i = 0; i < nAmp_; i++ ) {
559 
560  fSqSum_[i] = 0.0;
561  fNorm_[i] = 0.0;
562  ff_[i] = null;
563  fifjEffSum_[i].resize( nAmp_ );
564  fifjSum_[i].resize( nAmp_ );
565  fitFrac_[i].resize( nAmp_ + nIncohAmp_ );
566  fitFracEffUnCorr_[i].resize( nAmp_ + nIncohAmp_ );
567 
568  for ( UInt_t j = 0; j < nAmp_; j++ ) {
569  fifjEffSum_[i][j] = null;
570  fifjSum_[i][j] = null;
571  fitFrac_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
572  fitFracEffUnCorr_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
573  }
574  for ( UInt_t j = nAmp_; j < nAmp_ + nIncohAmp_; j++ ) {
575  fitFrac_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
576  fitFracEffUnCorr_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
577  }
578  }
579  for ( UInt_t i = nAmp_; i < nAmp_ + nIncohAmp_; i++ ) {
580  fSqSum_[i] = 0.0;
581  fNorm_[i] = 0.0;
582  incohInten_[i - nAmp_] = 0.0;
583  fitFrac_[i].resize( nAmp_ + nIncohAmp_ );
584  fitFracEffUnCorr_[i].resize( nAmp_ + nIncohAmp_ );
585 
586  for ( UInt_t j = 0; j < nAmp_ + nIncohAmp_; j++ ) {
587  fitFrac_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
588  fitFracEffUnCorr_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
589  }
590  }
591 
592  UInt_t nKMatrixProps = kMatrixPropagators_.size();
593  extraParameters_.clear();
594  extraParameters_.resize( nKMatrixProps );
595 
596  for ( UInt_t i = 0; i < nKMatrixProps; ++i ) {
597  extraParameters_[i].valueAndRange( 0.0, -100.0, 100.0 );
598  }
599 }
600 
602 {
603  // Routine to end integration calculation for loglike normalisation.
604  // This writes out the normalisation integral output into the file named
605  // outputFileName.
606  std::cout << "INFO in LauIsobarDynamics::writeIntegralsFile : Writing integral output to integrals file "
607  << intFileName_.Data() << std::endl;
608 
609  UInt_t i( 0 ), j( 0 );
610  std::ofstream getChar( intFileName_.Data() );
611 
612  getChar << std::setprecision( 10 );
613 
614  // Write out daughter types (pi, pi0, K, K0s?)
615  for ( i = 0; i < 3; i++ ) {
616  getChar << typDaug_[i] << " ";
617  }
618 
619  // Write out number of resonances in the Dalitz plot model
620  getChar << nAmp_ << std::endl;
621 
622  // Write out the resonances
623  for ( i = 0; i < nAmp_; i++ ) {
624  getChar << resTypAmp_[i] << " ";
625  }
626 
627  getChar << std::endl;
628 
629  // Write out the resonance model types (BW, RelBW etc...)
630  for ( i = 0; i < nAmp_; i++ ) {
631  LauAbsResonance* theResonance = sigResonances_[i];
632  Int_t resModelInt = theResonance->getResonanceModel();
633  getChar << resModelInt << " ";
634  }
635 
636  getChar << std::endl;
637 
638  // Write out the track pairings for each resonance. This is specified
639  // by the resPairAmpInt integer in the addResonance function.
640  for ( i = 0; i < nAmp_; i++ ) {
641  getChar << resPairAmp_[i] << " ";
642  }
643 
644  getChar << std::endl;
645 
646  // Write out the fSqSum = |ff|^2, where ff = resAmp()
647  for ( i = 0; i < nAmp_; i++ ) {
648  getChar << fSqSum_[i] << " ";
649  }
650 
651  getChar << std::endl;
652 
653  // Similar to fSqSum, but with the efficiency term included.
654  for ( i = 0; i < nAmp_; i++ ) {
655  getChar << fSqEffSum_[i] << " ";
656  }
657 
658  getChar << std::endl;
659 
660  // Write out the f_i*f_j_conj*eff values = resAmp_i*resAmp_j_conj*eff.
661  // Note that only the top half of the i*j "matrix" is required, as it
662  // is symmetric w.r.t i, j.
663  for ( i = 0; i < nAmp_; i++ ) {
664  for ( j = i; j < nAmp_; j++ ) {
665  getChar << fifjEffSum_[i][j] << " ";
666  }
667  }
668 
669  getChar << std::endl;
670 
671  // Similar to fifjEffSum, but without the efficiency term included.
672  for ( i = 0; i < nAmp_; i++ ) {
673  for ( j = i; j < nAmp_; j++ ) {
674  getChar << fifjSum_[i][j] << " ";
675  }
676  }
677 
678  getChar << std::endl;
679 
680  // Write out number of incoherent resonances in the Dalitz plot model
681  getChar << nIncohAmp_ << std::endl;
682 
683  // Write out the incoherent resonances
684  for ( i = 0; i < nIncohAmp_; i++ ) {
685  getChar << incohResTypAmp_[i] << " ";
686  }
687 
688  getChar << std::endl;
689 
690  // Write out the incoherent resonance model types (BW, RelBW etc...)
691  for ( i = 0; i < nIncohAmp_; i++ ) {
692  LauAbsResonance* theResonance = sigIncohResonances_[i];
693  Int_t resModelInt = theResonance->getResonanceModel();
694  getChar << resModelInt << " ";
695  }
696 
697  getChar << std::endl;
698 
699  // Write out the track pairings for each incoherent resonance. This is specified
700  // by the resPairAmpInt integer in the addIncohResonance function.
701  for ( i = 0; i < nIncohAmp_; i++ ) {
702  getChar << incohResPairAmp_[i] << " ";
703  }
704 
705  getChar << std::endl;
706 
707  // Write out the fSqSum = |ff|^2, where |ff|^2 = incohResAmp()
708  for ( i = nAmp_; i < nAmp_ + nIncohAmp_; i++ ) {
709  getChar << fSqSum_[i] << " ";
710  }
711 
712  getChar << std::endl;
713 
714  // Similar to fSqSum, but with the efficiency term included.
715  for ( i = nAmp_; i < nAmp_ + nIncohAmp_; i++ ) {
716  getChar << fSqEffSum_[i] << " ";
717  }
718 
719  getChar << std::endl;
720 }
721 
723  const TString& resName,
724  const Int_t resPairAmpInt,
727 {
728  // Function to add a resonance in a Dalitz plot.
729  // No check is made w.r.t flavour and charge conservation rules, and so
730  // the user is responsible for checking the internal consistency of
731  // their function statements with these laws. For example, the program
732  // will not prevent the user from asking for a rho resonance in a K-pi
733  // pair or a K* resonance in a pi-pi pair.
734  // However, to assist the user, a summary of the resonant structure requested
735  // by the user is printed before the program runs. It is important to check this
736  // information when you first define your Dalitz plot model before doing
737  // any fitting/generating.
738  // Arguments are: resonance name, integer to specify the resonance track pairing
739  // (1 => m_23, 2 => m_13, 3 => m_12), i.e. the bachelor track number.
740  // The third argument resType specifies whether the resonance is a Breit-Wigner (BW)
741  // Relativistic Breit-Wigner (RelBW) or Flatte distribution (Flatte), for example.
742 
743  if ( LauAbsResonance::isIncoherentModel( resType ) == true ) {
744  std::cerr << "ERROR in LauIsobarDynamics::addResonance : Resonance type \"" << resType
745  << "\" not allowed for a coherent resonance" << std::endl;
746  return 0;
747  }
748 
749  LauResonanceMaker& resonanceMaker = LauResonanceMaker::get();
750  LauAbsResonance* theResonance =
751  resonanceMaker.getResonance( daughters_, resName, resPairAmpInt, resType, bwCategory );
752 
753  if ( theResonance == 0 ) {
754  std::cerr << "ERROR in LauIsobarDynamics::addResonance : Couldn't create the resonance \""
755  << resName << "\"" << std::endl;
756  return 0;
757  }
758 
759  // implement the helicity flip here
760  if ( flipHelicity_ && daughters_->getCharge( resPairAmpInt ) == 0 &&
761  daughters_->getChargeParent() == 0 && daughters_->getTypeParent() > 0 ) {
762  if ( ( resPairAmpInt == 1 && TMath::Abs( daughters_->getTypeDaug2() ) ==
763  TMath::Abs( daughters_->getTypeDaug3() ) ) ||
764  ( resPairAmpInt == 2 && TMath::Abs( daughters_->getTypeDaug1() ) ==
765  TMath::Abs( daughters_->getTypeDaug3() ) ) ||
766  ( resPairAmpInt == 3 && TMath::Abs( daughters_->getTypeDaug1() ) ==
767  TMath::Abs( daughters_->getTypeDaug2() ) ) ) {
768  theResonance->flipHelicity( kTRUE );
769  }
770  }
771 
772  // Set the resonance name and what track is the bachelor
773  TString resonanceName = theResonance->getResonanceName();
774  resTypAmp_.push_back( resonanceName );
775 
776  // Always force the non-resonant amplitude pair to have resPairAmp = 0
777  // in case the user chooses the wrong number.
778  if ( resType == LauAbsResonance::FlatNR || resType == LauAbsResonance::NRModel ) {
779  std::cout << "INFO in LauIsobarDynamics::addResonance : Setting resPairAmp to 0 for "
780  << resonanceName << " contribution." << std::endl;
781  resPairAmp_.push_back( 0 );
782  } else {
783  resPairAmp_.push_back( resPairAmpInt );
784  }
785 
786  // Increment the number of resonance amplitudes we have so far
787  ++nAmp_;
788 
789  // Finally, add the resonance object to the internal array
790  sigResonances_.push_back( theResonance );
791 
792  std::cout << "INFO in LauIsobarDynamics::addResonance : Successfully added resonance. Total number of resonances so far = "
793  << nAmp_ << std::endl;
794 
795  return theResonance;
796 }
797 
799  const TString& resName,
800  const Int_t resPairAmpInt,
801  const LauAbsResonance::LauResonanceModel resType )
802 {
803  // Function to add an incoherent resonance in a Dalitz plot.
804  // No check is made w.r.t flavour and charge conservation rules, and so
805  // the user is responsible for checking the internal consistency of
806  // their function statements with these laws. For example, the program
807  // will not prevent the user from asking for a rho resonance in a K-pi
808  // pair or a K* resonance in a pi-pi pair.
809  // However, to assist the user, a summary of the resonant structure requested
810  // by the user is printed before the program runs. It is important to check this
811  // information when you first define your Dalitz plot model before doing
812  // any fitting/generating.
813  // Arguments are: resonance name, integer to specify the resonance track pairing
814  // (1 => m_23, 2 => m_13, 3 => m_12), i.e. the bachelor track number.
815  // The third argument resType specifies the shape of the resonance
816  // Gaussian (GaussIncoh), for example.
817 
818  if ( LauAbsResonance::isIncoherentModel( resType ) == false ) {
819  std::cerr << "ERROR in LauIsobarDynamics::addIncohResonance : Resonance type \"" << resType
820  << "\" not allowed for an incoherent resonance" << std::endl;
821  return 0;
822  }
823 
824  LauResonanceMaker& resonanceMaker = LauResonanceMaker::get();
825  LauAbsIncohRes* theResonance = dynamic_cast<LauAbsIncohRes*>(
826  resonanceMaker.getResonance( daughters_, resName, resPairAmpInt, resType ) );
827 
828  if ( theResonance == 0 ) {
829  std::cerr << "ERROR in LauIsobarDynamics::addIncohResonance : Couldn't create the resonance \""
830  << resName << "\"" << std::endl;
831  return 0;
832  }
833 
834  // Set the resonance name and what track is the bachelor
835  TString resonanceName = theResonance->getResonanceName();
836  incohResTypAmp_.push_back( resonanceName );
837  incohResPairAmp_.push_back( resPairAmpInt );
838 
839  // Increment the number of resonance amplitudes we have so far
840  ++nIncohAmp_;
841 
842  // Finally, add the resonance object to the internal array
843  sigIncohResonances_.push_back( theResonance );
844 
845  std::cout << "INFO in LauIsobarDynamics::addIncohResonance : Successfully added incoherent resonance. Total number of incoherent resonances so far = "
846  << nIncohAmp_ << std::endl;
847 
848  return theResonance;
849 }
850 
852  const TString& paramFileName,
853  Int_t resPairAmpInt,
854  Int_t nChannels,
855  Int_t nPoles,
856  Int_t rowIndex )
857 {
858  // Define the K-matrix propagator. The resPairAmpInt integer specifies which mass combination should be used
859  // for the invariant mass-squared variable "s". The pole masses and coupling constants are defined in the
860  // paramFileName parameter file.
861  // The number of channels and poles are defined by the nChannels and nPoles integers, respectively.
862  // The integer rowIndex specifies which row of the propagator should be used when
863  // summing over all amplitude channels: S-wave will be the first row, so rowIndex = 1.
864 
865  // Check that the rowIndex is valid
866  if ( rowIndex < 1 || rowIndex > nChannels ) {
867  std::cerr << "ERROR in LauIsobarDynamics::defineKMatrixPropagator. The rowIndex, which is set to "
868  << rowIndex << ", must be between 1 and the number of channels " << nChannels
869  << std::endl;
870  gSystem->Exit( EXIT_FAILURE );
871  }
872 
873  TString propagatorName( propName ), parameterFile( paramFileName );
874 
875  LauKMatrixPropagator* thePropagator =
877  parameterFile,
878  resPairAmpInt,
879  nChannels,
880  nPoles,
881  rowIndex );
882  kMatrixPropagators_[propagatorName] = thePropagator;
883 
884  return thePropagator;
885 }
886 
887 void LauIsobarDynamics::addKMatrixProdPole( const TString& poleName,
888  const TString& propName,
889  Int_t poleIndex,
890  Bool_t useProdAdler )
891 {
892 
893  // Add a K-matrix production pole term, using the K-matrix propagator given by the propName.
894  // Here, poleIndex is the integer specifying the pole number.
895 
896  // First, find the K-matrix propagator.
897  KMPropMap::iterator mapIter = kMatrixPropagators_.find( propName );
898  if ( mapIter != kMatrixPropagators_.end() ) {
899 
900  LauKMatrixPropagator* thePropagator = mapIter->second;
901 
902  // Make sure the pole index is valid
903  Int_t nPoles = thePropagator->getNPoles();
904  if ( poleIndex < 1 || poleIndex > nPoles ) {
905  std::cerr << "ERROR in LauIsobarDynamics::addKMatrixProdPole : The pole index "
906  << poleIndex << " is not between 1 and " << nPoles
907  << ". Not adding production pole " << poleName << " for K-matrix propagator "
908  << propName << std::endl;
909  return;
910  }
911 
912  // Now add the K-matrix production pole amplitude to the vector of LauAbsResonance pointers.
913  Int_t resPairAmpInt = thePropagator->getResPairAmpInt();
914  LauAbsResonance* prodPole = new LauKMatrixProdPole( poleName,
915  poleIndex,
916  resPairAmpInt,
917  thePropagator,
918  daughters_,
919  useProdAdler );
921 
922  resTypAmp_.push_back( poleName );
923  resPairAmp_.push_back( resPairAmpInt );
924 
925  ++nAmp_;
926  sigResonances_.push_back( prodPole );
927 
928  // Also store the propName-poleName pair for calculating total fit fractions later on
929  // (avoiding the need to use dynamic casts to check which resonances are of the K-matrix type)
930  kMatrixPropSet_[poleName] = propName;
931 
932  std::cout << "INFO in LauIsobarDynamics::addKMatrixProdPole : Successfully added K-matrix production pole term. Total number of resonances so far = "
933  << nAmp_ << std::endl;
934 
935  } else {
936 
937  std::cerr << "ERROR in LauIsobarDynamics::addKMatrixProdPole : The propagator of the name "
938  << propName << " could not be found for the production pole " << poleName
939  << std::endl;
940  }
941 }
942 
943 void LauIsobarDynamics::addKMatrixProdSVP( const TString& SVPName,
944  const TString& propName,
945  Int_t channelIndex,
946  Bool_t useProdAdler )
947 {
948 
949  // Add a K-matrix production "slowly-varying part" (SVP) term, using the K-matrix propagator
950  // given by the propName. Here, channelIndex is the integer specifying the channel number.
951 
952  // First, find the K-matrix propagator.
953  KMPropMap::iterator mapIter = kMatrixPropagators_.find( propName );
954  if ( mapIter != kMatrixPropagators_.end() ) {
955 
956  LauKMatrixPropagator* thePropagator = mapIter->second;
957 
958  // Make sure the channel index is valid
959  Int_t nChannels = thePropagator->getNChannels();
960  if ( channelIndex < 1 || channelIndex > nChannels ) {
961  std::cerr << "ERROR in LauIsobarDynamics::addKMatrixProdSVP : The channel index "
962  << channelIndex << " is not between 1 and " << nChannels
963  << ". Not adding production slowly-varying part " << SVPName
964  << " for K-matrix propagator " << propName << std::endl;
965  return;
966  }
967 
968  // Now add the K-matrix production SVP amplitude to the vector of LauAbsResonance pointers.
969  Int_t resPairAmpInt = thePropagator->getResPairAmpInt();
970  LauAbsResonance* prodSVP = new LauKMatrixProdSVP( SVPName,
971  channelIndex,
972  resPairAmpInt,
973  thePropagator,
974  daughters_,
975  useProdAdler );
977 
978  resTypAmp_.push_back( SVPName );
979  resPairAmp_.push_back( resPairAmpInt );
980 
981  ++nAmp_;
982  sigResonances_.push_back( prodSVP );
983 
984  // Also store the SVPName-propName pair for calculating total fit fractions later on
985  // (avoiding the need to use dynamic casts to check which resonances are of the K-matrix type)
986  kMatrixPropSet_[SVPName] = propName;
987 
988  std::cout << "INFO in LauIsobarDynamics::addKMatrixProdSVP : Successfully added K-matrix production slowly-varying (SVP) term. Total number of resonances so far = "
989  << nAmp_ << std::endl;
990 
991  } else {
992 
993  std::cerr << "ERROR in LauIsobarDynamics::addKMatrixProdSVP : The propagator of the name "
994  << propName << " could not be found for the production slowly-varying part "
995  << SVPName << std::endl;
996  }
997 }
998 
999 Int_t LauIsobarDynamics::resonanceIndex( const TString& resName ) const
1000 {
1001  Int_t index( 0 );
1002  const LauAbsResonance* theResonance( 0 );
1003 
1004  for ( std::vector<LauAbsResonance*>::const_iterator iter = sigResonances_.begin();
1005  iter != sigResonances_.end();
1006  ++iter ) {
1007  theResonance = ( *iter );
1008  if ( theResonance != 0 ) {
1009  const TString& resString = theResonance->getResonanceName();
1010  if ( resString == resName ) {
1011  return index;
1012  }
1013  }
1014  ++index;
1015  }
1016 
1017  for ( std::vector<LauAbsIncohRes*>::const_iterator iter = sigIncohResonances_.begin();
1018  iter != sigIncohResonances_.end();
1019  ++iter ) {
1020  theResonance = ( *iter );
1021  if ( theResonance != 0 ) {
1022  const TString& resString = theResonance->getResonanceName();
1023  if ( resString == resName ) {
1024  return index;
1025  }
1026  }
1027  ++index;
1028  }
1029 
1030  return -1;
1031 }
1032 
1033 Bool_t LauIsobarDynamics::hasResonance( const TString& resName ) const
1034 {
1035  const Int_t index = this->resonanceIndex( resName );
1036  if ( index < 0 ) {
1037  return kFALSE;
1038  } else {
1039  return kTRUE;
1040  }
1041 }
1042 
1043 const LauAbsResonance* LauIsobarDynamics::getResonance( const UInt_t resIndex ) const
1044 {
1045  if ( resIndex < this->getnCohAmp() ) {
1046  return sigResonances_[resIndex];
1047  } else if ( resIndex < this->getnTotAmp() ) {
1048  return sigIncohResonances_[resIndex - nAmp_];
1049  } else {
1050  std::cerr << "ERROR in LauIsobarDynamics::getResonance : Couldn't find resonance with index \""
1051  << resIndex << "\" in the model." << std::endl;
1052  return 0;
1053  }
1054 }
1055 
1057 {
1058  if ( resIndex < this->getnCohAmp() ) {
1059  return sigResonances_[resIndex];
1060  } else if ( resIndex < this->getnTotAmp() ) {
1061  return sigIncohResonances_[resIndex - nAmp_];
1062  } else {
1063  std::cerr << "ERROR in LauIsobarDynamics::getResonance : Couldn't find resonance with index \""
1064  << resIndex << "\" in the model." << std::endl;
1065  return 0;
1066  }
1067 }
1068 
1070 {
1071  const Int_t index = this->resonanceIndex( resName );
1072  if ( index < 0 ) {
1073  std::cerr << "ERROR in LauIsobarDynamics::findResonance : Couldn't find resonance with name \""
1074  << resName << "\" in the model." << std::endl;
1075  return 0;
1076  } else {
1077  return this->getResonance( index );
1078  }
1079 }
1080 
1081 const LauAbsResonance* LauIsobarDynamics::findResonance( const TString& resName ) const
1082 {
1083  const Int_t index = this->resonanceIndex( resName );
1084  if ( index < 0 ) {
1085  std::cerr << "ERROR in LauIsobarDynamics::findResonance : Couldn't find resonance with name \""
1086  << resName << "\" in the model." << std::endl;
1087  return 0;
1088  } else {
1089  return this->getResonance( index );
1090  }
1091 }
1092 
1093 void LauIsobarDynamics::removeCharge( TString& string ) const
1094 {
1095  Ssiz_t index = string.Index( "+" );
1096  if ( index != -1 ) {
1097  string.Remove( index, 1 );
1098  }
1099  index = string.Index( "-" );
1100  if ( index != -1 ) {
1101  string.Remove( index, 1 );
1102  }
1103 }
1104 
1106 {
1107  if ( ! normalizationSchemeDone_ ) {
1108  this->calcDPNormalisationScheme();
1109  }
1110 
1111  for ( std::vector<LauDPPartialIntegralInfo*>::iterator it = dpPartialIntegralInfo_.begin();
1112  it != dpPartialIntegralInfo_.end();
1113  ++it ) {
1114  this->calcDPPartialIntegral( *it );
1115  }
1116 
1117  for ( UInt_t i = 0; i < nAmp_ + nIncohAmp_; ++i ) {
1118  fNorm_[i] = 0.0;
1119  if ( fSqSum_[i] > 0.0 ) {
1120  fNorm_[i] = TMath::Sqrt( 1.0 / ( fSqSum_[i] ) );
1121  }
1122  }
1123 }
1124 
1125 std::vector<std::pair<Double_t, Double_t>> LauIsobarDynamics::formGapsFromRegions(
1126  const std::vector<std::pair<Double_t, Double_t>>& regions,
1127  const Double_t min,
1128  const Double_t max ) const
1129 {
1130  std::vector<std::pair<Double_t, Double_t>> gaps( regions.size() + 1, std::make_pair( 0., 0. ) );
1131 
1132  // Given some narrow resonance regions, find the regions that correspond to the gaps between them
1133 
1134  gaps[0].first = min;
1135 
1136  for ( UInt_t i = 0; i < regions.size(); ++i ) {
1137  gaps[i].second = regions[i].first;
1138  gaps[i + 1].first = regions[i].second;
1139  }
1140 
1141  gaps[gaps.size() - 1].second = max;
1142 
1143  return gaps;
1144 }
1145 
1146 void LauIsobarDynamics::cullNullRegions( std::vector<LauDPPartialIntegralInfo*>& regions ) const
1147 {
1148  LauDPPartialIntegralInfo* tmp( 0 );
1149  regions.erase( std::remove( regions.begin(), regions.end(), tmp ), regions.end() );
1150 }
1151 
1152 void LauIsobarDynamics::correctDPOverlap( std::vector<std::pair<Double_t, Double_t>>& regions,
1153  const std::vector<Double_t>& binnings ) const
1154 {
1155  if ( regions.empty() ) {
1156  return;
1157  }
1158 
1159  // If the regions overlap, ensure that the one with the finest binning takes precedence (i.e., extends its full width)
1160 
1161  for ( UInt_t i = 0; i < regions.size() - 1; ++i ) {
1162  if ( regions[i + 1].first <= regions[i].second ) {
1163  if ( ( binnings[i] < binnings[i + 1] ) ) {
1164  regions[i + 1] = std::make_pair( regions[i].second, regions[i + 1].second );
1165  } else {
1166  regions[i] = std::make_pair( regions[i].first, regions[i + 1].first );
1167  }
1168  }
1169  }
1170 }
1171 
1172 std::vector<LauDPPartialIntegralInfo*> LauIsobarDynamics::m13IntegrationRegions(
1173  const std::vector<std::pair<Double_t, Double_t>>& m13Regions,
1174  const std::vector<std::pair<Double_t, Double_t>>& m23Regions,
1175  const std::vector<Double_t>& m13Binnings,
1176  const Double_t precision,
1177  const Double_t defaultBinning ) const
1178 {
1179  // Create integration regions for all narrow resonances in m13 except for the overlaps with narrow resonances in m23
1180  std::vector<LauDPPartialIntegralInfo*> integrationRegions;
1181 
1182  const Double_t m23Min = kinematics_->getm23Min();
1183  const Double_t m23Max = kinematics_->getm23Max();
1184 
1185  // Loop over narrow resonances in m13
1186  for ( UInt_t m13i = 0; m13i < m13Regions.size(); ++m13i ) {
1187 
1188  const Double_t m13Binning = m13Binnings[m13i];
1189 
1190  const Double_t resMin13 = m13Regions[m13i].first;
1191  const Double_t resMax13 = m13Regions[m13i].second;
1192 
1193  // Initialise to the full height of the DP in case there are no narrow resonances in m23
1194  Double_t lastResMax23 = m23Min;
1195 
1196  // Loop over narrow resonances in m23
1197  for ( UInt_t m23i = 0; m23i < m23Regions.size(); m23i++ ) {
1198 
1199  const Double_t resMin23 = m23Regions[m23i].first;
1200  const Double_t resMax23 = m23Regions[m23i].second;
1201 
1202  // For the first entry, add the area between m23 threshold and this first entry
1203  if ( m23i == 0 ) {
1204  integrationRegions.push_back( this->newDPIntegrationRegion( resMin13,
1205  resMax13,
1206  m23Min,
1207  resMin23,
1208  m13Binning,
1209  defaultBinning,
1210  precision,
1211  nAmp_,
1212  nIncohAmp_ ) );
1213  }
1214 
1215  // For all entries except the last one, add the area between this and the next entry
1216  if ( m23i != ( m23Regions.size() - 1 ) ) {
1217  const Double_t nextResMin23 = m23Regions[m23i + 1].first;
1218  integrationRegions.push_back( this->newDPIntegrationRegion( resMin13,
1219  resMax13,
1220  resMax23,
1221  nextResMin23,
1222  m13Binning,
1223  defaultBinning,
1224  precision,
1225  nAmp_,
1226  nIncohAmp_ ) );
1227  } else {
1228  lastResMax23 = resMax23;
1229  }
1230  }
1231 
1232  // Add the area between the last entry and the maximum m23 (which could be the whole strip if there are no entries in m23Regions)
1233  integrationRegions.push_back( this->newDPIntegrationRegion( resMin13,
1234  resMax13,
1235  lastResMax23,
1236  m23Max,
1237  m13Binning,
1238  defaultBinning,
1239  precision,
1240  nAmp_,
1241  nIncohAmp_ ) );
1242  }
1243 
1244  return integrationRegions;
1245 }
1246 
1247 std::vector<LauDPPartialIntegralInfo*> LauIsobarDynamics::m23IntegrationRegions(
1248  const std::vector<std::pair<Double_t, Double_t>>& m13Regions,
1249  const std::vector<std::pair<Double_t, Double_t>>& m23Regions,
1250  const std::vector<Double_t>& m13Binnings,
1251  const std::vector<Double_t>& m23Binnings,
1252  const Double_t precision,
1253  const Double_t defaultBinning ) const
1254 {
1255  // Create integration regions for all narrow resonances in m23 (including the overlap regions with m13 narrow resonances)
1256  std::vector<LauDPPartialIntegralInfo*> integrationRegions;
1257 
1258  const Double_t m13Min = kinematics_->getm13Min();
1259  const Double_t m13Max = kinematics_->getm13Max();
1260 
1261  // Loop over narrow resonances in m23
1262  for ( UInt_t m23i = 0; m23i < m23Regions.size(); m23i++ ) {
1263 
1264  const Double_t m23Binning = m23Binnings[m23i];
1265 
1266  const Double_t resMin23 = m23Regions[m23i].first;
1267  const Double_t resMax23 = m23Regions[m23i].second;
1268 
1269  // Initialise to the full width of the DP in case there are no narrow resonances in m13
1270  Double_t lastResMax13 = m13Min;
1271 
1272  // Loop over narrow resonances in m13
1273  for ( UInt_t m13i = 0; m13i < m13Regions.size(); m13i++ ) {
1274 
1275  const Double_t m13Binning = m13Binnings[m23i];
1276 
1277  const Double_t resMin13 = m13Regions[m13i].first;
1278  const Double_t resMax13 = m13Regions[m13i].second;
1279 
1280  // Overlap region (only needed in m23)
1281  integrationRegions.push_back( this->newDPIntegrationRegion( resMin13,
1282  resMax13,
1283  resMin23,
1284  resMax23,
1285  m13Binning,
1286  m23Binning,
1287  precision,
1288  nAmp_,
1289  nIncohAmp_ ) );
1290 
1291  // For the first entry, add the area between m13 threshold and this first entry
1292  if ( m13i == 0 ) {
1293  integrationRegions.push_back( this->newDPIntegrationRegion( m13Min,
1294  resMin13,
1295  resMin23,
1296  resMax23,
1297  defaultBinning,
1298  m23Binning,
1299  precision,
1300  nAmp_,
1301  nIncohAmp_ ) );
1302  }
1303 
1304  // For all entries except the last one, add the area between this and the next entry
1305  if ( m13i != m13Regions.size() - 1 ) {
1306  const Double_t nextResMin13 = m23Regions[m13i + 1].first;
1307  integrationRegions.push_back( this->newDPIntegrationRegion( resMax13,
1308  nextResMin13,
1309  resMin23,
1310  resMax23,
1311  defaultBinning,
1312  m23Binning,
1313  precision,
1314  nAmp_,
1315  nIncohAmp_ ) );
1316  } else {
1317  lastResMax13 = resMax13;
1318  }
1319  }
1320 
1321  // Add the area between the last entry and the maximum m13 (which could be the whole strip if there are no entries in m13Regions)
1322  integrationRegions.push_back( this->newDPIntegrationRegion( lastResMax13,
1323  m13Max,
1324  resMin23,
1325  resMax23,
1326  defaultBinning,
1327  m23Binning,
1328  precision,
1329  nAmp_,
1330  nIncohAmp_ ) );
1331  }
1332 
1333  return integrationRegions;
1334 }
1335 
1337  const Double_t maxm13,
1338  const Double_t minm23,
1339  const Double_t maxm23,
1340  const Double_t m13BinWidth,
1341  const Double_t m23BinWidth,
1342  const Double_t precision,
1343  const UInt_t nAmp,
1344  const UInt_t nIncohAmp ) const
1345 {
1346  const UInt_t nm13Points = static_cast<UInt_t>( ( maxm13 - minm13 ) / m13BinWidth );
1347  const UInt_t nm23Points = static_cast<UInt_t>( ( maxm23 - minm23 ) / m23BinWidth );
1348 
1349  // If we would create a region with no interior points, just return a null pointer
1350  if ( nm13Points == 0 || nm23Points == 0 ) {
1351  return 0;
1352  }
1353 
1354  return new LauDPPartialIntegralInfo( minm13,
1355  maxm13,
1356  minm23,
1357  maxm23,
1358  m13BinWidth,
1359  m23BinWidth,
1360  precision,
1361  nAmp,
1362  nIncohAmp );
1363 }
1364 
1366 {
1367  if ( ! dpPartialIntegralInfo_.empty() ) {
1368  std::cerr << "ERROR in LauIsobarDynamics::calcDPNormalisationScheme : Scheme already stored!"
1369  << std::endl;
1370  return;
1371  }
1372 
1373  // The precision for the Gauss-Legendre weights
1374  const Double_t precision( 1e-6 );
1375 
1376  // Get the rectangle that encloses the DP
1377  const Double_t minm13 = kinematics_->getm13Min();
1378  const Double_t maxm13 = kinematics_->getm13Max();
1379  const Double_t minm23 = kinematics_->getm23Min();
1380  const Double_t maxm23 = kinematics_->getm23Max();
1381  const Double_t minm12 = kinematics_->getm12Min();
1382  const Double_t maxm12 = kinematics_->getm12Max();
1383 
1384  // Find out whether we have narrow resonances in the DP (defined here as width < 20 MeV).
1385  std::vector<std::pair<Double_t, Double_t>> m13NarrowRes;
1386  std::vector<std::pair<Double_t, Double_t>> m23NarrowRes;
1387  std::vector<std::pair<Double_t, Double_t>> m12NarrowRes;
1388 
1389  // Rho-omega mixing models implicitly contains omega(782) model, but width is of rho(770) - handle as a special case
1390  LauResonanceMaker& resonanceMaker = LauResonanceMaker::get();
1391  LauResonanceInfo* omega_info = resonanceMaker.getResInfo( "omega(782)" );
1392  const Double_t omegaMass = ( omega_info != 0 ) ? omega_info->getMass()->unblindValue() : 0.78265;
1393  const Double_t omegaWidth = ( omega_info != 0 ) ? omega_info->getWidth()->unblindValue()
1394  : 0.00849;
1395 
1396  for ( std::vector<LauAbsResonance*>::const_iterator iter = sigResonances_.begin();
1397  iter != sigResonances_.end();
1398  ++iter ) {
1399 
1400  LauAbsResonance::LauResonanceModel model = ( *iter )->getResonanceModel();
1401  const TString& name = ( *iter )->getResonanceName();
1402  Int_t pair = ( *iter )->getPairInt();
1403  Double_t mass = ( *iter )->getMass();
1404  Double_t width = ( *iter )->getWidth();
1405 
1409  mass = omegaMass;
1410  width = omegaWidth;
1411  }
1412 
1413  if ( width > narrowWidth_ || width <= 0.0 ) {
1414  continue;
1415  }
1416 
1417  std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Found narrow resonance: "
1418  << name << ", mass = " << mass << ", width = " << width << ", pair int = " << pair
1419  << std::endl;
1420  if ( pair == 1 ) {
1421  if ( mass < minm23 || mass > maxm23 ) {
1422  std::cout << std::string( 53, ' ' )
1423  << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration"
1424  << std::endl;
1425  } else {
1426  m23NarrowRes.push_back( std::make_pair( mass, width ) );
1427  if ( fullySymmetricDP_ ) {
1428  m13NarrowRes.push_back( std::make_pair( mass, width ) );
1429  m12NarrowRes.push_back( std::make_pair( mass, width ) );
1430  } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) {
1431  m13NarrowRes.push_back( std::make_pair( mass, width ) );
1432  }
1433  }
1434  } else if ( pair == 2 ) {
1435  if ( mass < minm13 || mass > maxm13 ) {
1436  std::cout << std::string( 53, ' ' )
1437  << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration"
1438  << std::endl;
1439  } else {
1440  m13NarrowRes.push_back( std::make_pair( mass, width ) );
1441  if ( fullySymmetricDP_ ) {
1442  m23NarrowRes.push_back( std::make_pair( mass, width ) );
1443  m12NarrowRes.push_back( std::make_pair( mass, width ) );
1444  } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) {
1445  m23NarrowRes.push_back( std::make_pair( mass, width ) );
1446  }
1447  }
1448  } else if ( pair == 3 ) {
1449  if ( mass < minm12 || mass > maxm12 ) {
1450  std::cout << std::string( 53, ' ' )
1451  << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration"
1452  << std::endl;
1453  } else {
1454  m12NarrowRes.push_back( std::make_pair( mass, width ) );
1455  if ( fullySymmetricDP_ ) {
1456  m13NarrowRes.push_back( std::make_pair( mass, width ) );
1457  m12NarrowRes.push_back( std::make_pair( mass, width ) );
1458  }
1459  }
1460  } else {
1461  std::cerr << "WARNING in LauIsobarDynamics::calcDPNormalisationScheme : strange pair integer, "
1462  << pair << ", for resonance \"" << ( *iter )->getResonanceName() << std::endl;
1463  }
1464  }
1465 
1466  for ( std::vector<LauAbsIncohRes*>::const_iterator iter = sigIncohResonances_.begin();
1467  iter != sigIncohResonances_.end();
1468  ++iter ) {
1469 
1470  const TString& name = ( *iter )->getResonanceName();
1471  Int_t pair = ( *iter )->getPairInt();
1472  Double_t mass = ( *iter )->getMass();
1473  Double_t width = ( *iter )->getWidth();
1474 
1475  if ( width > narrowWidth_ || width == 0.0 ) {
1476  continue;
1477  }
1478 
1479  std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Found narrow resonance: "
1480  << name << ", mass = " << mass << ", width = " << width << ", pair int = " << pair
1481  << std::endl;
1482 
1483  if ( pair == 1 ) {
1484  if ( mass < minm23 || mass > maxm23 ) {
1485  std::cout << std::string( 53, ' ' )
1486  << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration"
1487  << std::endl;
1488  } else {
1489  m23NarrowRes.push_back( std::make_pair( mass, width ) );
1490  if ( fullySymmetricDP_ ) {
1491  m13NarrowRes.push_back( std::make_pair( mass, width ) );
1492  m12NarrowRes.push_back( std::make_pair( mass, width ) );
1493  } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) {
1494  m13NarrowRes.push_back( std::make_pair( mass, width ) );
1495  }
1496  }
1497  } else if ( pair == 2 ) {
1498  if ( mass < minm13 || mass > maxm13 ) {
1499  std::cout << std::string( 53, ' ' )
1500  << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration"
1501  << std::endl;
1502  } else {
1503  m13NarrowRes.push_back( std::make_pair( mass, width ) );
1504  if ( fullySymmetricDP_ ) {
1505  m23NarrowRes.push_back( std::make_pair( mass, width ) );
1506  m12NarrowRes.push_back( std::make_pair( mass, width ) );
1507  } else if ( symmetricalDP_ || ( flavConjDP_ && forceSymmetriseIntegration_ ) ) {
1508  m23NarrowRes.push_back( std::make_pair( mass, width ) );
1509  }
1510  }
1511  } else if ( pair == 3 ) {
1512  if ( mass < minm12 || mass > maxm12 ) {
1513  std::cout << std::string( 53, ' ' )
1514  << ": But its pole is outside the kinematically allowed range, so will not consider it narrow for the purposes of integration"
1515  << std::endl;
1516  } else {
1517  m12NarrowRes.push_back( std::make_pair( mass, width ) );
1518  if ( fullySymmetricDP_ ) {
1519  m13NarrowRes.push_back( std::make_pair( mass, width ) );
1520  m12NarrowRes.push_back( std::make_pair( mass, width ) );
1521  }
1522  }
1523  } else {
1524  std::cerr << "WARNING in LauIsobarDynamics::calcDPNormalisationScheme : strange pair integer, "
1525  << pair << ", for resonance \"" << ( *iter )->getResonanceName() << std::endl;
1526  }
1527  }
1528 
1529  // Depending on how many narrow resonances we have and where they are
1530  // we adopt different approaches
1531  if ( ! m12NarrowRes.empty() ) {
1532 
1533  // We have at least one narrow resonance in m12
1534  // Switch to using the square DP for the integration
1535  // TODO - for the time being just use a single, reasonably fine by default and tunable, grid
1536  // - can later consider whether there's a need to split up the mPrime axis into regions around particularly narrow resonances in m12
1537  // - but it seems that this isn't really needed since even the default tune gives a good resolution for most narrow resonances such as phi / chi_c0
1538  std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : One or more narrow resonances found in m12, integrating over whole square Dalitz plot with bin widths of "
1539  << mPrimeBinWidth_ << " in mPrime and " << thPrimeBinWidth_ << " in thetaPrime..."
1540  << std::endl;
1541 
1542  // Make sure that the kinematics will calculate the square DP co-ordinates
1543  if ( ! kinematics_->squareDP() ) {
1544  std::cerr << "WARNING in LauIsobarDynamics::calcDPNormalisationScheme : forcing kinematics to calculate the required square DP co-ordinates"
1545  << std::endl;
1546  kinematics_->squareDP( kTRUE );
1547  }
1548 
1550  1.0,
1551  0.0,
1552  1.0,
1555  precision,
1556  nAmp_,
1557  nIncohAmp_,
1558  kTRUE,
1559  kinematics_ ) );
1560 
1561  } else if ( m13NarrowRes.empty() && m23NarrowRes.empty() ) {
1562 
1563  // There are no narrow resonances, so we just do a single grid over the whole DP
1564  std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : No narrow resonances found, integrating over whole Dalitz plot..."
1565  << std::endl;
1566  dpPartialIntegralInfo_.push_back( new LauDPPartialIntegralInfo( minm13,
1567  maxm13,
1568  minm23,
1569  maxm23,
1570  m13BinWidth_,
1571  m23BinWidth_,
1572  precision,
1573  nAmp_,
1574  nIncohAmp_ ) );
1575 
1576  } else {
1577 
1578  // Get regions in that correspond to narrow resonances in m13 and m23, and correct for overlaps in each dimension (to use the finest binning)
1579 
1580  // Sort resonances by ascending mass to calculate regions properly
1581  std::sort( m13NarrowRes.begin(), m13NarrowRes.end() );
1582  std::sort( m23NarrowRes.begin(), m23NarrowRes.end() );
1583 
1584  // For each narrow resonance in m13, determine the corresponding window and its binning
1585  std::vector<std::pair<Double_t, Double_t>> m13Regions;
1586  std::vector<Double_t> m13Binnings;
1587 
1588  for ( std::vector<std::pair<Double_t, Double_t>>::const_iterator iter = m13NarrowRes.begin();
1589  iter != m13NarrowRes.end();
1590  ++iter ) {
1591  Double_t mass = iter->first;
1592  Double_t width = iter->second;
1593 
1594  Double_t regionBegin = mass - 5.0 * width;
1595  Double_t regionEnd = mass + 5.0 * width;
1596  Double_t binning = width / binningFactor_;
1597 
1598  // check if we ought to extend the region to the edge of the phase space (in either direction)
1599  if ( regionBegin < ( minm13 + 50.0 * m13BinWidth_ ) ) {
1600  std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m13 = "
1601  << mass << " is close to threshold, extending integration region"
1602  << std::endl;
1603  regionBegin = minm13;
1604  }
1605  if ( regionEnd > ( maxm13 - 50.0 * m13BinWidth_ ) ) {
1606  std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m13 = "
1607  << mass
1608  << " is close to upper edge of phase space, extending integration region"
1609  << std::endl;
1610  regionEnd = maxm13;
1611  }
1612 
1613  m13Regions.push_back( std::make_pair( regionBegin, regionEnd ) );
1614  m13Binnings.push_back( binning );
1615  }
1616 
1617  // For each narrow resonance in m23, determine the corresponding window and its binning
1618  std::vector<std::pair<Double_t, Double_t>> m23Regions;
1619  std::vector<Double_t> m23Binnings;
1620 
1621  for ( std::vector<std::pair<Double_t, Double_t>>::const_iterator iter = m23NarrowRes.begin();
1622  iter != m23NarrowRes.end();
1623  ++iter ) {
1624  Double_t mass = iter->first;
1625  Double_t width = iter->second;
1626 
1627  Double_t regionBegin = mass - 5.0 * width;
1628  Double_t regionEnd = mass + 5.0 * width;
1629  Double_t binning = width / binningFactor_;
1630 
1631  // check if we ought to extend the region to the edge of the phase space (in either direction)
1632  if ( regionBegin < ( minm23 + 50.0 * m23BinWidth_ ) ) {
1633  std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m23 = "
1634  << mass << " is close to threshold, extending integration region"
1635  << std::endl;
1636  regionBegin = minm23;
1637  }
1638  if ( regionEnd > ( maxm23 - 50.0 * m23BinWidth_ ) ) {
1639  std::cout << "INFO in LauIsobarDynamics::calcDPNormalisationScheme : Resonance at m23 = "
1640  << mass
1641  << " is close to upper edge of phase space, extending integration region"
1642  << std::endl;
1643  regionEnd = maxm23;
1644  }
1645 
1646  m23Regions.push_back( std::make_pair( regionBegin, regionEnd ) );
1647  m23Binnings.push_back( binning );
1648  }
1649 
1650  // Sort out overlaps between regions in the same mass pairing
1651  this->correctDPOverlap( m13Regions, m13Binnings );
1652  this->correctDPOverlap( m23Regions, m23Binnings );
1653 
1654  // Get the narrow resonance regions plus any overlap region
1655  std::vector<LauDPPartialIntegralInfo*> fineScheme13 =
1656  this->m13IntegrationRegions( m13Regions, m23Regions, m13Binnings, precision, m13BinWidth_ );
1657  std::vector<LauDPPartialIntegralInfo*> fineScheme23 =
1658  this->m23IntegrationRegions( m13Regions,
1659  m23Regions,
1660  m13Binnings,
1661  m23Binnings,
1662  precision,
1663  m23BinWidth_ );
1664 
1665  // Get coarse regions by calculating the gaps between the
1666  // narrow resonances and using the same functions to create
1667  // the integration grid object for each
1668  std::vector<std::pair<Double_t, Double_t>> coarseRegions =
1669  this->formGapsFromRegions( m13Regions, minm13, maxm13 );
1670  std::vector<Double_t> coarseBinning( fineScheme13.size() + 1, m13BinWidth_ );
1671  std::vector<LauDPPartialIntegralInfo*> coarseScheme =
1672  this->m13IntegrationRegions( coarseRegions,
1673  m23Regions,
1674  coarseBinning,
1675  precision,
1676  m13BinWidth_ );
1677 
1679  fineScheme13.begin(),
1680  fineScheme13.end() );
1682  fineScheme23.begin(),
1683  fineScheme23.end() );
1685  coarseScheme.begin(),
1686  coarseScheme.end() );
1687 
1688  // Remove any null pointer entries in the integral list
1689  // (that are produced when an integration region with no
1690  // interior points is defined)
1692  }
1693 
1694  normalizationSchemeDone_ = kTRUE;
1695 }
1696 
1697 void LauIsobarDynamics::setIntegralBinWidths( const Double_t m13BinWidth,
1698  const Double_t m23BinWidth,
1699  const Double_t mPrimeBinWidth,
1700  const Double_t thPrimeBinWidth )
1701 {
1702  // Set the bin widths for the m13 vs m23 integration grid
1703  m13BinWidth_ = m13BinWidth;
1704  m23BinWidth_ = m23BinWidth;
1705 
1706  // Set the bin widths for the m' vs theta' integration grid
1707  mPrimeBinWidth_ = mPrimeBinWidth;
1708  thPrimeBinWidth_ = thPrimeBinWidth;
1709 }
1710 
1712 {
1713  // Calculate the integrals for all parts of the amplitude in the given region of the DP
1714 
1715  const Bool_t squareDP = intInfo->getSquareDP();
1716  const UInt_t nm13Points = intInfo->getnm13Points();
1717  const UInt_t nm23Points = intInfo->getnm23Points();
1718 
1719  //Double_t dpArea(0.0);
1720  for ( UInt_t i = 0; i < nm13Points; ++i ) {
1721 
1722  const Double_t m13 = intInfo->getM13Value( i );
1723  const Double_t m13Sq = m13 * m13;
1724 
1725  for ( UInt_t j = 0; j < nm23Points; ++j ) {
1726 
1727  const Double_t m23 = intInfo->getM23Value( j );
1728  const Double_t m23Sq = m23 * m23;
1729  const Double_t weight = intInfo->getWeight( i, j );
1730 
1731  // Calculate the integral contributions for each resonance.
1732  // Only points within the DP area contribute.
1733  // This also calculates the total DP area as a check.
1734  // NB if squareDP is true, m13 and m23 are actually mPrime and thetaPrime
1735  Bool_t withinDP = squareDP ? kinematics_->withinSqDPLimits( m13, m23 )
1736  : kinematics_->withinDPLimits( m13Sq, m23Sq );
1737  if ( withinDP == kTRUE ) {
1738 
1739  if ( squareDP ) {
1740  // NB m13 and m23 are actually mPrime and thetaPrime
1741  kinematics_->updateSqDPKinematics( m13, m23 );
1742  } else {
1743  kinematics_->updateKinematics( m13Sq, m23Sq );
1744  }
1745 
1746  this->calculateAmplitudes( intInfo, i, j );
1747 
1748  this->addGridPointToIntegrals( weight );
1749 
1750  // Increment total DP area
1751  //dpArea += weight;
1752  }
1753 
1754  } // j weights loop
1755  } // i weights loop
1756 
1757  // Print out DP area to check whether we have a sensible output
1758  //std::cout<<" : dpArea = "<<dpArea<<std::endl;
1759 }
1760 
1762  const UInt_t m13Point,
1763  const UInt_t m23Point )
1764 {
1765  const std::set<UInt_t>::const_iterator intEnd = integralsToBeCalculated_.end();
1766 
1767  for ( UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp ) {
1768 
1769  if ( integralsToBeCalculated_.find( iAmp ) != intEnd ) {
1770  // Calculate the dynamics for this resonance
1771  ff_[iAmp] = this->resAmp( iAmp );
1772 
1773  // Store the new value in the integration info object
1774  intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] );
1775  } else {
1776  // Retrieve the cached value of the amplitude
1777  ff_[iAmp] = intInfo->getAmplitude( m13Point, m23Point, iAmp );
1778  }
1779  }
1780 
1781  for ( UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp ) {
1782 
1783  if ( integralsToBeCalculated_.find( iAmp + nAmp_ ) != intEnd ) {
1784  // Calculate the dynamics for this resonance
1785  incohInten_[iAmp] = this->incohResAmp( iAmp );
1786 
1787  // Store the new value in the integration info object
1788  intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] );
1789  } else {
1790  // Retrieve the cached value of the amplitude
1791  incohInten_[iAmp] = intInfo->getIntensity( m13Point, m23Point, iAmp );
1792  }
1793  }
1794 
1795  // If symmetric, do as above with flipped kinematics and add to amplitude
1796  // (No need to retrive the cache if this was done in the first case)
1797 
1798  if ( symmetricalDP_ == kTRUE ) {
1800 
1801  for ( UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp ) {
1802 
1803  if ( ( integralsToBeCalculated_.find( iAmp ) != intEnd ) &&
1804  ! sigResonances_[iAmp]->preSymmetrised() ) {
1805  // Calculate the dynamics for this resonance
1806  ff_[iAmp] += this->resAmp( iAmp );
1807 
1808  // Store the new value in the integration info object
1809  intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] );
1810  }
1811  }
1812 
1813  for ( UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp ) {
1814 
1815  if ( ( integralsToBeCalculated_.find( iAmp + nAmp_ ) != intEnd ) &&
1816  ! sigResonances_[iAmp]->preSymmetrised() ) {
1817  // Calculate the dynamics for this resonance
1818  incohInten_[iAmp] += this->incohResAmp( iAmp );
1819 
1820  // Store the new value in the integration info object
1821  intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] );
1822  }
1823  }
1824 
1826  }
1827 
1828  if ( fullySymmetricDP_ == kTRUE ) {
1829  // rotate and evaluate
1831  for ( UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp ) {
1832  if ( ( integralsToBeCalculated_.find( iAmp ) != intEnd ) &&
1833  ! sigResonances_[iAmp]->preSymmetrised() ) {
1834  // Calculate the dynamics for this resonance
1835  ff_[iAmp] += this->resAmp( iAmp );
1836  // Store the new value in the integration info object
1837  intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] );
1838  }
1839  }
1840  for ( UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp ) {
1841  if ( ( integralsToBeCalculated_.find( iAmp + nAmp_ ) != intEnd ) &&
1842  ! sigResonances_[iAmp]->preSymmetrised() ) {
1843  // Calculate the dynamics for this resonance
1844  incohInten_[iAmp] += this->incohResAmp( iAmp );
1845  // Store the new value in the integration info object
1846  intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] );
1847  }
1848  }
1849 
1850  // rotate and evaluate
1852  for ( UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp ) {
1853  if ( ( integralsToBeCalculated_.find( iAmp ) != intEnd ) &&
1854  ! sigResonances_[iAmp]->preSymmetrised() ) {
1855  // Calculate the dynamics for this resonance
1856  ff_[iAmp] += this->resAmp( iAmp );
1857  // Store the new value in the integration info object
1858  intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] );
1859  }
1860  }
1861  for ( UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp ) {
1862  if ( ( integralsToBeCalculated_.find( iAmp + nAmp_ ) != intEnd ) &&
1863  ! sigResonances_[iAmp]->preSymmetrised() ) {
1864  // Calculate the dynamics for this resonance
1865  incohInten_[iAmp] += this->incohResAmp( iAmp );
1866  // Store the new value in the integration info object
1867  intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] );
1868  }
1869  }
1870 
1871  // rotate, flip and evaluate
1874  for ( UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp ) {
1875  if ( ( integralsToBeCalculated_.find( iAmp ) != intEnd ) &&
1876  ! sigResonances_[iAmp]->preSymmetrised() ) {
1877  // Calculate the dynamics for this resonance
1878  ff_[iAmp] += this->resAmp( iAmp );
1879  // Store the new value in the integration info object
1880  intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] );
1881  }
1882  }
1883  for ( UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp ) {
1884  if ( ( integralsToBeCalculated_.find( iAmp + nAmp_ ) != intEnd ) &&
1885  ! sigResonances_[iAmp]->preSymmetrised() ) {
1886  // Calculate the dynamics for this resonance
1887  incohInten_[iAmp] += this->incohResAmp( iAmp );
1888  // Store the new value in the integration info object
1889  intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] );
1890  }
1891  }
1892 
1893  // rotate and evaluate
1895  for ( UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp ) {
1896  if ( ( integralsToBeCalculated_.find( iAmp ) != intEnd ) &&
1897  ! sigResonances_[iAmp]->preSymmetrised() ) {
1898  // Calculate the dynamics for this resonance
1899  ff_[iAmp] += this->resAmp( iAmp );
1900  // Store the new value in the integration info object
1901  intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] );
1902  }
1903  }
1904  for ( UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp ) {
1905  if ( ( integralsToBeCalculated_.find( iAmp + nAmp_ ) != intEnd ) &&
1906  ! sigResonances_[iAmp]->preSymmetrised() ) {
1907  // Calculate the dynamics for this resonance
1908  incohInten_[iAmp] += this->incohResAmp( iAmp );
1909  // Store the new value in the integration info object
1910  intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] );
1911  }
1912  }
1913 
1914  // rotate and evaluate
1916  for ( UInt_t iAmp = 0; iAmp < nAmp_; ++iAmp ) {
1917  if ( ( integralsToBeCalculated_.find( iAmp ) != intEnd ) &&
1918  ! sigResonances_[iAmp]->preSymmetrised() ) {
1919  // Calculate the dynamics for this resonance
1920  ff_[iAmp] += this->resAmp( iAmp );
1921  // Store the new value in the integration info object
1922  intInfo->storeAmplitude( m13Point, m23Point, iAmp, ff_[iAmp] );
1923  }
1924  }
1925  for ( UInt_t iAmp = 0; iAmp < nIncohAmp_; ++iAmp ) {
1926  if ( ( integralsToBeCalculated_.find( iAmp + nAmp_ ) != intEnd ) &&
1927  ! sigResonances_[iAmp]->preSymmetrised() ) {
1928  // Calculate the dynamics for this resonance
1929  incohInten_[iAmp] += this->incohResAmp( iAmp );
1930  // Store the new value in the integration info object
1931  intInfo->storeIntensity( m13Point, m23Point, iAmp, incohInten_[iAmp] );
1932  }
1933  }
1934 
1935  // rotate and flip to get us back to where we started
1938  }
1939 
1940  // If we haven't cached the data, then we need to find out the efficiency.
1941  eff_ = this->retrieveEfficiency();
1942 
1943  intInfo->storeEfficiency( m13Point, m23Point, eff_ );
1944 }
1945 
1947 {
1948  std::set<UInt_t>::const_iterator iter = integralsToBeCalculated_.begin();
1949  const std::set<UInt_t>::const_iterator intEnd = integralsToBeCalculated_.end();
1950 
1951  for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter ) {
1952 
1953  // Calculate the dynamics for this resonance
1954  if ( *iter < nAmp_ ) {
1955  ff_[*iter] = this->resAmp( *iter );
1956  } else {
1957  incohInten_[*iter - nAmp_] = this->incohResAmp( *iter - nAmp_ );
1958  }
1959  }
1960 
1961  if ( symmetricalDP_ == kTRUE ) {
1963 
1964  for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter ) {
1965 
1966  // Calculate the dynamics for this resonance
1967  if ( *iter < nAmp_ && ! sigResonances_[*iter]->preSymmetrised() ) {
1968  ff_[*iter] += this->resAmp( *iter );
1969  } else if ( *iter >= nAmp_ && ! sigResonances_[*iter - nAmp_]->preSymmetrised() ) {
1970  incohInten_[*iter - nAmp_] += this->incohResAmp( *iter - nAmp_ );
1971  }
1972  }
1973 
1975  }
1976 
1977  if ( fullySymmetricDP_ == kTRUE ) {
1978  // rotate and evaluate
1980  for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter ) {
1981  if ( *iter < nAmp_ && ! sigResonances_[*iter]->preSymmetrised() ) {
1982  ff_[*iter] += this->resAmp( *iter );
1983  } else if ( *iter >= nAmp_ && ! sigResonances_[*iter - nAmp_]->preSymmetrised() ) {
1984  incohInten_[*iter - nAmp_] += this->incohResAmp( *iter - nAmp_ );
1985  }
1986  }
1987 
1988  // rotate and evaluate
1990  for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter ) {
1991  if ( *iter < nAmp_ && ! sigResonances_[*iter]->preSymmetrised() ) {
1992  ff_[*iter] += this->resAmp( *iter );
1993  } else if ( *iter >= nAmp_ && ! sigResonances_[*iter - nAmp_]->preSymmetrised() ) {
1994  incohInten_[*iter - nAmp_] += this->incohResAmp( *iter - nAmp_ );
1995  }
1996  }
1997 
1998  // rotate, flip and evaluate
2001  for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter ) {
2002  if ( *iter < nAmp_ && ! sigResonances_[*iter]->preSymmetrised() ) {
2003  ff_[*iter] += this->resAmp( *iter );
2004  } else if ( *iter >= nAmp_ && ! sigResonances_[*iter - nAmp_]->preSymmetrised() ) {
2005  incohInten_[*iter - nAmp_] += this->incohResAmp( *iter - nAmp_ );
2006  }
2007  }
2008 
2009  // rotate and evaluate
2011  for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter ) {
2012  if ( *iter < nAmp_ && ! sigResonances_[*iter]->preSymmetrised() ) {
2013  ff_[*iter] += this->resAmp( *iter );
2014  } else if ( *iter >= nAmp_ && ! sigResonances_[*iter - nAmp_]->preSymmetrised() ) {
2015  incohInten_[*iter - nAmp_] += this->incohResAmp( *iter - nAmp_ );
2016  }
2017  }
2018 
2019  // rotate and evaluate
2021  for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter ) {
2022  if ( *iter < nAmp_ && ! sigResonances_[*iter]->preSymmetrised() ) {
2023  ff_[*iter] += this->resAmp( *iter );
2024  } else if ( *iter >= nAmp_ && ! sigResonances_[*iter - nAmp_]->preSymmetrised() ) {
2025  incohInten_[*iter - nAmp_] += this->incohResAmp( *iter - nAmp_ );
2026  }
2027  }
2028 
2029  // rotate and flip to get us back to where we started
2032  }
2033 
2034  // If we haven't cached the data, then we need to find out the efficiency.
2035  eff_ = this->retrieveEfficiency();
2036 }
2037 
2038 void LauIsobarDynamics::calcTotalAmp( const Bool_t useEff )
2039 {
2040  // Reset the total amplitude to zero
2041  totAmp_.zero();
2042 
2043  // Loop over all signal amplitudes
2044  LauComplex ATerm;
2045  for ( UInt_t i = 0; i < nAmp_; ++i ) {
2046 
2047  // Get the partial complex amplitude - (mag, phase)*(resonance dynamics)
2048  ATerm = Amp_[i] * ff_[i];
2049 
2050  // Scale this contribution by its relative normalisation w.r.t. the whole dynamics
2051  ATerm.rescale( fNorm_[i] );
2052 
2053  // Add this partial amplitude to the sum
2054  totAmp_ += ATerm;
2055 
2056  } // Loop over amplitudes
2057 
2058  // |Sum of partial amplitudes|^2
2059  ASq_ = totAmp_.abs2();
2060 
2061  for ( UInt_t i = 0; i < nIncohAmp_; ++i ) {
2062 
2063  // Get the partial complex amplitude - (mag, phase)
2064  ATerm = Amp_[i + nAmp_];
2065 
2066  // Scale this contribution by its relative normalisation w.r.t. the whole dynamics
2067  ATerm.rescale( fNorm_[i + nAmp_] );
2068 
2069  // Add this partial amplitude to the sum
2070  ASq_ += ATerm.abs2() * incohInten_[i];
2071  }
2072 
2073  // Apply the efficiency correction for this event.
2074  // Multiply the amplitude squared sum by the DP efficiency
2075  if ( useEff ) {
2076  ASq_ *= eff_;
2077  }
2078 }
2079 
2080 void LauIsobarDynamics::addGridPointToIntegrals( const Double_t weight )
2081 {
2082  // Combine the Gauss-Legendre weight with the efficiency
2083  const Double_t effWeight = eff_ * weight;
2084 
2085  LauComplex fifjEffSumTerm;
2086  LauComplex fifjSumTerm;
2087 
2088  // Calculates the half-matrix of amplitude-squared and interference
2089  // terms (dynamical part only)
2090  // Add the values at this point on the integration grid to the sums
2091  // (one weighted only by the integration weights, one also weighted by
2092  // the efficiency)
2093  for ( UInt_t i = 0; i < nAmp_; ++i ) {
2094 
2095  // Add the dynamical amplitude squared for this resonance.
2096  Double_t fSqVal = ff_[i].abs2();
2097  fSqSum_[i] += fSqVal * weight;
2098  fSqEffSum_[i] += fSqVal * effWeight;
2099 
2100  for ( UInt_t j = i; j < nAmp_; ++j ) {
2101 
2102  fifjEffSumTerm = fifjSumTerm = ff_[i] * ff_[j].conj();
2103 
2104  fifjEffSumTerm.rescale( effWeight );
2105  fifjEffSum_[i][j] += fifjEffSumTerm;
2106 
2107  fifjSumTerm.rescale( weight );
2108  fifjSum_[i][j] += fifjSumTerm;
2109  }
2110  }
2111  for ( UInt_t i = 0; i < nIncohAmp_; ++i ) {
2112 
2113  // Add the dynamical amplitude squared for this resonance.
2114  Double_t fSqVal = incohInten_[i];
2115  fSqSum_[i + nAmp_] += fSqVal * weight;
2116  fSqEffSum_[i + nAmp_] += fSqVal * effWeight;
2117  }
2118 }
2119 
2121 {
2122  // Routine to calculate the resonance dynamics (amplitude)
2123  // using the appropriate Breit-Wigner/Form Factors.
2124 
2125  LauComplex amp = LauComplex( 0.0, 0.0 );
2126 
2127  if ( index >= nAmp_ ) {
2128  std::cerr << "ERROR in LauIsobarDynamics::resAmp : index = " << index
2129  << " is not within the range 0 to " << nAmp_ - 1 << std::endl;
2130  return amp;
2131  }
2132 
2133  // Get the signal resonance from the stored vector
2134  LauAbsResonance* sigResonance = sigResonances_[index];
2135 
2136  if ( sigResonance == 0 ) {
2137  std::cerr << "ERROR in LauIsobarDynamics::resAmp : Couldn't retrieve valid resonance with index = "
2138  << index << std::endl;
2139  return amp;
2140  }
2141 
2142  amp = sigResonance->amplitude( kinematics_ );
2143 
2144  return amp;
2145 }
2146 
2147 Double_t LauIsobarDynamics::incohResAmp( const UInt_t index )
2148 {
2149  // Routine to calculate the resonance dynamics (amplitude)
2150  // using the appropriate Breit-Wigner/Form Factors.
2151 
2152  Double_t intensity = 0.;
2153 
2154  if ( index >= nIncohAmp_ ) {
2155  std::cerr << "ERROR in LauIsobarDynamics::incohResAmp : index = " << index
2156  << " is not within the range 0 to " << nIncohAmp_ - 1 << std::endl;
2157  return intensity;
2158  }
2159 
2160  // Get the signal resonance from the stored vector
2161  LauAbsIncohRes* sigResonance = sigIncohResonances_[index];
2162 
2163  if ( sigResonance == 0 ) {
2164  std::cerr << "ERROR in LauIsobarDynamics::incohResAmp : Couldn't retrieve valid incoherent resonance with index = "
2165  << index << std::endl;
2166  return intensity;
2167  }
2168 
2169  LauComplex ff = sigResonance->amplitude( kinematics_ );
2170  intensity = sigResonance->intensityFactor( kinematics_ ) * ff.abs2();
2171 
2172  return intensity;
2173 }
2174 
2175 void LauIsobarDynamics::setFFTerm( const UInt_t index, const Double_t realPart, const Double_t imagPart )
2176 {
2177  // Function to set the internal ff term (normally calculated using resAmp(index).
2178  if ( index >= nAmp_ ) {
2179  std::cerr << "ERROR in LauIsobarDynamics::setFFTerm : index = " << index
2180  << " is not within the range 0 to " << nAmp_ - 1 << std::endl;
2181  return;
2182  }
2183 
2184  ff_[index].setRealImagPart( realPart, imagPart );
2185 }
2186 
2187 void LauIsobarDynamics::setIncohIntenTerm( const UInt_t index, const Double_t value )
2188 {
2189  // Function to set the internal incoherent intensity term (normally calculated using incohResAmp(index).
2190  if ( index >= nIncohAmp_ ) {
2191  std::cerr << "ERROR in LauIsobarDynamics::setFFTerm : index = " << index
2192  << " is not within the range 0 to " << nIncohAmp_ - 1 << std::endl;
2193  return;
2194  }
2195 
2196  incohInten_[index] = value;
2197 }
2198 
2199 void LauIsobarDynamics::calcExtraInfo( const Bool_t init )
2200 {
2201  // This method calculates the fit fractions, mean efficiency and total DP rate
2202 
2203  Double_t fifjEffTot( 0.0 ), fifjTot( 0.0 );
2204  UInt_t i, j;
2205  for ( i = 0; i < nAmp_; i++ ) {
2206 
2207  // Calculate the diagonal terms
2208  TString name = "A";
2209  name += i;
2210  name += "Sq_FitFrac";
2211  fitFrac_[i][i].name( name );
2212 
2213  name += "EffUnCorr";
2214  fitFracEffUnCorr_[i][i].name( name );
2215 
2216  Double_t fifjSumReal = fifjSum_[i][i].re();
2217  Double_t sumTerm = Amp_[i].abs2() * fifjSumReal * fNorm_[i] * fNorm_[i];
2218  fifjTot += sumTerm;
2219 
2220  Double_t fifjEffSumReal = fifjEffSum_[i][i].re();
2221  Double_t sumEffTerm = Amp_[i].abs2() * fifjEffSumReal * fNorm_[i] * fNorm_[i];
2222  fifjEffTot += sumEffTerm;
2223 
2224  fitFrac_[i][i].value( sumTerm );
2225  fitFracEffUnCorr_[i][i].value( sumEffTerm );
2226  }
2227 
2228  for ( i = 0; i < nAmp_; i++ ) {
2229  for ( j = i + 1; j < nAmp_ + nIncohAmp_; j++ ) {
2230  // Calculate the cross-terms
2231  TString name = "A";
2232  name += i;
2233  name += "A";
2234  name += j;
2235  name += "_FitFrac";
2236  fitFrac_[i][j].name( name );
2237 
2238  name += "EffUnCorr";
2239  fitFracEffUnCorr_[i][j].name( name );
2240 
2241  if ( j >= nAmp_ ) {
2242  //Set off-diagonal incoherent terms to zero
2243  fitFrac_[i][j].value( 0. );
2244  fitFracEffUnCorr_[i][j].value( 0. );
2245  continue;
2246  }
2247 
2248  LauComplex AmpjConj = Amp_[j].conj();
2249  LauComplex AmpTerm = Amp_[i] * AmpjConj;
2250 
2251  Double_t crossTerm = 2.0 * ( AmpTerm * fifjSum_[i][j] ).re() * fNorm_[i] * fNorm_[j];
2252  fifjTot += crossTerm;
2253 
2254  Double_t crossEffTerm = 2.0 * ( AmpTerm * fifjEffSum_[i][j] ).re() * fNorm_[i] *
2255  fNorm_[j];
2256  fifjEffTot += crossEffTerm;
2257 
2258  fitFrac_[i][j].value( crossTerm );
2259  fitFracEffUnCorr_[i][j].value( crossEffTerm );
2260  }
2261  }
2262 
2263  for ( i = nAmp_; i < nAmp_ + nIncohAmp_; i++ ) {
2264 
2265  // Calculate the incoherent terms
2266  TString name = "A";
2267  name += i;
2268  name += "Sq_FitFrac";
2269  fitFrac_[i][i].name( name );
2270 
2271  name += "EffUnCorr";
2272  fitFracEffUnCorr_[i][i].name( name );
2273 
2274  Double_t sumTerm = Amp_[i].abs2() * fSqSum_[i] * fNorm_[i] * fNorm_[i];
2275  fifjTot += sumTerm;
2276 
2277  Double_t sumEffTerm = Amp_[i].abs2() * fSqEffSum_[i] * fNorm_[i] * fNorm_[i];
2278  fifjEffTot += sumEffTerm;
2279 
2280  fitFrac_[i][i].value( sumTerm );
2281  fitFracEffUnCorr_[i][i].value( sumEffTerm );
2282  }
2283 
2284  for ( i = nAmp_; i < nAmp_ + nIncohAmp_; i++ ) {
2285  for ( j = i + 1; j < nAmp_ + nIncohAmp_; j++ ) {
2286  //Set off-diagonal incoherent terms to zero
2287  TString name = "A";
2288  name += i;
2289  name += "A";
2290  name += j;
2291  name += "_FitFrac";
2292  fitFrac_[i][j].name( name );
2293 
2294  name += "EffUnCorr";
2295  fitFracEffUnCorr_[i][j].name( name );
2296 
2297  fitFrac_[i][j].value( 0. );
2298  fitFracEffUnCorr_[i][j].value( 0. );
2299  }
2300  }
2301 
2302  if ( TMath::Abs( fifjTot ) > 1e-10 ) {
2303  meanDPEff_.value( fifjEffTot / fifjTot );
2304  if ( init ) {
2307  }
2308  }
2309  DPRate_.value( fifjTot );
2310  if ( init ) {
2313  }
2314 
2315  // Now divide the fitFraction sums by the overall integral
2316  for ( i = 0; i < nAmp_ + nIncohAmp_; i++ ) {
2317  for ( j = i; j < nAmp_ + nIncohAmp_; j++ ) {
2318  // Get the actual fractions by dividing by the total DP rate
2319  Double_t fitFracVal = fitFrac_[i][j].value();
2320  fitFracVal /= fifjTot;
2321  fitFrac_[i][j].value( fitFracVal );
2322 
2323  Double_t fitFracEffUnCorrVal = fitFracEffUnCorr_[i][j].value();
2324  fitFracEffUnCorrVal /= fifjEffTot;
2325  fitFracEffUnCorr_[i][j].value( fitFracEffUnCorrVal );
2326 
2327  if ( init ) {
2328  fitFrac_[i][j].genValue( fitFrac_[i][j].value() );
2329  fitFrac_[i][j].initValue( fitFrac_[i][j].value() );
2330  fitFracEffUnCorr_[i][j].genValue( fitFracEffUnCorr_[i][j].value() );
2331  fitFracEffUnCorr_[i][j].initValue( fitFracEffUnCorr_[i][j].value() );
2332  }
2333  }
2334  }
2335 
2336  // Work out total fit fraction over all K-matrix components (for each propagator)
2337  KMPropMap::iterator mapIter;
2338  Int_t propInt( 0 );
2339 
2340  for ( mapIter = kMatrixPropagators_.begin(); mapIter != kMatrixPropagators_.end(); ++mapIter ) {
2341 
2342  LauKMatrixPropagator* thePropagator = mapIter->second;
2343 
2344  TString propName = thePropagator->getName();
2345 
2346  // Now loop over all resonances and find those which are K-matrix components for this propagator
2347  Double_t kMatrixTotFitFrac( 0.0 );
2348 
2349  for ( i = 0; i < nAmp_; i++ ) {
2350 
2351  Bool_t gotKMRes1 = this->gotKMatrixMatch( i, propName );
2352  if ( gotKMRes1 == kFALSE ) {
2353  continue;
2354  }
2355 
2356  Double_t fifjSumReal = fifjSum_[i][i].re();
2357  Double_t sumTerm = Amp_[i].abs2() * fifjSumReal * fNorm_[i] * fNorm_[i];
2358 
2359  //Double_t fifjEffSumReal = fifjEffSum_[i][i].re();
2360  //Double_t sumEffTerm = Amp_[i].abs2()*fifjEffSumReal*fNorm_[i]*fNorm_[i];
2361 
2362  kMatrixTotFitFrac += sumTerm;
2363 
2364  for ( j = i + 1; j < nAmp_; j++ ) {
2365 
2366  Bool_t gotKMRes2 = this->gotKMatrixMatch( j, propName );
2367  if ( gotKMRes2 == kFALSE ) {
2368  continue;
2369  }
2370 
2371  LauComplex AmpjConj = Amp_[j].conj();
2372  LauComplex AmpTerm = Amp_[i] * AmpjConj;
2373 
2374  Double_t crossTerm = 2.0 * ( AmpTerm * fifjSum_[i][j] ).re() * fNorm_[i] * fNorm_[j];
2375  //Double_t crossEffTerm = 2.0*(AmpTerm*fifjEffSum_[i][j]).re()*fNorm_[i]*fNorm_[j];
2376 
2377  kMatrixTotFitFrac += crossTerm;
2378  }
2379  }
2380 
2381  kMatrixTotFitFrac /= fifjTot;
2382 
2383  TString parName( "KMatrixTotFF_" );
2384  parName += propInt;
2385  extraParameters_[propInt].name( parName );
2386  extraParameters_[propInt].value( kMatrixTotFitFrac );
2387  if ( init ) {
2388  extraParameters_[propInt].genValue( kMatrixTotFitFrac );
2389  extraParameters_[propInt].initValue( kMatrixTotFitFrac );
2390  }
2391 
2392  std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : Total K-matrix fit fraction for propagator "
2393  << propName << " is " << kMatrixTotFitFrac << std::endl;
2394 
2395  ++propInt;
2396  }
2397 
2398  // Calculate rho and omega fit fractions from LauRhoOmegaMix
2399 
2400  // In principle the presence of LauRhoOmegaMix can be detected, however
2401  // working out the index of the correct component is hard.
2402 
2403  // To prevent unwanted effects, this has to be manually turned on, with the
2404  // assumption that the first two components are rho and rho_COPY in a LauCPFitModel
2405 
2406  if ( this->calculateRhoOmegaFitFractions_ && ! init ) {
2407 
2408  int omegaID = 0;
2409  int storeID = 1;
2410 
2411  // Check which B flavour (and therefore which rho_COPY we are) by whether the FF is non-zero
2412  // Only for CP fit though - for a 'simple' fit this is more complicated
2413  if ( fitFrac_[omegaID][omegaID].value() < 1E-4 ) {
2414  omegaID = 1;
2415  storeID = 0;
2416  }
2417 
2418  // Check this is really the correct model
2419 
2420  LauRhoOmegaMix* rhomega = dynamic_cast<LauRhoOmegaMix*>( getResonance( omegaID ) );
2421 
2422  if ( rhomega != NULL ) { // Bail out
2423 
2424  std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : Calculating omega fit fraction from resonance "
2425  << omegaID << std::endl;
2426  std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : Storing omega fit fraction in resonance "
2427  << storeID << std::endl;
2428 
2429  // Tell the RhoOmegaMix model only to give us the omega amplitude-squared
2430 
2431  rhomega->setWhichAmpSq( 1 );
2432 
2433  // Recalculate the integrals for the omega fit-fraction
2434 
2435  integralsDone_ = kFALSE;
2436 
2437  this->resetNormVectors();
2438  for ( UInt_t k( 0 ); k < nAmp_ + nIncohAmp_; ++k ) {
2439  integralsToBeCalculated_.insert( k );
2440  }
2441  this->calcDPNormalisation();
2442 
2443  integralsDone_ = kTRUE;
2444 
2445  Double_t fifjSumRealOmega = fifjSum_[omegaID][omegaID].re();
2446 
2447  // Recalculate the integrals for the rho fit-fraction
2448 
2449  rhomega->setWhichAmpSq( 2 );
2450 
2451  integralsDone_ = kFALSE;
2452 
2453  this->resetNormVectors();
2454  for ( UInt_t k( 0 ); k < nAmp_ + nIncohAmp_; ++k ) {
2455  integralsToBeCalculated_.insert( k );
2456  }
2457  this->calcDPNormalisation();
2458 
2459  integralsDone_ = kTRUE;
2460 
2461  Double_t fitFracPartRho = Amp_[omegaID].abs2() * fifjSum_[omegaID][omegaID].re();
2462 
2463  // Reset the RhoOmegaMix model and the integrals
2464 
2465  rhomega->setWhichAmpSq( 0 );
2466 
2467  integralsDone_ = kFALSE;
2468 
2469  this->resetNormVectors();
2470  for ( UInt_t k( 0 ); k < nAmp_ + nIncohAmp_; ++k ) {
2471  integralsToBeCalculated_.insert( k );
2472  }
2473  this->calcDPNormalisation();
2474 
2475  integralsDone_ = kTRUE;
2476 
2477  // Store the omega fit-fraction in the rho_COPY location (which is otherwise empty)
2478  // Store the rho fit-fraction in the rho location (overwriting the combined FF)
2479 
2480  Double_t omegaFF = fifjSumRealOmega * fitFrac_[omegaID][omegaID].value();
2481 
2482  fitFrac_[storeID][storeID].value( omegaFF );
2483  fitFrac_[omegaID][omegaID].value( fitFracPartRho * fNorm_[omegaID] * fNorm_[omegaID] /
2484  DPRate_.value() );
2485 
2486  } else {
2487  std::cout << "INFO in LauIsobarDynamics::calcExtraInfo : calculateRhoOmegaFitFractions is set, but the RhoOmegaMix model isn't in the right place. Ignoring this option."
2488  << std::endl;
2489  }
2490  }
2491 }
2492 
2493 Bool_t LauIsobarDynamics::gotKMatrixMatch( UInt_t resAmpInt, const TString& propName ) const
2494 {
2495 
2496  Bool_t gotMatch( kFALSE );
2497 
2498  if ( resAmpInt >= nAmp_ ) {
2499  return kFALSE;
2500  }
2501 
2502  const LauAbsResonance* theResonance = sigResonances_[resAmpInt];
2503 
2504  if ( theResonance == 0 ) {
2505  return kFALSE;
2506  }
2507 
2508  Int_t resModelInt = theResonance->getResonanceModel();
2509 
2510  if ( resModelInt == LauAbsResonance::KMatrix ) {
2511 
2512  TString resName = theResonance->getResonanceName();
2513 
2514  KMStringMap::const_iterator kMPropSetIter = kMatrixPropSet_.find( resName );
2515 
2516  if ( kMPropSetIter != kMatrixPropSet_.end() ) {
2517  TString kmPropString = kMPropSetIter->second;
2518  if ( kmPropString == propName ) {
2519  gotMatch = kTRUE;
2520  }
2521  }
2522  }
2523 
2524  return gotMatch;
2525 }
2526 
2528 {
2529  // Calculate the normalisation for the log-likelihood function.
2530  DPNorm_ = 0.0;
2531 
2532  for ( UInt_t i = 0; i < nAmp_; i++ ) {
2533  // fifjEffSum is the contribution from the term involving the resonance
2534  // dynamics (f_i for resonance i) and the efficiency term.
2535  Double_t fifjEffSumReal = fifjEffSum_[i][i].re();
2536  // We need to normalise this contribution w.r.t. the complete dynamics in the DP.
2537  // Hence we scale by the fNorm_i factor (squared), which is calculated by the
2538  // initialise() function, when the normalisation integrals are calculated and cached.
2539  // We also include the complex amplitude squared to get the total normalisation
2540  // contribution from this resonance.
2541  DPNorm_ += Amp_[i].abs2() * fifjEffSumReal * fNorm_[i] * fNorm_[i];
2542  }
2543 
2544  // We now come to the cross-terms (between resonances i and j) in the normalisation.
2545  for ( UInt_t i = 0; i < nAmp_; i++ ) {
2546  for ( UInt_t j = i + 1; j < nAmp_; j++ ) {
2547  LauComplex AmpjConj = Amp_[j].conj();
2548  LauComplex AmpTerm = Amp_[i] * AmpjConj;
2549  // Again, fifjEffSum is the contribution from the term involving the resonance
2550  // dynamics (f_i*f_j_conjugate) and the efficiency cross term.
2551  // Also include the relative normalisation between these two resonances w.r.t. the
2552  // total DP dynamical structure (fNorm_i and fNorm_j) and the complex
2553  // amplitude squared (mag,phase) part.
2554  DPNorm_ += 2.0 * ( AmpTerm * fifjEffSum_[i][j] ).re() * fNorm_[i] * fNorm_[j];
2555  }
2556  }
2557 
2558  for ( UInt_t i = 0; i < nIncohAmp_; i++ ) {
2559  DPNorm_ += Amp_[i + nAmp_].abs2() * fSqEffSum_[i + nAmp_] * fNorm_[i + nAmp_] *
2560  fNorm_[i + nAmp_];
2561  }
2562 
2563  return DPNorm_;
2564 }
2565 
2567 {
2568  // Routine to generate a signal event according to the Dalitz plot
2569  // model we have defined.
2570 
2571  // We need to make sure to calculate everything for every resonance
2572  integralsToBeCalculated_.clear();
2573  for ( UInt_t i { 0 }; i < nAmp_ + nIncohAmp_; ++i ) {
2574  integralsToBeCalculated_.insert( i );
2575  }
2576 
2577  if ( aSqMaxAuto_ ) {
2578  std::cout << "INFO in LauIsobarDynamics::generate : Starting auto-location of |A|^2 maximum"
2579  << std::endl;
2580 
2581  LauASqMaxFinder finder { *this };
2582  aSqMaxSet_ = finder.find();
2583  aSqMaxAuto_ = kFALSE;
2584 
2585  std::cout << "INFO in LauIsobarDynamics::generate : auto-location of |A|^2 maximum finds: "
2586  << aSqMaxSet_ << std::endl;
2587  aSqMaxSet_ *= 1.10;
2588  std::cout << " : applying safety factor of 10\% gives: "
2589  << aSqMaxSet_ << std::endl;
2590  }
2591 
2592  nSigGenLoop_ = 0;
2593  Bool_t generatedSig( kFALSE );
2594 
2595  while ( generatedSig == kFALSE && nSigGenLoop_ < iterationsMax_ ) {
2596 
2597  // Generates uniform DP phase-space distribution
2598  Double_t m13Sq( 0.0 ), m23Sq( 0.0 );
2599  kinematics_->genFlatPhaseSpace( m13Sq, m23Sq );
2600 
2601  // If we're in a symmetrical DP then we should only generate events in one half
2602  // TODO - what do we do for fully symmetric?
2603  if ( symmetricalDP_ && ! fullySymmetricDP_ && m13Sq > m23Sq ) {
2604  Double_t tmpSq = m13Sq;
2605  m13Sq = m23Sq;
2606  m23Sq = tmpSq;
2607  }
2608 
2609  // Calculate the amplitudes and total amplitude for the given DP point
2610  this->calcLikelihoodInfo( m13Sq, m23Sq );
2611 
2612  // Throw the random number and check it against the ratio of ASq and the accept/reject ceiling
2613  const Double_t randNo = LauRandom::randomFun()->Rndm();
2614  if ( randNo > ASq_ / aSqMaxSet_ ) {
2615  ++nSigGenLoop_;
2616  } else {
2617  generatedSig = kTRUE;
2618  nSigGenLoop_ = 0;
2619 
2620  // Keep a note of the maximum ASq that we've found
2621  if ( ASq_ > aSqMaxVar_ ) {
2622  aSqMaxVar_ = ASq_;
2623  }
2624  }
2625 
2626  } // while loop
2627 
2628  // Check that all is well with the generation
2629  Bool_t sigGenOK( kTRUE );
2630  if ( GenOK != this->checkToyMC( kTRUE, kFALSE ) ) {
2631  sigGenOK = kFALSE;
2632  }
2633 
2634  return sigGenOK;
2635 }
2636 
2638  Bool_t printInfoMessages )
2639 {
2640  // Check whether we have generated the toy MC OK.
2641  ToyMCStatus ok( GenOK );
2642 
2643  if ( nSigGenLoop_ >= iterationsMax_ ) {
2644  // Exceeded maximum allowed iterations - the generation is too inefficient
2645  if ( printErrorMessages ) {
2646  std::cerr << "WARNING in LauIsobarDynamics::checkToyMC : More than " << iterationsMax_
2647  << " iterations performed and no event accepted." << std::endl;
2648  }
2649 
2650  if ( aSqMaxSet_ > 1.01 * aSqMaxVar_ ) {
2651  if ( printErrorMessages ) {
2652  std::cerr << " : |A|^2 maximum was set to "
2653  << aSqMaxSet_ << " but this appears to be too high." << std::endl;
2654  std::cerr << " : Maximum value of |A|^2 found so far = "
2655  << aSqMaxVar_ << std::endl;
2656  std::cerr << " : The value of |A|^2 maximum will be decreased and the generation restarted."
2657  << std::endl;
2658  }
2659  aSqMaxSet_ = 1.01 * aSqMaxVar_;
2660  std::cout << "INFO in LauIsobarDynamics::checkToyMC : |A|^2 max reset to " << aSqMaxSet_
2661  << std::endl;
2662  ok = MaxIterError;
2663  } else {
2664  if ( printErrorMessages ) {
2665  std::cerr << " : |A|^2 maximum was set to "
2666  << aSqMaxSet_ << ", which seems to be correct for the given model."
2667  << std::endl;
2668  std::cerr << " : However, the generation is very inefficient - please check your model."
2669  << std::endl;
2670  std::cerr << " : The maximum number of iterations will be increased and the generation restarted."
2671  << std::endl;
2672  }
2673  iterationsMax_ *= 2;
2674  std::cout << "INFO in LauIsobarDynamics::checkToyMC : max number of iterations reset to "
2675  << iterationsMax_ << std::endl;
2676  ok = MaxIterError;
2677  }
2678  } else if ( aSqMaxVar_ > aSqMaxSet_ ) {
2679  // Found a value of ASq higher than the accept/reject ceiling - the generation is biased
2680  if ( printErrorMessages ) {
2681  std::cerr << "WARNING in LauIsobarDynamics::checkToyMC : |A|^2 maximum was set to "
2682  << aSqMaxSet_ << " but a value exceeding this was found: " << aSqMaxVar_
2683  << std::endl;
2684  std::cerr << " : This value was found at m13Sq = "
2685  << kinematics_->getm13Sq() << " and m23Sq = " << kinematics_->getm23Sq()
2686  << std::endl;
2687  std::cerr << " : Run was invalid, as any generated MC will be biased, according to the accept/reject method!"
2688  << std::endl;
2689  std::cerr << " : The value of |A|^2 maximum be reset to be > "
2690  << aSqMaxVar_ << " and the generation restarted." << std::endl;
2691  }
2692  aSqMaxSet_ = 1.01 * aSqMaxVar_;
2693  std::cout << "INFO in LauIsobarDynamics::checkToyMC : |A|^2 max reset to " << aSqMaxSet_
2694  << std::endl;
2695  ok = ASqMaxError;
2696  } else if ( printInfoMessages ) {
2697  std::cout << "INFO in LauIsobarDynamics::checkToyMC : aSqMaxSet = " << aSqMaxSet_
2698  << " and aSqMaxVar = " << aSqMaxVar_ << std::endl;
2699  }
2700 
2701  return ok;
2702 }
2703 
2705 {
2706  // Retrieve the data for event iEvt
2707  if ( data_.size() > iEvt ) {
2708  currentEvent_ = data_[iEvt];
2709  } else {
2710  std::cerr << "ERROR in LauIsobarDynamics::setDataEventNo : Event index too large: " << iEvt
2711  << " >= " << data_.size() << "." << std::endl;
2712  }
2713 
2720  scfFraction_ =
2721  currentEvent_->retrieveScfFraction(); // These two are necessary, even though the dynamics don't actually use scfFraction_ or jacobian_,
2722  jacobian_ = currentEvent_->retrieveJacobian(); // since this is at the heart of the caching mechanism.
2723 }
2724 
2725 void LauIsobarDynamics::calcLikelihoodInfo( const UInt_t iEvt )
2726 {
2727  // Calculate the likelihood and associated info
2728  // for the given event using cached information
2729  evtLike_ = 0.0;
2730 
2731  // retrieve the cached dynamics from the tree:
2732  // realAmp, imagAmp for each resonance plus efficiency, scf fraction and jacobian
2733  this->setDataEventNo( iEvt );
2734 
2735  // use realAmp and imagAmp to create the resonance amplitudes
2736  const std::vector<Double_t>& realAmp = currentEvent_->retrieveRealAmp();
2737  const std::vector<Double_t>& imagAmp = currentEvent_->retrieveImagAmp();
2738  const std::vector<Double_t>& incohInten = currentEvent_->retrieveIncohIntensities();
2739  for ( UInt_t i = 0; i < nAmp_; i++ ) {
2740  this->setFFTerm( i, realAmp[i], imagAmp[i] );
2741  }
2742  for ( UInt_t i = 0; i < nIncohAmp_; i++ ) {
2743  this->setIncohIntenTerm( i, incohInten[i] );
2744  }
2745 
2746  // Update the dynamics - calculates totAmp_ and then ASq_ = totAmp_.abs2() * eff_
2747  // All calculated using cached information on the individual amplitudes and efficiency.
2748  this->calcTotalAmp( kTRUE );
2749 
2750  // Calculate the normalised matrix element squared value
2751  if ( DPNorm_ > 1e-10 ) {
2752  evtLike_ = ASq_ / DPNorm_;
2753  }
2754 }
2755 
2756 void LauIsobarDynamics::calcLikelihoodInfo( const Double_t m13Sq, const Double_t m23Sq )
2757 {
2758  this->calcLikelihoodInfo( m13Sq, m23Sq, -1 );
2759 }
2760 
2761 void LauIsobarDynamics::calcLikelihoodInfo( const Double_t m13Sq,
2762  const Double_t m23Sq,
2763  const Int_t tagCat )
2764 {
2765  // Calculate the likelihood and associated info
2766  // for the given point in the Dalitz plot
2767  // Also retrieves the SCF fraction in the bin where the event lies (done
2768  // here to cache it along with the the rest of the DP quantities, like eff)
2769  // The jacobian for the square DP is calculated here for the same reason.
2770  evtLike_ = 0.0;
2771 
2772  // update the kinematics for the specified DP point
2773  kinematics_->updateKinematics( m13Sq, m23Sq );
2774 
2775  // calculate the jacobian and the scfFraction to cache them later
2776  scfFraction_ = this->retrieveScfFraction( tagCat );
2777  if ( kinematics_->squareDP() == kTRUE ) {
2779  }
2780 
2781  // calculate the ff_ terms and retrieves eff_ from the efficiency model
2782  this->calculateAmplitudes();
2783  // then calculate totAmp_ and finally ASq_ = totAmp_.abs2() * eff_
2784  this->calcTotalAmp( kTRUE );
2785 
2786  // Calculate the normalised matrix element squared value
2787  if ( DPNorm_ > 1e-10 ) {
2788  evtLike_ = ASq_ / DPNorm_;
2789  }
2790 }
2791 
2793 {
2794  if ( recalcNormalisation_ == kFALSE ) {
2795  return;
2796  }
2797 
2798  const UInt_t nEvents = data_.size();
2799 
2800  std::set<UInt_t>::const_iterator iter = integralsToBeCalculated_.begin();
2801  const std::set<UInt_t>::const_iterator intEnd = integralsToBeCalculated_.end();
2802 
2803  for ( UInt_t iEvt = 0; iEvt < nEvents; ++iEvt ) {
2804 
2805  currentEvent_ = data_[iEvt];
2806 
2807  std::vector<Double_t>& realAmp = currentEvent_->retrieveRealAmp();
2808  std::vector<Double_t>& imagAmp = currentEvent_->retrieveImagAmp();
2809  std::vector<Double_t>& incohInten = currentEvent_->retrieveIncohIntensities();
2810 
2811  const Double_t m13Sq = currentEvent_->retrievem13Sq();
2812  const Double_t m23Sq = currentEvent_->retrievem23Sq();
2813  const Int_t tagCat = currentEvent_->retrieveTagCat();
2814 
2815  this->calcLikelihoodInfo( m13Sq, m23Sq, tagCat );
2816 
2817  for ( iter = integralsToBeCalculated_.begin(); iter != intEnd; ++iter ) {
2818  const UInt_t i = *iter;
2819  if ( *iter < nAmp_ ) {
2820  realAmp[i] = ff_[i].re();
2821  imagAmp[i] = ff_[i].im();
2822  } else {
2823  incohInten[i - nAmp_] = incohInten_[i - nAmp_];
2824  }
2825  }
2826  }
2827 }
2828 
2830 {
2831  // In LauFitDataTree, the first two variables should always be m13^2 and m23^2.
2832  // Other variables follow thus: charge/flavour tag prob, etc.
2833 
2834  // Since this is the first caching, we need to make sure to calculate everything for every resonance
2835  integralsToBeCalculated_.clear();
2836  for ( UInt_t i( 0 ); i < nAmp_ + nIncohAmp_; ++i ) {
2837  integralsToBeCalculated_.insert( i );
2838  }
2839 
2840  UInt_t nBranches = inputFitTree.nBranches();
2841 
2842  if ( nBranches < 2 ) {
2843  std::cerr << "ERROR in LauIsobarDynamics::fillDataTree : Expecting at least 2 variables "
2844  << "in input data tree, but there are " << nBranches << "!\n";
2845  std::cerr << " : Make sure you have the right number of variables in your input data file!"
2846  << std::endl;
2847  gSystem->Exit( EXIT_FAILURE );
2848  }
2849 
2850  // Data structure that will cache the variables required to
2851  // calculate the signal likelihood for this experiment
2852  for ( std::vector<LauCacheData*>::iterator iter = data_.begin(); iter != data_.end(); ++iter ) {
2853  delete ( *iter );
2854  }
2855  data_.clear();
2856 
2857  Double_t m13Sq( 0.0 ), m23Sq( 0.0 );
2858  Double_t mPrime( 0.0 ), thPrime( 0.0 );
2859  Int_t tagCat( -1 );
2860  std::vector<Double_t> realAmp( nAmp_ ), imagAmp( nAmp_ );
2861  Double_t eff( 0.0 ), scfFraction( 0.0 ), jacobian( 0.0 );
2862 
2863  UInt_t nEvents = inputFitTree.nEvents() + inputFitTree.nFakeEvents();
2864 
2865  data_.reserve( nEvents );
2866 
2867  for ( UInt_t iEvt = 0; iEvt < nEvents; ++iEvt ) {
2868 
2869  const LauFitData& dataValues = inputFitTree.getData( iEvt );
2870  LauFitData::const_iterator iter = dataValues.find( "m13Sq" );
2871  m13Sq = iter->second;
2872  iter = dataValues.find( "m23Sq" );
2873  m23Sq = iter->second;
2874 
2875  // is there more than one tagging category?
2876  // if so then we need to know the category from the data
2877  if ( scfFractionModel_.size() > 1 ) {
2878  iter = dataValues.find( "tagCat" );
2879  tagCat = static_cast<Int_t>( iter->second );
2880  }
2881 
2882  // calculates the amplitudes and total amplitude for the given DP point
2883  // tagging category not needed by dynamics, but to find out the scfFraction
2884  this->calcLikelihoodInfo( m13Sq, m23Sq, tagCat );
2885 
2886  // extract the real and imaginary parts of the ff_ terms for storage
2887  for ( UInt_t i = 0; i < nAmp_; i++ ) {
2888  realAmp[i] = ff_[i].re();
2889  imagAmp[i] = ff_[i].im();
2890  }
2891 
2892  if ( kinematics_->squareDP() ) {
2893  mPrime = kinematics_->getmPrime();
2894  thPrime = kinematics_->getThetaPrime();
2895  }
2896 
2897  eff = this->getEvtEff();
2898  scfFraction = this->getEvtScfFraction();
2899  jacobian = this->getEvtJacobian();
2900 
2901  // store the data for each event in the list
2902  data_.push_back( new LauCacheData() );
2903  data_[iEvt]->storem13Sq( m13Sq );
2904  data_[iEvt]->storem23Sq( m23Sq );
2905  data_[iEvt]->storemPrime( mPrime );
2906  data_[iEvt]->storethPrime( thPrime );
2907  data_[iEvt]->storeTagCat( tagCat );
2908  data_[iEvt]->storeEff( eff );
2909  data_[iEvt]->storeScfFraction( scfFraction );
2910  data_[iEvt]->storeJacobian( jacobian );
2911  data_[iEvt]->storeRealAmp( realAmp );
2912  data_[iEvt]->storeImagAmp( imagAmp );
2913  data_[iEvt]->storeIncohIntensities( incohInten_ );
2914  }
2915 }
2916 
2918 {
2919  // Select the event (kinematics_) using an accept/reject method based on the
2920  // ratio of the current value of ASq to the maximal value.
2921  Bool_t accepted( kFALSE );
2922 
2923  // calculate the ff_ terms and retrieves eff_ from the efficiency model
2924  this->calculateAmplitudes();
2925  // then calculate totAmp_ and finally ASq_ = totAmp_.abs2() (without the efficiency correction!)
2926  this->calcTotalAmp( kFALSE );
2927 
2928  // Compare the ASq value with the maximal value (set by the user)
2929  if ( LauRandom::randomFun()->Rndm() < ASq_ / aSqMaxSet_ ) {
2930  accepted = kTRUE;
2931  }
2932 
2933  if ( ASq_ > aSqMaxVar_ ) {
2934  aSqMaxVar_ = ASq_;
2935  }
2936 
2937  return accepted;
2938 }
2939 
2941 {
2942  // calculate the ff_ terms and retrieves eff_ from the efficiency model
2943  this->calculateAmplitudes();
2944 
2945  // then calculate totAmp_ and finally ASq_ = totAmp_.abs2() (without the efficiency correction!)
2946  this->calcTotalAmp( kFALSE );
2947 
2948  // return the event weight = the value of the squared amplitude
2949  return ASq_;
2950 }
2951 
2952 void LauIsobarDynamics::updateCoeffs( const std::vector<LauComplex>& coeffs )
2953 {
2954  // Check that the number of coeffs is correct
2955  if ( coeffs.size() != this->getnTotAmp() ) {
2956  std::cerr << "ERROR in LauIsobarDynamics::updateCoeffs : Expected " << this->getnTotAmp()
2957  << " but got " << coeffs.size() << std::endl;
2958  gSystem->Exit( EXIT_FAILURE );
2959  }
2960 
2961  // Now check if the coeffs have changed
2962  Bool_t changed = ( Amp_ != coeffs );
2963  if ( changed ) {
2964  // Copy the coeffs
2965  Amp_ = coeffs;
2966  }
2967 
2968  // TODO should perhaps keep track of whether the resonance parameters have changed here and if none of those and none of the coeffs have changed then we don't need to update the norm
2969 
2970  // Update the total normalisation for the signal likelihood
2971  this->calcSigDPNorm();
2972 }
2973 
2974 TString LauIsobarDynamics::getConjResName( const TString& resName ) const
2975 {
2976  // Get the name of the charge conjugate resonance
2977  TString conjName( resName );
2978 
2979  Ssiz_t index1 = resName.Index( "+" );
2980  Ssiz_t index2 = resName.Index( "-" );
2981  if ( index1 != -1 ) {
2982  conjName.Replace( index1, 1, "-" );
2983  } else if ( index2 != -1 ) {
2984  conjName.Replace( index2, 1, "+" );
2985  }
2986 
2987  return conjName;
2988 }
2989 
2991 {
2992  Double_t eff( 1.0 );
2993  if ( effModel_ != 0 ) {
2995  }
2996  return eff;
2997 }
2998 
3000 {
3001  Double_t scfFraction( 0.0 );
3002 
3003  // scf model and eff model are exactly the same, functionally
3004  // so we use an instance of LauAbsEffModel, and the method
3005  // calcEfficiency actually calculates the scf fraction
3006  if ( tagCat == -1 ) {
3007  if ( ! scfFractionModel_.empty() ) {
3008  scfFraction = scfFractionModel_[0]->calcEfficiency( kinematics_ );
3009  }
3010  } else {
3011  scfFraction = scfFractionModel_[tagCat]->calcEfficiency( kinematics_ );
3012  }
3013  return scfFraction;
3014 }
Double_t getm12Max() const
Get the m12 maximum defined as (mParent - m3)
File containing declaration of LauAbsEffModel class.
TString getNameDaug3() const
Get name of the third daughter particle.
File containing declaration of LauResonanceInfo class.
Double_t getEventWeight()
Calculate the acceptance rate, for events with the current kinematics, when generating events accordi...
Bool_t normalizationSchemeDone_
Whether the scheme for the integration has been determined.
File containing LauRandom namespace.
Int_t retrieveTagCat() const
Retrieve the tagging category.
Bool_t aSqMaxAuto_
Flag to generate aSqMaxSet_ once generate is called.
static LauResonanceMaker & get()
Get the factory instance.
Int_t resonanceIndex(const TString &resName) const
Retrieve the index for the given resonance.
const LauAbsResonance * getResonance(const UInt_t resIndex) const
Retrieve a resonance by its index.
std::vector< Double_t > incohInten_
The dynamic part of the intensity for each incoherent amplitude component at the current point in the...
Double_t getWeight(const UInt_t m13Point, const UInt_t m23Point) const
Retrieve the weight for the given grid point.
LauParArray fitFrac_
The fit fractions for the amplitude components.
std::vector< TString > incohResTypAmp_
The resonance types of all of the incoherent amplitude components.
const TString & getResonanceName() const
Get the name of the resonance.
Double_t unblindValue() const
The unblinded value of the parameter.
std::vector< LauComplex > ff_
The dynamic part of the amplitude for each amplitude component at the current point in the Dalitz plo...
LauKinematics * kinematics_
The kinematics of the decay.
std::vector< LauAbsIncohRes * > sigIncohResonances_
The incoherent resonances in the model.
UInt_t nIncohAmp_
The number of incoherent amplitude components.
const LauComplex & getAmplitude(const UInt_t m13Point, const UInt_t m23Point, const UInt_t iAmp) const
Retrieve the amplitude for the given grid point and amplitude index.
Abstract class for defining incoherent resonant amplitude models.
const LauAbsResonance * findResonance(const TString &resName) const
Retrieve the named resonance.
std::vector< Double_t > fNorm_
The normalisation factors for the dynamic parts of the amplitude for each amplitude component.
KMPropMap kMatrixPropagators_
The K-matrix propagators.
Int_t getCharge(Int_t resPairAmpInt) const
Get charge of a particular two-daughter combination.
File containing declaration of LauDPPartialIntegralInfo class.
void calcLikelihoodInfo(const UInt_t iEvt)
Calculate the likelihood (and all associated information) for the given event number.
LauKMatrixPropagator * defineKMatrixPropagator(const TString &propName, const TString &paramFileName, Int_t resPairAmpInt, Int_t nChannels, Int_t nPoles, Int_t rowIndex=1)
Define a new K-matrix Propagator.
File containing declaration of LauASqMaxFinder class.
TString getNameDaug2() const
Get name of the second daughter particle.
Bool_t symmetricalDP_
Whether the Dalitz plot is symmetrical.
Double_t value() const
The value of the parameter.
UInt_t nBranches() const
Obtain the number of branches in the tree.
LauComplex resAmp(const UInt_t index)
Calculate the dynamic part of the amplitude for a given component at the current point in the Dalitz ...
Double_t aSqMaxSet_
The maximum allowed value of A squared.
void setDataEventNo(UInt_t iEvt)
Load the data for a given event.
Bool_t gotFullySymmetricDP() const
Is Dalitz plot fully symmetric, i.e. 3 identical particles.
Definition: LauDaughters.hh:90
void setIncohIntenTerm(const UInt_t index, const Double_t value)
Set the dynamic part of the intensity for a given incoherent amplitude component at the current point...
Bool_t getSquareDP() const
Retrieve the square DP flag.
KMStringMap kMatrixPropSet_
The names of the M-matrix components in the model mapped to their propagators.
void calcDPNormalisation()
Calculate the Dalitz plot normalisation integrals across the whole Dalitz plot.
Double_t getEvtEff() const
Retrieve the efficiency for the current event.
static bool isIncoherentModel(LauResonanceModel model)
Is the resonance model incoherent?
UInt_t nAmp_
The number of amplitude components.
const LauFitData & getData(UInt_t iEvt) const
Retrieve the data for a given event.
Class for defining the rho-omega resonance mixing model.
Double_t getThetaPrime() const
Get theta' value.
Int_t nSigGenLoop_
The number of unsucessful attempts to generate an event so far.
Double_t getM13Value(const UInt_t m13Point) const
Retrieve the m13 value at the given grid point.
void recalculateNormalisation()
recalculate Normalization
Bool_t fullySymmetricDP_
Whether the Dalitz plot is fully symmetric.
Double_t getmPrime() const
Get m' value.
Double_t ASq_
The value of A squared for the current event.
TString getNameParent() const
Get name of the parent particle.
void cullNullRegions(std::vector< LauDPPartialIntegralInfo * > &regions) const
Removes entries in the vector of LauDPPartialIntegralInfo* that are null.
std::vector< LauDPPartialIntegralInfo * > m13IntegrationRegions(const std::vector< std::pair< Double_t, Double_t >> &m13Regions, const std::vector< std::pair< Double_t, Double_t >> &m23Regions, const std::vector< Double_t > &m13Binnings, const Double_t precision, const Double_t defaultBinning) const
Create the integration grid objects for the m13 narrow resonance regions, excluding the overlap regio...
File containing declaration of LauCacheData class.
void flipAndUpdateKinematics()
Flips the DP variables m13^2 <-> m23^2 and recalculates all kinematic quantities.
std::vector< Double_t > fSqSum_
The event-by-event running total of the dynamical amplitude squared for each amplitude component.
File containing declaration of LauBelleNR class.
Class for defining a K-matrix production "slowly-varying part" (SVP) amplitude.
Double_t getm13Max() const
Get the m13 maximum defined as (mParent - m2)
void setFFTerm(const UInt_t index, const Double_t realPart, const Double_t imagPart)
Set the dynamic part of the amplitude for a given amplitude component at the current point in the Dal...
void calcTotalAmp(const Bool_t useEff)
Calculate the total Dalitz plot amplitude at the current point in the Dalitz plot.
File containing declaration of LauAbsResonance class.
Double_t getIntensity(const UInt_t m13Point, const UInt_t m23Point, const UInt_t iAmp) const
Retrieve the intensity for the given grid point and intensity index.
virtual Double_t calcEfficiency(const LauKinematics *kinematics) const =0
Determine the efficiency for a given point in the Dalitz plot.
Bool_t flipHelicity_
The helicity flip flag for new amplitude components.
const std::vector< Double_t > & retrieveImagAmp() const
Retrieve the imaginary parts of the amplitudes.
Bool_t gotFlavourConjugateDP() const
Is Dalitz plot flavour-conjugate, i.e. CP(d1) = d2 and CP(d3) = d3.
Definition: LauDaughters.hh:96
void fillDataTree(const LauFitDataTree &fitDataTree)
Fill the internal data structure that caches the resonance dynamics.
Int_t getTypeDaug2() const
Get PDG code of the second daughter particle.
void updateKinematics(const Double_t m13Sq, const Double_t m23Sq)
Update all kinematic quantities based on the DP co-ordinates m13Sq and m23Sq.
Double_t retrieveEff() const
Retrieve the efficiency.
File containing declaration of LauFitDataTree class.
Bool_t recalcNormalisation_
Flag to recalculate the normalisation.
LauAbsResonance * addResonance(const TString &resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory=LauBlattWeisskopfFactor::Default)
Add a resonance to the Dalitz plot.
Bool_t hasResonance(const TString &resName) const
Check whether this model includes a named resonance.
TString intFileName_
The name of the file to save integrals to.
void rotateAndUpdateKinematics()
Cyclically rotates the DP variables (m12 -> m23, m23 -> m13, m13 -> m12) and recalculates all kinemat...
virtual Double_t intensityFactor(const LauKinematics *kinematics)=0
Get intensity factor.
LauDPPartialIntegralInfo * newDPIntegrationRegion(const Double_t minm13, const Double_t maxm13, const Double_t minm23, const Double_t maxm23, const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t precision, const UInt_t nAmp, const UInt_t nIncohAmp) const
Wrapper for LauDPPartialIntegralInfo constructor.
Bool_t withinDPLimits(const Double_t m13Sq, const Double_t m23Sq) const
Check whether a given (m13Sq,m23Sq) point is within the kinematic limits of the Dalitz plot.
void correctDPOverlap(std::vector< std::pair< Double_t, Double_t >> &regions, const std::vector< Double_t > &binnings) const
Correct regions to ensure that the finest integration grid takes precedence.
std::vector< Int_t > incohResPairAmp_
The index of the daughter not produced by the resonance for each incoherent amplitude component.
File containing declaration of LauNRAmplitude class.
LauAbsEffModel * effModel_
The efficiency model across the Dalitz plot.
Int_t getTypeParent() const
Get PDG code of the parent particle.
TString getNameDaug1() const
Get name of the first daughter particle.
LauTagCatScfFractionModelMap scfFractionModel_
The self cross feed fraction models across the Dalitz plot.
void storeEfficiency(const UInt_t m13Point, const UInt_t m23Point, const Double_t efficiency)
Store the efficiency for the given grid point.
Double_t aSqMaxVar_
The maximum value of A squared that has been seen so far while generating.
LauDaughters * daughters_
The daughters of the decay.
Double_t scfFraction_
The fraction of events that are poorly reconstructed (the self cross feed fraction) at the current po...
void addGridPointToIntegrals(const Double_t weight)
Add the amplitude values (with the appropriate weight) at the current grid point to the running integ...
Class to store the input fit variables.
void zero()
Set both real and imaginary part to zero.
Definition: LauComplex.hh:331
Double_t m13Sq_
The invariant mass squared of the first and third daughters.
Double_t getm23Max() const
Get the m23 maximum defined as (mParent - m1)
File containing declaration of LauKMatrixPropFactory class.
Bool_t generate()
Generate a toy MC signal event.
Double_t narrowWidth_
The value below which a resonance width is considered to be narrow.
Class for defining a complex number.
Definition: LauComplex.hh:61
Int_t iterationsMax_
The maximum allowed number of attempts when generating an event.
UInt_t getnTotAmp() const
Retrieve the total number of amplitude components.
std::vector< LauParameter > extraParameters_
any extra parameters/quantities (e.g. K-matrix total fit fractions)
void storeAmplitude(const UInt_t m13Point, const UInt_t m23Point, const UInt_t iAmp, const LauComplex &amplitude)
Store the amplitude for the given grid point and amplitude index.
std::vector< Double_t > resonanceParValues_
List of floating resonance parameter values from previous calculation.
std::vector< LauDPPartialIntegralInfo * > m23IntegrationRegions(const std::vector< std::pair< Double_t, Double_t >> &m13Regions, const std::vector< std::pair< Double_t, Double_t >> &m23Regions, const std::vector< Double_t > &m13Binnings, const std::vector< Double_t > &m23Binnings, const Double_t precision, const Double_t defaultBinning) const
Create the integration grid objects for the m23 narrow resonance regions, including the overlap regio...
std::map< Int_t, LauAbsEffModel * > LauTagCatScfFractionModelMap
The type used for containing multiple self cross feed fraction models for different categories (e....
Double_t getm12Min() const
Get the m12 minimum defined as (m1 + m2)
std::vector< Double_t > fSqEffSum_
The event-by-event running total of the dynamical amplitude squared for each amplitude component.
void calculateAmplitudes()
Calculate the amplitudes for all resonances for the current kinematics.
Class for defining a K-matrix propagator.
LauAbsResonance * getResonance(const LauDaughters *daughters, const TString &resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType, const LauBlattWeisskopfFactor::BlattWeisskopfCategory bwCategory=LauBlattWeisskopfFactor::Default)
Create a resonance.
Class for defining (a section of) the Dalitz plot integration binning scheme.
UInt_t nFakeEvents() const
Retrieve the number of fake events.
Class to contain cached data relating to an event.
Definition: LauCacheData.hh:43
Bool_t gotReweightedEvent()
Calculates whether an event with the current kinematics should be accepted in order to produce a dist...
Double_t DPNorm_
The normalisation factor for the log-likelihood function.
LauParameter * getWidth() const
Retrieve the width of the resonant particle.
void rescale(Double_t scaleVal)
Scale this by a factor.
Definition: LauComplex.hh:301
Int_t getNChannels() const
Get the number of channels.
void squareDP(const Bool_t calcSquareDPCoords)
Enable/disable the calculation of square Dalitz plot co-ordinates.
void findIntegralsToBeRecalculated()
Determine which amplitudes and integrals need to be recalculated.
std::vector< LauCacheData * > data_
The cached data for all events.
ToyMCStatus
The possible statuses for toy MC generation.
Double_t retrievem13Sq() const
Retrieve the invariant mass squared of the first and third daugthers.
TString getConjResName(const TString &resName) const
Retrieve the name of the charge conjugate of a named resonance.
Double_t getm23Min() const
Get the m23 minimum defined as (m2 + m3)
LauParameter * getMass() const
Retrieve the mass of the resonant particle.
LauComplex totAmp_
The total amplitude for the current event.
Double_t retrievem23Sq() const
Retrieve the invariant mass squared of the second and third daugthers.
std::vector< Int_t > typDaug_
The PDG codes of the daughters.
File containing declaration of LauDaughters class.
Double_t eff_
The efficiency at the current point in the Dalitz plot.
void addKMatrixProdSVP(const TString &SVPName, const TString &propName, Int_t channelIndex, Bool_t useProdAdler=kFALSE)
Add a K-matrix slowly-varying part (SVP) term to the model.
ToyMCStatus checkToyMC(Bool_t printErrorMessages=kTRUE, Bool_t printInfoMessages=kFALSE)
Check the status of the toy MC generation.
Class for defining a K-matrix production pole amplitude term.
Double_t retrieveJacobian() const
Retrieve the Jacobian for the transformation into square-Dalitz-plot coordinates.
Double_t thPrime_
The square Dalitz plot coordinate theta'.
UInt_t getnCohAmp() const
Retrieve the number of coherent amplitude components.
TRandom * randomFun()
Access the singleton random number generator with a particular seed.
Definition: LauRandom.cc:33
Bool_t flipHelicity() const
Get the helicity flip flag.
void initSummary()
Print a summary of the model to be used.
void resetNormVectors()
Zero the various values used to store integrals info.
void storeIntensity(const UInt_t m13Point, const UInt_t m23Point, const UInt_t iAmp, const Double_t intensity)
Store the intensity for the given grid point and intensity index.
Double_t abs2() const
Obtain the square of the absolute value of the complex number.
Definition: LauComplex.hh:260
LauParameter DPRate_
The overall Dalitz plot rate.
Bool_t gotKMatrixMatch(UInt_t resAmpInt, const TString &propName) const
Check whether a resonance is a K-matrix component of a given propagator.
void setWhichAmpSq(Int_t which)
Set which rho/omega amplitude to calculate for FF.
File containing declaration of LauBelleSymNR class.
LauParameter meanDPEff_
The mean efficiency across the Dalitz plot.
void genFlatPhaseSpace(Double_t &m13Sq, Double_t &m23Sq) const
Routine to generate events flat in phase-space.
Class for defining the properties of a resonant particle.
Double_t mPrimeBinWidth_
The bin width to use when integrating over mPrime.
virtual LauComplex amplitude(const LauKinematics *kinematics)
Calculate the complex amplitude.
LauKMatrixPropagator * getPropagator(const TString &name, const TString &paramFileName, Int_t resPairAmpInt, Int_t nChannels, Int_t nPoles, Int_t rowIndex)
Retrieve the propagator if it already exists, otherwise create one.
Double_t m23Sq_
The invariant mass squared of the second and third daughters.
void calcDPPartialIntegral(LauDPPartialIntegralInfo *intInfo)
Calculate the Dalitz plot normalisation integrals over a given range.
Double_t retrieveScfFraction(Int_t tagCat)
Obtain the self cross feed fraction of the current event from the model.
File containing LauConstants namespace.
Double_t evtLike_
The normalised likelihood for the current event.
std::vector< std::vector< LauComplex > > fifjEffSum_
The event-by-event running total of efficiency corrected amplitude cross terms for each pair of ampli...
const TString & name() const
The parameter name.
void initialise(const std::vector< LauComplex > &coeffs)
Initialise the Dalitz plot dynamics.
LauIsobarDynamics(LauDaughters *daughters, LauAbsEffModel *effModel, LauAbsEffModel *scfFractionModel=0)
Constructor.
Int_t tagCat_
The tagging category.
std::vector< std::pair< Double_t, Double_t > > formGapsFromRegions(const std::vector< std::pair< Double_t, Double_t >> &regions, const Double_t min, const Double_t max) const
Form the regions that are produced by the spaces between narrow resonances.
void collateResonanceParameters()
Collate the resonance parameters to initialise (or re-initialise) the model.
std::vector< LauAbsResonance * > sigResonances_
The resonances in the model.
UInt_t getnm23Points() const
Retrieve the number of bins in m23.
Class for locating the |A|^2 max for a given model.
Bool_t flavConjDP_
Whether the Dalitz plot is a flavour-conjugate final state.
File containing declaration of LauAbsIncohRes class.
std::vector< LauParameter * > resonancePars_
List of floating resonance parameters.
Singleton factory class for creating resonances.
const std::vector< Double_t > & retrieveIncohIntensities() const
Retrieve the incoherent intensities.
Double_t m23BinWidth_
The bin width to use when integrating over m23.
Double_t getEvtScfFraction() const
Retrieve the fraction of events that are poorly reconstructed (the self cross feed fraction) for the ...
File containing declaration of LauRhoOmegaMix class.
BlattWeisskopfCategory
Define resonance categories that will share common barrier factor radii.
Bool_t integralsDone_
Whether the integrals have been performed.
std::map< TString, Double_t > LauFitData
Type for holding event data.
std::vector< LauComplex > Amp_
The complex coefficients for the amplitude components.
void modifyDataTree()
Recache the amplitude values for those that have changed.
File containing declaration of LauKMatrixProdSVP class.
void updateSqDPKinematics(const Double_t mPrime, const Double_t thetaPrime)
Update all kinematic quantities based on the square DP co-ordinates m' and theta'.
Bool_t forceSymmetriseIntegration_
Force the symmetrisation of the integration in m13 <-> m23 for non-symmetric but flavour-conjugate fi...
std::vector< TString > resTypAmp_
The resonance types of all of the amplitude components.
void addKMatrixProdPole(const TString &poleName, const TString &propName, Int_t poleIndex, Bool_t useProdAdler=kFALSE)
Add a K-matrix production pole term to the model.
Double_t calcSigDPNorm()
Calculate the normalisation factor for the log-likelihood function.
Abstract class for defining type for resonance amplitude models (Breit-Wigner, Flatte etc....
File containing declaration of LauPrint class and LauOutputLevel enum.
Double_t jacobian_
The Jacobian, for the transformation into square DP coordinates at the current point in the Dalitz pl...
void initialiseVectors()
Initialise the internal storage for this model.
TString getName() const
Get the propagator name.
Double_t mPrime_
The square Dalitz plot coordinate, m'.
LauCacheData * currentEvent_
The cached data for the current event.
std::vector< std::vector< UInt_t > > resonanceParResIndex_
Indices in sigResonances_ to point to the corresponding signal resonance(s) for each floating paramet...
Double_t getM23Value(const UInt_t m23Point) const
Retrieve the m23 value at the given grid point.
Bool_t calculateRhoOmegaFitFractions_
Whether to calculate separate rho and omega fit fractions from the LauRhoOmegaMix model.
File containing declaration of LauKMatrixPropagator class.
Double_t calcSqDPJacobian(const Double_t mPrime, const Double_t thPrime) const
Calculate the Jacobian for the transformation m23^2, m13^2 -> m', theta' (square DP) at the given poi...
Double_t genValue() const
The value generated for the parameter.
const std::vector< Double_t > & retrieveRealAmp() const
Retrieve the real parts of the amplitudes.
LauParArray fitFracEffUnCorr_
The efficiency-uncorrected fit fractions for the amplitude components.
Double_t getm13Min() const
Get the m13 minimum defined as (m1 + m3)
Double_t retrieveEfficiency()
Obtain the efficiency of the current event from the model.
void setSpinType(const LauSpinType spinType)
Set the spin formalism to be used.
Pure abstract base class for defining the efficiency description across the signal Dalitz plot.
File containing declaration of LauKMatrixProdPole class.
Int_t getResPairAmpInt() const
Get the DP axis identifier.
void updateCoeffs(const std::vector< LauComplex > &coeffs)
Update the complex coefficients for the resonances.
virtual LauResonanceModel getResonanceModel() const =0
Get the resonance model type.
std::set< UInt_t > integralsToBeCalculated_
Resonance indices for which the amplitudes and integrals should be recalculated.
UInt_t getnm13Points() const
Retrieve the number of bins in m13.
Int_t getTypeDaug1() const
Get PDG code of the first daughter particle.
Double_t getEvtJacobian() const
Retrieve the Jacobian, for the transformation into square DP coordinates, for the current event.
Class that defines the particular 3-body decay under study.
Definition: LauDaughters.hh:47
Double_t retrievemPrime() const
Retrieve the square Dalitz plot coordinate, m'.
Double_t getm23Sq() const
Get the m23 invariant mass square.
void removeCharge(TString &string) const
Remove the charge from the given particle name.
std::vector< Int_t > resPairAmp_
The index of the daughter not produced by the resonance for each amplitude component.
LauResonanceInfo * getResInfo(const TString &resName) const
Get the information for the given resonance name.
std::vector< std::vector< LauComplex > > fifjSum_
The event-by-event running total of the amplitude cross terms for each pair of amplitude components.
Double_t getm13Sq() const
Get the m13 invariant mass square.
Double_t retrievethPrime() const
Retrieve the square Dalitz plot coordinate, theta'.
Int_t getChargeParent() const
Get charge of the parent particle.
Bool_t gotSymmetricalDP() const
Is Dalitz plot symmetric, i.e. 2 identical particles.
Definition: LauDaughters.hh:84
Int_t getNPoles() const
Get the number of poles.
void setIntegralBinWidths(const Double_t m13BinWidth, const Double_t m23BinWidth, const Double_t mPrimeBinWidth=0.001, const Double_t thPrimeBinWidth=0.001)
Set the widths of the bins to use when integrating across the Dalitz plot or square Dalitz plot.
Double_t thPrimeBinWidth_
The bin width to use when integrating over thetaPrime.
virtual ~LauIsobarDynamics()
Destructor.
Int_t getTypeDaug3() const
Get PDG code of the third daughter particle.
void calcExtraInfo(const Bool_t init=kFALSE)
Calculate the fit fractions, mean efficiency and total DP rate.
void calcDPNormalisationScheme()
Calculate the Dalitz plot normalisation integrals across the whole Dalitz plot.
Double_t initValue() const
The initial value of the parameter.
Double_t retrieveScfFraction() const
Retrieve the fraction of poorly reconstructed events (the so-called self cross feed fraction)
UInt_t nEvents() const
Retrieve the number of events.
LauResonanceModel
Define the allowed resonance types.
Double_t m13BinWidth_
The bin width to use when integrating over m13.
File containing declaration of LauIsobarDynamics class.
LauAbsResonance * addIncoherentResonance(const TString &resName, const Int_t resPairAmpInt, const LauAbsResonance::LauResonanceModel resType)
Add an incoherent resonance to the Dalitz plot.
void writeIntegralsFile()
Write the results of the integrals (and related information) to a file.
File containing declaration of LauResonanceMaker class.
File containing declaration of LauKinematics class.
Double_t incohResAmp(const UInt_t index)
Calculate the dynamic part of the intensity for a given incoherent component at the current point in ...
static LauKMatrixPropFactory * getInstance()
Get a static instance of this factory class. Only one is created per application.
Double_t binningFactor_
The factor relating the width of the narrowest resonance and the binning size.
std::vector< LauDPPartialIntegralInfo * > dpPartialIntegralInfo_
The storage of the integration scheme.
Bool_t withinSqDPLimits(const Double_t mPrime, const Double_t thetaPrime) const
Check whether a given (m',theta') point is within the kinematic limits of the Dalitz plot.