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