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