laura is hosted by Hepforge, IPPP Durham
Laura++  v3r1
A maximum likelihood fitting package for performing Dalitz-plot analysis.
LauCPFitModel.cc
Go to the documentation of this file.
1 
2 // Copyright University of Warwick 2004 - 2014.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 // Authors:
7 // Thomas Latham
8 // John Back
9 // Paul Harrison
10 
15 #include <iostream>
16 #include <iomanip>
17 #include <fstream>
18 #include <vector>
19 
20 #include "TVirtualFitter.h"
21 #include "TSystem.h"
22 #include "TMinuit.h"
23 #include "TRandom.h"
24 #include "TFile.h"
25 #include "TMath.h"
26 #include "TH2.h"
27 
28 #include "LauAbsBkgndDPModel.hh"
29 #include "LauAbsCoeffSet.hh"
30 #include "LauIsobarDynamics.hh"
31 #include "LauAbsPdf.hh"
32 #include "LauAsymmCalc.hh"
33 #include "LauComplex.hh"
34 #include "LauConstants.hh"
35 #include "LauCPFitModel.hh"
36 #include "LauDaughters.hh"
37 #include "LauEffModel.hh"
38 #include "LauEmbeddedData.hh"
39 #include "LauFitNtuple.hh"
40 #include "LauKinematics.hh"
41 #include "LauPrint.hh"
42 #include "LauRandom.hh"
43 #include "LauScfMap.hh"
44 #include "TGraph2D.h"
45 #include "TGraph.h"
46 #include "TStyle.h"
47 #include "TCanvas.h"
48 #include "TGraph2D.h"
49 #include "TGraph.h"
50 #include "TStyle.h"
51 #include "TCanvas.h"
52 
54 
55 
56 LauCPFitModel::LauCPFitModel(LauIsobarDynamics* negModel, LauIsobarDynamics* posModel, Bool_t tagged, const TString& tagVarName) : LauAbsFitModel(),
57  negSigModel_(negModel), posSigModel_(posModel),
58  negKinematics_(negModel ? negModel->getKinematics() : 0),
59  posKinematics_(posModel ? posModel->getKinematics() : 0),
60  usingBkgnd_(kFALSE),
61  nSigComp_(0),
62  nSigDPPar_(0),
63  nExtraPdfPar_(0),
64  nNormPar_(0),
65  negMeanEff_("negMeanEff",0.0,0.0,1.0), posMeanEff_("posMeanEff",0.0,0.0,1.0),
66  negDPRate_("negDPRate",0.0,0.0,100.0), posDPRate_("posDPRate",0.0,0.0,100.0),
67  signalEvents_(0),
68  signalAsym_(0),
69  forceAsym_(kFALSE),
70  tagged_(tagged),
71  tagVarName_(tagVarName),
72  curEvtCharge_(0),
73  useSCF_(kFALSE),
74  useSCFHist_(kFALSE),
75  scfFrac_("scfFrac",0.0,0.0,1.0),
76  scfFracHist_(0),
77  scfMap_(0),
78  compareFitData_(kFALSE),
79  negParent_("B-"), posParent_("B+"),
80  negSignalTree_(0), posSignalTree_(0),
81  reuseSignal_(kFALSE),
82  useNegReweighting_(kFALSE), usePosReweighting_(kFALSE),
83  sigDPLike_(0.0),
84  scfDPLike_(0.0),
85  sigExtraLike_(0.0),
86  scfExtraLike_(0.0),
87  sigTotalLike_(0.0),
88  scfTotalLike_(0.0)
89 {
90  const LauDaughters* negDaug = negSigModel_->getDaughters();
91  if (negDaug != 0) {negParent_ = negDaug->getNameParent();}
92  const LauDaughters* posDaug = posSigModel_->getDaughters();
93  if (posDaug != 0) {posParent_ = posDaug->getNameParent();}
94 }
95 
97 {
98  delete negSignalTree_;
99  delete posSignalTree_;
100  for (LauBkgndEmbDataList::iterator iter = negBkgndTree_.begin(); iter != negBkgndTree_.end(); ++iter) {
101  delete (*iter);
102  }
103  for (LauBkgndEmbDataList::iterator iter = posBkgndTree_.begin(); iter != posBkgndTree_.end(); ++iter) {
104  delete (*iter);
105  }
106  delete scfFracHist_;
107 }
108 
110 {
111  UInt_t nBkgnds = this->nBkgndClasses();
112  negBkgndDPModels_.resize( nBkgnds );
113  posBkgndDPModels_.resize( nBkgnds );
114  negBkgndPdfs_.resize( nBkgnds );
115  posBkgndPdfs_.resize( nBkgnds );
116  bkgndEvents_.resize( nBkgnds );
117  bkgndAsym_.resize( nBkgnds );
118  negBkgndTree_.resize( nBkgnds );
119  posBkgndTree_.resize( nBkgnds );
120  reuseBkgnd_.resize( nBkgnds );
121  bkgndDPLike_.resize( nBkgnds );
122  bkgndExtraLike_.resize( nBkgnds );
123  bkgndTotalLike_.resize( nBkgnds );
124 }
125 
127 {
128  if ( nSigEvents == 0 ) {
129  std::cerr << "ERROR in LauCPFitModel::setNSigEvents : The LauParameter pointer is null." << std::endl;
130  gSystem->Exit(EXIT_FAILURE);
131  }
132  if ( signalEvents_ != 0 ) {
133  std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal yield." << std::endl;
134  return;
135  }
136  if ( signalAsym_ != 0 ) {
137  std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal asymmetry." << std::endl;
138  return;
139  }
140 
141  signalEvents_ = nSigEvents;
142  TString name = signalEvents_->name();
143  if ( ! name.Contains("signalEvents") && !( name.BeginsWith("signal") && name.EndsWith("Events") ) ) {
144  signalEvents_->name("signalEvents");
145  }
146  Double_t value = nSigEvents->value();
147  signalEvents_->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0));
148 
149  signalAsym_ = new LauParameter("signalAsym",0.0,-1.0,1.0,kTRUE);
150 }
151 
152 void LauCPFitModel::setNSigEvents( LauParameter* nSigEvents, LauParameter* sigAsym, Bool_t forceAsym )
153 {
154  if ( nSigEvents == 0 ) {
155  std::cerr << "ERROR in LauCPFitModel::setNSigEvents : The event LauParameter pointer is null." << std::endl;
156  gSystem->Exit(EXIT_FAILURE);
157  }
158  if ( sigAsym == 0 ) {
159  std::cerr << "ERROR in LauCPFitModel::setNSigEvents : The asym LauParameter pointer is null." << std::endl;
160  gSystem->Exit(EXIT_FAILURE);
161  }
162 
163  if ( signalEvents_ != 0 ) {
164  std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal yield." << std::endl;
165  return;
166  }
167  if ( signalAsym_ != 0 ) {
168  std::cerr << "ERROR in LauCPFitModel::setNSigEvents : You are trying to overwrite the signal asymmetry." << std::endl;
169  return;
170  }
171 
172  signalEvents_ = nSigEvents;
173  signalEvents_->name("signalEvents");
174  Double_t value = nSigEvents->value();
175  signalEvents_->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0));
176 
177  signalAsym_ = sigAsym;
178  signalAsym_->name("signalAsym");
179  signalAsym_->range(-1.0,1.0);
180 
181  forceAsym_ = forceAsym;
182 }
183 
185 {
186  if ( nBkgndEvents == 0 ) {
187  std::cerr << "ERROR in LauCPFitModel::setNBgkndEvents : The background yield LauParameter pointer is null." << std::endl;
188  gSystem->Exit(EXIT_FAILURE);
189  }
190 
191  if ( ! this->validBkgndClass( nBkgndEvents->name() ) ) {
192  std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : Invalid background class \"" << nBkgndEvents->name() << "\"." << std::endl;
193  std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl;
194  gSystem->Exit(EXIT_FAILURE);
195  }
196 
197  UInt_t bkgndID = this->bkgndClassID( nBkgndEvents->name() );
198 
199  if ( bkgndEvents_[bkgndID] != 0 ) {
200  std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background yield." << std::endl;
201  return;
202  }
203 
204  if ( bkgndAsym_[bkgndID] != 0 ) {
205  std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background asymmetry." << std::endl;
206  return;
207  }
208 
209  bkgndEvents_[bkgndID] = nBkgndEvents;
210  bkgndEvents_[bkgndID]->name( nBkgndEvents->name()+"Events" );
211  Double_t value = nBkgndEvents->value();
212  bkgndEvents_[bkgndID]->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0));
213 
214  bkgndAsym_[bkgndID] = new LauParameter(nBkgndEvents->name()+"Asym",0.0,-1.0,1.0,kTRUE);
215 }
216 
218 {
219  if ( nBkgndEvents == 0 ) {
220  std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : The background yield LauParameter pointer is null." << std::endl;
221  gSystem->Exit(EXIT_FAILURE);
222  }
223 
224  if ( bkgndAsym == 0 ) {
225  std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : The background asym LauParameter pointer is null." << std::endl;
226  gSystem->Exit(EXIT_FAILURE);
227  }
228 
229  if ( ! this->validBkgndClass( nBkgndEvents->name() ) ) {
230  std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : Invalid background class \"" << nBkgndEvents->name() << "\"." << std::endl;
231  std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl;
232  gSystem->Exit(EXIT_FAILURE);
233  }
234 
235  UInt_t bkgndID = this->bkgndClassID( nBkgndEvents->name() );
236 
237  if ( bkgndEvents_[bkgndID] != 0 ) {
238  std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background yield." << std::endl;
239  return;
240  }
241 
242  if ( bkgndAsym_[bkgndID] != 0 ) {
243  std::cerr << "ERROR in LauCPFitModel::setNBkgndEvents : You are trying to overwrite the background asymmetry." << std::endl;
244  return;
245  }
246 
247  bkgndEvents_[bkgndID] = nBkgndEvents;
248  bkgndEvents_[bkgndID]->name( nBkgndEvents->name()+"Events" );
249  Double_t value = nBkgndEvents->value();
250  bkgndEvents_[bkgndID]->range(-2.0*(TMath::Abs(value)+1.0), 2.0*(TMath::Abs(value)+1.0));
251 
252  bkgndAsym_[bkgndID] = bkgndAsym;
253  bkgndAsym_[bkgndID]->name( nBkgndEvents->name()+"Asym" );
254  bkgndAsym_[bkgndID]->range(-1.0,1.0);
255 }
256 
257 void LauCPFitModel::splitSignalComponent( const TH2* dpHisto, const Bool_t upperHalf, const Bool_t fluctuateBins, LauScfMap* scfMap )
258 {
259  if ( useSCF_ == kTRUE ) {
260  std::cerr << "ERROR in LauCPFitModel::splitSignalComponent : Have already setup SCF." << std::endl;
261  return;
262  }
263 
264  if ( dpHisto == 0 ) {
265  std::cerr << "ERROR in LauCPFitModel::splitSignalComponent : The histogram pointer is null." << std::endl;
266  return;
267  }
268 
269  const LauDaughters* daughters = negSigModel_->getDaughters();
270  scfFracHist_ = new LauEffModel( daughters, 0 );
271  scfFracHist_->setEffHisto( dpHisto, kTRUE, fluctuateBins, 0.0, 0.0, upperHalf, daughters->squareDP() );
272 
273  scfMap_ = scfMap;
274 
275  useSCF_ = kTRUE;
276  useSCFHist_ = kTRUE;
277 }
278 
279 void LauCPFitModel::splitSignalComponent( const Double_t scfFrac, const Bool_t fixed )
280 {
281  if ( useSCF_ == kTRUE ) {
282  std::cerr << "ERROR in LauCPFitModel::splitSignalComponent : Have already setup SCF." << std::endl;
283  return;
284  }
285 
286  scfFrac_.range( 0.0, 1.0 );
287  scfFrac_.value( scfFrac ); scfFrac_.initValue( scfFrac ); scfFrac_.genValue( scfFrac );
288  scfFrac_.fixed( fixed );
289 
290  useSCF_ = kTRUE;
291  useSCFHist_ = kFALSE;
292 }
293 
294 void LauCPFitModel::setBkgndDPModels(const TString& bkgndClass, LauAbsBkgndDPModel* negModel, LauAbsBkgndDPModel* posModel)
295 {
296  if ((negModel==0) || (posModel==0)) {
297  std::cerr << "ERROR in LauCPFitModel::setBkgndDPModels : One or both of the model pointers is null." << std::endl;
298  return;
299  }
300 
301  // check that this background name is valid
302  if ( ! this->validBkgndClass( bkgndClass) ) {
303  std::cerr << "ERROR in LauCPFitModel::setBkgndDPModel : Invalid background class \"" << bkgndClass << "\"." << std::endl;
304  std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl;
305  return;
306  }
307 
308  UInt_t bkgndID = this->bkgndClassID( bkgndClass );
309  negBkgndDPModels_[bkgndID] = negModel;
310  posBkgndDPModels_[bkgndID] = posModel;
311 
312  usingBkgnd_ = kTRUE;
313 }
314 
316 {
317  if ( tagged_ ) {
318  if (negPdf==0 || posPdf==0) {
319  std::cerr << "ERROR in LauCPFitModel::setSignalPdfs : One or both of the PDF pointers is null." << std::endl;
320  return;
321  }
322  } else {
323  // if we're doing an untagged analysis we will only use the negative PDFs
324  if ( negPdf==0 ) {
325  std::cerr << "ERROR in LauCPFitModel::setSignalPdfs : The negative PDF pointer is null." << std::endl;
326  return;
327  }
328  if ( posPdf!=0 ) {
329  std::cerr << "WARNING in LauCPFitModel::setSignalPdfs : Doing an untagged fit so will not use the positive PDF." << std::endl;
330  }
331  }
332  negSignalPdfs_.push_back(negPdf);
333  posSignalPdfs_.push_back(posPdf);
334 }
335 
337 {
338  if ( tagged_ ) {
339  if (negPdf==0 || posPdf==0) {
340  std::cerr << "ERROR in LauCPFitModel::setSCFPdfs : One or both of the PDF pointers is null." << std::endl;
341  return;
342  }
343  } else {
344  // if we're doing an untagged analysis we will only use the negative PDFs
345  if ( negPdf==0 ) {
346  std::cerr << "ERROR in LauCPFitModel::setSCFPdfs : The negative PDF pointer is null." << std::endl;
347  return;
348  }
349  if ( posPdf!=0 ) {
350  std::cerr << "WARNING in LauCPFitModel::setSCFPdfs : Doing an untagged fit so will not use the positive PDF." << std::endl;
351  }
352  }
353  negScfPdfs_.push_back(negPdf);
354  posScfPdfs_.push_back(posPdf);
355 }
356 
357 void LauCPFitModel::setBkgndPdfs(const TString& bkgndClass, LauAbsPdf* negPdf, LauAbsPdf* posPdf)
358 {
359  if ( tagged_ ) {
360  if (negPdf==0 || posPdf==0) {
361  std::cerr << "ERROR in LauCPFitModel::setBkgndPdfs : One or both of the PDF pointers is null." << std::endl;
362  return;
363  }
364  } else {
365  // if we're doing an untagged analysis we will only use the negative PDFs
366  if ( negPdf==0 ) {
367  std::cerr << "ERROR in LauCPFitModel::setBkgndPdfs : The negative PDF pointer is null." << std::endl;
368  return;
369  }
370  if ( posPdf!=0 ) {
371  std::cerr << "WARNING in LauCPFitModel::setBkgndPdfs : Doing an untagged fit so will not use the positive PDF." << std::endl;
372  }
373  }
374 
375  // check that this background name is valid
376  if ( ! this->validBkgndClass( bkgndClass ) ) {
377  std::cerr << "ERROR in LauCPFitModel::setBkgndPdfs : Invalid background class \"" << bkgndClass << "\"." << std::endl;
378  std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl;
379  return;
380  }
381 
382  UInt_t bkgndID = this->bkgndClassID( bkgndClass );
383  negBkgndPdfs_[bkgndID].push_back(negPdf);
384  posBkgndPdfs_[bkgndID].push_back(posPdf);
385 
386  usingBkgnd_ = kTRUE;
387 }
388 
390 {
391  // Resize the coeffPars vector if not already done
392  if ( coeffPars_.empty() ) {
393  const UInt_t nNegAmp = negSigModel_->getnTotAmp();
394  const UInt_t nPosAmp = posSigModel_->getnTotAmp();
395  if ( nNegAmp != nPosAmp ) {
396  std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : Unequal number of signal DP components in the negative and positive models: " << nNegAmp << " != " << nPosAmp << std::endl;
397  gSystem->Exit(EXIT_FAILURE);
398  }
399  coeffPars_.resize( nNegAmp );
400  for (std::vector<LauAbsCoeffSet*>::iterator iter = coeffPars_.begin(); iter != coeffPars_.end(); ++iter) {
401  (*iter) = 0;
402  }
403  fitFracAsymm_.resize( nNegAmp );
404  acp_.resize( nNegAmp );
405  }
406 
407  // Is there a component called compName in the signal model?
408  TString compName(coeffSet->name());
409  TString conjName = negSigModel_->getConjResName(compName);
410  const Int_t negIndex = negSigModel_->resonanceIndex(compName);
411  const Int_t posIndex = posSigModel_->resonanceIndex(conjName);
412  if ( negIndex < 0 ) {
413  std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : " << negParent_ << " signal DP model doesn't contain component \"" << compName << "\"." << std::endl;
414  return;
415  }
416  if ( posIndex < 0 ) {
417  std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : " << posParent_ << " signal DP model doesn't contain component \"" << conjName << "\"." << std::endl;
418  return;
419  }
420  if ( posIndex != negIndex ) {
421  std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : " << negParent_ << " signal DP model and " << posParent_ << " signal DP model have different indices for components \"" << compName << "\" and \"" << conjName << "\"." << std::endl;
422  return;
423  }
424 
425  // Do we already have it in our list of names?
426  if ( coeffPars_[negIndex] != 0 && coeffPars_[negIndex]->name() == compName) {
427  std::cerr << "ERROR in LauCPFitModel::setAmpCoeffSet : Have already set coefficients for \"" << compName << "\"." << std::endl;
428  return;
429  }
430 
431  coeffSet->index(negIndex);
432  coeffPars_[negIndex] = coeffSet;
433 
434  TString parName = coeffSet->baseName(); parName += "FitFracAsym";
435  fitFracAsymm_[negIndex] = LauParameter(parName, 0.0, -1.0, 1.0);
436 
437  acp_[negIndex] = coeffSet->acp();
438 
439  ++nSigComp_;
440 
441  std::cout << "INFO in LauCPFitModel::setAmpCoeffSet : Added coefficients for component \"" << compName << "\" to the fit model." << std::endl;
442  coeffSet->printParValues();
443 }
444 
446 {
447  // Initialisation
448  if (!this->useDP() && negSignalPdfs_.empty()) {
449  std::cerr << "ERROR in LauCPFitModel::initialise : Signal model doesn't exist for any variable." << std::endl;
450  gSystem->Exit(EXIT_FAILURE);
451  }
452 
453  if ( this->useDP() ) {
454  // Check that we have all the Dalitz-plot models
455  if ((negSigModel_ == 0) || (posSigModel_ == 0)) {
456  std::cerr << "ERROR in LauCPFitModel::initialise : the pointer to one (neg or pos) of the signal DP models is null.\n";
457  std::cerr << " : Removing the Dalitz Plot from the model." << std::endl;
458  this->useDP(kFALSE);
459  }
460  if ( usingBkgnd_ ) {
461  if ( negBkgndDPModels_.empty() || posBkgndDPModels_.empty() ) {
462  std::cerr << "ERROR in LauCPFitModel::initialise : No background DP models found.\n";
463  std::cerr << " : Removing the Dalitz plot from the model." << std::endl;
464  this->useDP(kFALSE);
465  }
466  for (LauBkgndDPModelList::const_iterator dpmodel_iter = negBkgndDPModels_.begin(); dpmodel_iter != negBkgndDPModels_.end(); ++dpmodel_iter ) {
467  if ( (*dpmodel_iter) == 0 ) {
468  std::cerr << "ERROR in LauCPFitModel::initialise : The pointer to one of the background DP models is null.\n";
469  std::cerr << " : Removing the Dalitz Plot from the model." << std::endl;
470  this->useDP(kFALSE);
471  break;
472  }
473  }
474  for (LauBkgndDPModelList::const_iterator dpmodel_iter = posBkgndDPModels_.begin(); dpmodel_iter != posBkgndDPModels_.end(); ++dpmodel_iter ) {
475  if ( (*dpmodel_iter) == 0 ) {
476  std::cerr << "ERROR in LauCPFitModel::initialise : The pointer to one of the background DP models is null.\n";
477  std::cerr << " : Removing the Dalitz Plot from the model." << std::endl;
478  this->useDP(kFALSE);
479  break;
480  }
481  }
482  }
483 
484  // Need to check that the number of components we have and that the dynamics has matches up
485  const UInt_t nNegAmp = negSigModel_->getnTotAmp();
486  const UInt_t nPosAmp = posSigModel_->getnTotAmp();
487  if ( nNegAmp != nPosAmp ) {
488  std::cerr << "ERROR in LauCPFitModel::initialise : Unequal number of signal DP components in the negative and positive models: " << nNegAmp << " != " << nPosAmp << std::endl;
489  gSystem->Exit(EXIT_FAILURE);
490  }
491  if ( nNegAmp != nSigComp_ ) {
492  std::cerr << "ERROR in LauCPFitModel::initialise : Number of signal DP components in the model (" << nNegAmp << ") not equal to number of coefficients supplied (" << nSigComp_ << ")." << std::endl;
493  gSystem->Exit(EXIT_FAILURE);
494  }
495 
496 
497  // From the initial parameter values calculate the coefficients
498  // so they can be passed to the signal model
499  this->updateCoeffs();
500 
501  // If all is well, go ahead and initialise them
502  this->initialiseDPModels();
503  }
504 
505  // Next check that, if a given component is being used we've got the
506  // right number of PDFs for all the variables involved
507  // TODO - should probably check variable names and so on as well
508 
509  UInt_t nsigpdfvars(0);
510  for ( LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter ) {
511  std::vector<TString> varNames = (*pdf_iter)->varNames();
512  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
513  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
514  ++nsigpdfvars;
515  }
516  }
517  }
518  if (useSCF_) {
519  UInt_t nscfpdfvars(0);
520  for ( LauPdfList::const_iterator pdf_iter = negScfPdfs_.begin(); pdf_iter != negScfPdfs_.end(); ++pdf_iter ) {
521  std::vector<TString> varNames = (*pdf_iter)->varNames();
522  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
523  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
524  ++nscfpdfvars;
525  }
526  }
527  }
528  if (nscfpdfvars != nsigpdfvars) {
529  std::cerr << "ERROR in LauCPFitModel::initialise : There are " << nsigpdfvars << " TM signal PDF variables but " << nscfpdfvars << " SCF signal PDF variables." << std::endl;
530  gSystem->Exit(EXIT_FAILURE);
531  }
532  }
533  if (usingBkgnd_) {
534  for (LauBkgndPdfsList::const_iterator bgclass_iter = negBkgndPdfs_.begin(); bgclass_iter != negBkgndPdfs_.end(); ++bgclass_iter) {
535  UInt_t nbkgndpdfvars(0);
536  const LauPdfList& pdfList = (*bgclass_iter);
537  for ( LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter ) {
538  std::vector<TString> varNames = (*pdf_iter)->varNames();
539  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
540  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
541  ++nbkgndpdfvars;
542  }
543  }
544  }
545  if (nbkgndpdfvars != nsigpdfvars) {
546  std::cerr << "ERROR in LauCPFitModel::initialise : There are " << nsigpdfvars << " signal PDF variables but " << nbkgndpdfvars << " bkgnd PDF variables." << std::endl;
547  gSystem->Exit(EXIT_FAILURE);
548  }
549  }
550  }
551 
552  // Clear the vectors of parameter information so we can start from scratch
553  this->clearFitParVectors();
554 
555  // Set the fit parameters for signal and background models
556  this->setSignalDPParameters();
557 
558  // Set the fit parameters for the various extra PDFs
559  this->setExtraPdfParameters();
560 
561  // Set the initial bg and signal events
562  this->setFitNEvents();
563 
564  // Check that we have the expected number of fit variables
565  const LauParameterPList& fitVars = this->fitPars();
566  if (fitVars.size() != (nSigDPPar_ + nExtraPdfPar_ + nNormPar_)) {
567  std::cerr << "ERROR in LauCPFitModel::initialise : Number of fit parameters not of expected size. Exiting" << std::endl;
568  gSystem->Exit(EXIT_FAILURE);
569  }
570 
571  this->setExtraNtupleVars();
572 }
573 
575 {
576  //std::cout << "INFO in LauCPFitModel::recalculateNormalizationInDPModels : Recalc Norm in DP model" << std::endl;
581 }
582 
584 {
585  std::cout << "INFO in LauCPFitModel::initialiseDPModels : Initialising signal DP model" << std::endl;
588 
589  if (usingBkgnd_ == kTRUE) {
590  for (LauBkgndDPModelList::iterator iter = negBkgndDPModels_.begin(); iter != negBkgndDPModels_.end(); ++iter) {
591  (*iter)->initialise();
592  }
593  for (LauBkgndDPModelList::iterator iter = posBkgndDPModels_.begin(); iter != posBkgndDPModels_.end(); ++iter) {
594  (*iter)->initialise();
595  }
596  }
597 }
598 
600 {
601  // Set the fit parameters for the signal model.
602 
603  nSigDPPar_ = 0;
604  if ( ! this->useDP() ) {
605  return;
606  }
607 
608  std::cout << "INFO in LauCPFitModel::setSignalDPParameters : Setting the initial fit parameters for the signal DP model." << std::endl;
609 
610  // Place isobar coefficient parameters in vector of fit variables
611  LauParameterPList& fitVars = this->fitPars();
612  for (UInt_t i = 0; i < nSigComp_; i++) {
613  LauParameterPList pars = coeffPars_[i]->getParameters();
614  for (LauParameterPList::iterator iter = pars.begin(); iter != pars.end(); ++iter) {
615  if ( !(*iter)->clone() ) {
616  fitVars.push_back(*iter);
617  ++nSigDPPar_;
618  }
619  }
620  }
621 
622  // Obtain the resonance parameters and place them in the vector of fit variables and in a separate vector
623  // Need to make sure that they are unique because some might appear in both DP models
624  LauParameterPSet& resVars = this->resPars();
625  resVars.clear();
626 
629 
630  for ( LauParameterPList::iterator iter = negSigDPPars.begin(); iter != negSigDPPars.end(); ++iter ) {
631  if ( resVars.insert(*iter).second ) {
632  fitVars.push_back(*iter);
633  ++nSigDPPar_;
634  }
635  }
636  for ( LauParameterPList::iterator iter = posSigDPPars.begin(); iter != posSigDPPars.end(); ++iter ) {
637  if ( resVars.insert(*iter).second ) {
638  fitVars.push_back(*iter);
639  ++nSigDPPar_;
640  }
641  }
642 }
643 
645 {
646  // Include all the parameters of the PDF in the fit
647  // NB all of them are passed to the fit, even though some have been fixed through parameter.fixed(kTRUE)
648  // With the new "cloned parameter" scheme only "original" parameters are passed to the fit.
649  // Their clones are updated automatically when the originals are updated.
650 
651  nExtraPdfPar_ = 0;
652 
654  if ( tagged_ ) {
656  }
657 
658  if (useSCF_ == kTRUE) {
660  if ( tagged_ ) {
662  }
663  }
664 
665  if (usingBkgnd_ == kTRUE) {
666  for (LauBkgndPdfsList::iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) {
667  nExtraPdfPar_ += this->addFitParameters(*iter);
668  }
669  if ( tagged_ ) {
670  for (LauBkgndPdfsList::iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) {
671  nExtraPdfPar_ += this->addFitParameters(*iter);
672  }
673  }
674  }
675 }
676 
678 {
679  if ( signalEvents_ == 0 ) {
680  std::cerr << "ERROR in LauCPFitModel::setFitNEvents : Signal yield not defined." << std::endl;
681  return;
682  }
683  nNormPar_ = 0;
684 
685  // initialise the total number of events to be the sum of all the hypotheses
686  Double_t nTotEvts = signalEvents_->value();
687  for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) {
688  nTotEvts += (*iter)->value();
689  if ( (*iter) == 0 ) {
690  std::cerr << "ERROR in LauCPFitModel::setFitNEvents : Background yield not defined." << std::endl;
691  return;
692  }
693  }
694  this->eventsPerExpt(TMath::FloorNint(nTotEvts));
695 
696  LauParameterPList& fitVars = this->fitPars();
697 
698  // if doing an extended ML fit add the number of signal events into the fit parameters
699  if (this->doEMLFit()) {
700  std::cout << "INFO in LauCPFitModel::setFitNEvents : Initialising number of events for signal and background components..." << std::endl;
701  // add the signal fraction to the list of fit parameters
702  if(!signalEvents_->fixed()) {
703  fitVars.push_back(signalEvents_);
704  ++nNormPar_;
705  }
706  } else {
707  std::cout << "INFO in LauCPFitModel::setFitNEvents : Initialising number of events for background components (and hence signal)..." << std::endl;
708  }
709 
710  // if not using the DP in the model we need an explicit signal asymmetry parameter
711  if (this->useDP() == kFALSE) {
712  if(!signalAsym_->fixed()) {
713  fitVars.push_back(signalAsym_);
714  ++nNormPar_;
715  }
716  }
717 
718  if (useSCF_ && !useSCFHist_) {
719  if(!scfFrac_.fixed()) {
720  fitVars.push_back(&scfFrac_);
721  ++nNormPar_;
722  }
723  }
724 
725  if (usingBkgnd_ == kTRUE) {
726  for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) {
727  LauParameter* parameter = (*iter);
728  if(!parameter->fixed()) {
729  fitVars.push_back(parameter);
730  ++nNormPar_;
731  }
732  }
733  for (LauBkgndYieldList::iterator iter = bkgndAsym_.begin(); iter != bkgndAsym_.end(); ++iter) {
734  LauParameter* parameter = (*iter);
735  if(!parameter->fixed()) {
736  fitVars.push_back(parameter);
737  ++nNormPar_;
738  }
739  }
740  }
741 }
742 
744 {
745  // Set-up other parameters derived from the fit results, e.g. fit fractions.
746 
747  if (this->useDP() != kTRUE) {
748  return;
749  }
750 
751  // First clear the vectors so we start from scratch
752  this->clearExtraVarVectors();
753 
754  LauParameterList& extraVars = this->extraPars();
755 
756  // Add the positive and negative fit fractions for each signal component
758  if (negFitFrac_.size() != nSigComp_) {
759  std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << negFitFrac_.size() << std::endl;
760  gSystem->Exit(EXIT_FAILURE);
761  }
762  for (UInt_t i(0); i<nSigComp_; ++i) {
763  if (negFitFrac_[i].size() != nSigComp_) {
764  std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << negFitFrac_[i].size() << std::endl;
765  gSystem->Exit(EXIT_FAILURE);
766  }
767  }
768 
770  if (posFitFrac_.size() != nSigComp_) {
771  std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << posFitFrac_.size() << std::endl;
772  gSystem->Exit(EXIT_FAILURE);
773  }
774  for (UInt_t i(0); i<nSigComp_; ++i) {
775  if (posFitFrac_[i].size() != nSigComp_) {
776  std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << posFitFrac_[i].size() << std::endl;
777  gSystem->Exit(EXIT_FAILURE);
778  }
779  }
780 
781  // Add the positive and negative fit fractions that have not been corrected for the efficiency for each signal component
783  if (negFitFracEffUnCorr_.size() != nSigComp_) {
784  std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << negFitFracEffUnCorr_.size() << std::endl;
785  gSystem->Exit(EXIT_FAILURE);
786  }
787  for (UInt_t i(0); i<nSigComp_; ++i) {
788  if (negFitFracEffUnCorr_[i].size() != nSigComp_) {
789  std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << negFitFracEffUnCorr_[i].size() << std::endl;
790  gSystem->Exit(EXIT_FAILURE);
791  }
792  }
793 
795  if (posFitFracEffUnCorr_.size() != nSigComp_) {
796  std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << posFitFracEffUnCorr_.size() << std::endl;
797  gSystem->Exit(EXIT_FAILURE);
798  }
799  for (UInt_t i(0); i<nSigComp_; ++i) {
800  if (posFitFracEffUnCorr_[i].size() != nSigComp_) {
801  std::cerr << "ERROR in LauCPFitModel::setExtraNtupleVars : Initial Fit Fraction array of unexpected dimension: " << posFitFracEffUnCorr_[i].size() << std::endl;
802  gSystem->Exit(EXIT_FAILURE);
803  }
804  }
805 
806  for (UInt_t i(0); i<nSigComp_; ++i) {
807  for (UInt_t j(i); j<nSigComp_; ++j) {
808  TString name = negFitFrac_[i][j].name();
809  name.Insert( name.Index("FitFrac"), "Neg" );
810  negFitFrac_[i][j].name(name);
811  extraVars.push_back(negFitFrac_[i][j]);
812 
813  name = posFitFrac_[i][j].name();
814  name.Insert( name.Index("FitFrac"), "Pos" );
815  posFitFrac_[i][j].name(name);
816  extraVars.push_back(posFitFrac_[i][j]);
817 
818  name = negFitFracEffUnCorr_[i][j].name();
819  name.Insert( name.Index("FitFrac"), "Neg" );
820  negFitFracEffUnCorr_[i][j].name(name);
821  extraVars.push_back(negFitFracEffUnCorr_[i][j]);
822 
823  name = posFitFracEffUnCorr_[i][j].name();
824  name.Insert( name.Index("FitFrac"), "Pos" );
825  posFitFracEffUnCorr_[i][j].name(name);
826  extraVars.push_back(posFitFracEffUnCorr_[i][j]);
827  }
828  }
829 
830  // Store any extra parameters/quantities from the DP model (e.g. K-matrix total fit fractions)
831  std::vector<LauParameter> negExtraPars = negSigModel_->getExtraParameters();
832  std::vector<LauParameter>::iterator negExtraIter;
833  for (negExtraIter = negExtraPars.begin(); negExtraIter != negExtraPars.end(); ++negExtraIter) {
834  LauParameter negExtraParameter = (*negExtraIter);
835  extraVars.push_back(negExtraParameter);
836  }
837 
838  std::vector<LauParameter> posExtraPars = posSigModel_->getExtraParameters();
839  std::vector<LauParameter>::iterator posExtraIter;
840  for (posExtraIter = posExtraPars.begin(); posExtraIter != posExtraPars.end(); ++posExtraIter) {
841  LauParameter posExtraParameter = (*posExtraIter);
842  extraVars.push_back(posExtraParameter);
843  }
844 
845  // Now add in the DP efficiency value
846  Double_t initMeanEff = negSigModel_->getMeanEff().initValue();
847  negMeanEff_.value(initMeanEff);
848  negMeanEff_.genValue(initMeanEff);
849  negMeanEff_.initValue(initMeanEff);
850  extraVars.push_back(negMeanEff_);
851 
852  initMeanEff = posSigModel_->getMeanEff().initValue();
853  posMeanEff_.value(initMeanEff);
854  posMeanEff_.genValue(initMeanEff);
855  posMeanEff_.initValue(initMeanEff);
856  extraVars.push_back(posMeanEff_);
857 
858  // Also add in the DP rates
859  Double_t initDPRate = negSigModel_->getDPRate().initValue();
860  negDPRate_.value(initDPRate);
861  negDPRate_.genValue(initDPRate);
862  negDPRate_.initValue(initDPRate);
863  extraVars.push_back(negDPRate_);
864 
865  initDPRate = posSigModel_->getDPRate().initValue();
866  posDPRate_.value(initDPRate);
867  posDPRate_.genValue(initDPRate);
868  posDPRate_.initValue(initDPRate);
869  extraVars.push_back(posDPRate_);
870 
871  // Calculate the CPC and CPV Fit Fractions, ACPs and FitFrac asymmetries
872  this->calcExtraFractions(kTRUE);
873  this->calcAsymmetries(kTRUE);
874 
875  // Add the CP violating and CP conserving fit fractions for each signal component
876  for (UInt_t i = 0; i < nSigComp_; i++) {
877  for (UInt_t j = i; j < nSigComp_; j++) {
878  extraVars.push_back(CPVFitFrac_[i][j]);
879  }
880  }
881  for (UInt_t i = 0; i < nSigComp_; i++) {
882  for (UInt_t j = i; j < nSigComp_; j++) {
883  extraVars.push_back(CPCFitFrac_[i][j]);
884  }
885  }
886 
887  // Add the Fit Fraction asymmetry for each signal component
888  for (UInt_t i = 0; i < nSigComp_; i++) {
889  extraVars.push_back(fitFracAsymm_[i]);
890  }
891 
892  // Add the calculated CP asymmetry for each signal component
893  for (UInt_t i = 0; i < nSigComp_; i++) {
894  extraVars.push_back(acp_[i]);
895  }
896 }
897 
898 void LauCPFitModel::calcExtraFractions(Bool_t initValues)
899 {
900  // Calculate the CP-conserving and CP-violating fit fractions
901 
902  if (initValues) {
903  // create the structure
904  CPCFitFrac_.clear();
905  CPVFitFrac_.clear();
906  CPCFitFrac_.resize(nSigComp_);
907  CPVFitFrac_.resize(nSigComp_);
908  for (UInt_t i(0); i<nSigComp_; ++i) {
909  CPCFitFrac_[i].resize(nSigComp_);
910  CPVFitFrac_[i].resize(nSigComp_);
911 
912  for (UInt_t j(i); j<nSigComp_; ++j) {
913  TString name = negFitFrac_[i][j].name();
914  name.Replace( name.Index("Neg"), 3, "CPC" );
915  CPCFitFrac_[i][j].name( name );
916  CPCFitFrac_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
917 
918  name = negFitFrac_[i][j].name();
919  name.Replace( name.Index("Neg"), 3, "CPV" );
920  CPVFitFrac_[i][j].name( name );
921  CPVFitFrac_[i][j].valueAndRange( 0.0, -100.0, 100.0 );
922  }
923  }
924  }
925 
926  Double_t denom = negDPRate_.value() + posDPRate_.value();
927 
928  for (UInt_t i(0); i<nSigComp_; ++i) {
929  for (UInt_t j(i); j<nSigComp_; ++j) {
930 
931  Double_t negTerm = negFitFrac_[i][j].value()*negDPRate_.value();
932  Double_t posTerm = posFitFrac_[i][j].value()*posDPRate_.value();
933 
934  Double_t cpcFitFrac = (negTerm + posTerm)/denom;
935  Double_t cpvFitFrac = (negTerm - posTerm)/denom;
936 
937  CPCFitFrac_[i][j].value(cpcFitFrac);
938  CPVFitFrac_[i][j].value(cpvFitFrac);
939 
940  if (initValues) {
941  CPCFitFrac_[i][j].genValue(cpcFitFrac);
942  CPCFitFrac_[i][j].initValue(cpcFitFrac);
943 
944  CPVFitFrac_[i][j].genValue(cpvFitFrac);
945  CPVFitFrac_[i][j].initValue(cpvFitFrac);
946  }
947  }
948  }
949 }
950 
951 void LauCPFitModel::calcAsymmetries(Bool_t initValues)
952 {
953  // Calculate the CP asymmetries
954  // Also calculate the fit fraction asymmetries
955 
956  for (UInt_t i = 0; i < nSigComp_; i++) {
957 
958  acp_[i] = coeffPars_[i]->acp();
959 
960  LauAsymmCalc asymmCalc(negFitFrac_[i][i].value(), posFitFrac_[i][i].value());
961  Double_t asym = asymmCalc.getAsymmetry();
962  fitFracAsymm_[i].value(asym);
963  if (initValues) {
964  fitFracAsymm_[i].genValue(asym);
965  fitFracAsymm_[i].initValue(asym);
966  }
967  }
968 }
969 
970 void LauCPFitModel::finaliseFitResults(const TString& tablePrefixName)
971 {
972  // Retrieve parameters from the fit results for calculations and toy generation
973  // and eventually store these in output root ntuples/text files
974 
975  // Now take the fit parameters and update them as necessary
976  // i.e. to make mag > 0.0, phase in the right range.
977  // This function will also calculate any other values, such as the
978  // fit fractions, using any errors provided by fitParErrors as appropriate.
979  // Also obtain the pull values: (measured - generated)/(average error)
980 
981  if (this->useDP() == kTRUE) {
982  for (UInt_t i = 0; i < nSigComp_; ++i) {
983  // Check whether we have "a/b > 0.0", and phases in the right range
984  coeffPars_[i]->finaliseValues();
985  }
986  }
987 
988  // update the pulls on the event fractions and asymmetries
989  if (this->doEMLFit()) {
991  }
992  if (this->useDP() == kFALSE) {
994  }
995  if (useSCF_ && !useSCFHist_) {
997  }
998  if (usingBkgnd_ == kTRUE) {
999  for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) {
1000  (*iter)->updatePull();
1001  }
1002  for (LauBkgndYieldList::iterator iter = bkgndAsym_.begin(); iter != bkgndAsym_.end(); ++iter) {
1003  (*iter)->updatePull();
1004  }
1005  }
1006 
1007  // Update the pulls on all the extra PDFs' parameters
1010  if (useSCF_ == kTRUE) {
1013  }
1014  if (usingBkgnd_ == kTRUE) {
1015  for (LauBkgndPdfsList::iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) {
1016  this->updateFitParameters(*iter);
1017  }
1018  for (LauBkgndPdfsList::iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) {
1019  this->updateFitParameters(*iter);
1020  }
1021  }
1022 
1023  // Fill the fit results to the ntuple
1024 
1025  // update the coefficients and then calculate the fit fractions and ACP's
1026  if (this->useDP() == kTRUE) {
1027  this->updateCoeffs();
1030 
1031  LauParArray negFitFrac = negSigModel_->getFitFractions();
1032  if (negFitFrac.size() != nSigComp_) {
1033  std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << negFitFrac.size() << std::endl;
1034  gSystem->Exit(EXIT_FAILURE);
1035  }
1036  for (UInt_t i(0); i<nSigComp_; ++i) {
1037  if (negFitFrac[i].size() != nSigComp_) {
1038  std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << negFitFrac[i].size() << std::endl;
1039  gSystem->Exit(EXIT_FAILURE);
1040  }
1041  }
1042 
1043  LauParArray posFitFrac = posSigModel_->getFitFractions();
1044  if (posFitFrac.size() != nSigComp_) {
1045  std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << posFitFrac.size() << std::endl;
1046  gSystem->Exit(EXIT_FAILURE);
1047  }
1048  for (UInt_t i(0); i<nSigComp_; ++i) {
1049  if (posFitFrac[i].size() != nSigComp_) {
1050  std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << posFitFrac[i].size() << std::endl;
1051  gSystem->Exit(EXIT_FAILURE);
1052  }
1053  }
1054 
1056  if (negFitFracEffUnCorr.size() != nSigComp_) {
1057  std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << negFitFracEffUnCorr.size() << std::endl;
1058  gSystem->Exit(EXIT_FAILURE);
1059  }
1060  for (UInt_t i(0); i<nSigComp_; ++i) {
1061  if (negFitFracEffUnCorr[i].size() != nSigComp_) {
1062  std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << negFitFracEffUnCorr[i].size() << std::endl;
1063  gSystem->Exit(EXIT_FAILURE);
1064  }
1065  }
1066 
1068  if (posFitFracEffUnCorr.size() != nSigComp_) {
1069  std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << posFitFracEffUnCorr.size() << std::endl;
1070  gSystem->Exit(EXIT_FAILURE);
1071  }
1072  for (UInt_t i(0); i<nSigComp_; ++i) {
1073  if (posFitFracEffUnCorr[i].size() != nSigComp_) {
1074  std::cerr << "ERROR in LauCPFitModel::finaliseFitResults : Fit Fraction array of unexpected dimension: " << posFitFracEffUnCorr[i].size() << std::endl;
1075  gSystem->Exit(EXIT_FAILURE);
1076  }
1077  }
1078 
1079  for (UInt_t i(0); i<nSigComp_; ++i) {
1080  for (UInt_t j(i); j<nSigComp_; ++j) {
1081  negFitFrac_[i][j].value(negFitFrac[i][j].value());
1082  posFitFrac_[i][j].value(posFitFrac[i][j].value());
1083  negFitFracEffUnCorr_[i][j].value(negFitFracEffUnCorr[i][j].value());
1084  posFitFracEffUnCorr_[i][j].value(posFitFracEffUnCorr[i][j].value());
1085  }
1086  }
1087 
1092 
1093  this->calcExtraFractions();
1094  this->calcAsymmetries();
1095 
1096  // Then store the final fit parameters, and any extra parameters for
1097  // the signal model (e.g. fit fractions, FF asymmetries, ACPs, mean efficiency and DP rate)
1098 
1099  this->clearExtraVarVectors();
1100  LauParameterList& extraVars = this->extraPars();
1101 
1102  // Add the positive and negative fit fractions for each signal component
1103  for (UInt_t i(0); i<nSigComp_; ++i) {
1104  for (UInt_t j(i); j<nSigComp_; ++j) {
1105  extraVars.push_back(negFitFrac_[i][j]);
1106  extraVars.push_back(posFitFrac_[i][j]);
1107  extraVars.push_back(negFitFracEffUnCorr_[i][j]);
1108  extraVars.push_back(posFitFracEffUnCorr_[i][j]);
1109  }
1110  }
1111 
1112  // Store any extra parameters/quantities from the DP model (e.g. K-matrix total fit fractions)
1113  std::vector<LauParameter> negExtraPars = negSigModel_->getExtraParameters();
1114  std::vector<LauParameter>::iterator negExtraIter;
1115  for (negExtraIter = negExtraPars.begin(); negExtraIter != negExtraPars.end(); ++negExtraIter) {
1116  LauParameter negExtraParameter = (*negExtraIter);
1117  extraVars.push_back(negExtraParameter);
1118  }
1119 
1120  std::vector<LauParameter> posExtraPars = posSigModel_->getExtraParameters();
1121  std::vector<LauParameter>::iterator posExtraIter;
1122  for (posExtraIter = posExtraPars.begin(); posExtraIter != posExtraPars.end(); ++posExtraIter) {
1123  LauParameter posExtraParameter = (*posExtraIter);
1124  extraVars.push_back(posExtraParameter);
1125  }
1126 
1127  extraVars.push_back(negMeanEff_);
1128  extraVars.push_back(posMeanEff_);
1129  extraVars.push_back(negDPRate_);
1130  extraVars.push_back(posDPRate_);
1131 
1132  for (UInt_t i = 0; i < nSigComp_; i++) {
1133  for (UInt_t j(i); j<nSigComp_; ++j) {
1134  extraVars.push_back(CPVFitFrac_[i][j]);
1135  }
1136  }
1137  for (UInt_t i = 0; i < nSigComp_; i++) {
1138  for (UInt_t j(i); j<nSigComp_; ++j) {
1139  extraVars.push_back(CPCFitFrac_[i][j]);
1140  }
1141  }
1142  for (UInt_t i(0); i<nSigComp_; ++i) {
1143  extraVars.push_back(fitFracAsymm_[i]);
1144  }
1145  for (UInt_t i(0); i<nSigComp_; ++i) {
1146  extraVars.push_back(acp_[i]);
1147  }
1148 
1149  this->printFitFractions(std::cout);
1150  this->printAsymmetries(std::cout);
1151  }
1152 
1153  const LauParameterPList& fitVars = this->fitPars();
1154  const LauParameterList& extraVars = this->extraPars();
1155  LauFitNtuple* ntuple = this->fitNtuple();
1156  ntuple->storeParsAndErrors(fitVars, extraVars);
1157 
1158  // find out the correlation matrix for the parameters
1159  ntuple->storeCorrMatrix(this->iExpt(), this->nll(), this->fitStatus(), this->covarianceMatrix());
1160 
1161  // Fill the data into ntuple
1162  ntuple->updateFitNtuple();
1163 
1164  // Print out the partial fit fractions, phases and the
1165  // averaged efficiency, reweighted by the dynamics (and anything else)
1166  if (this->writeLatexTable()) {
1167  TString sigOutFileName(tablePrefixName);
1168  sigOutFileName += "_"; sigOutFileName += this->iExpt(); sigOutFileName += "Expt.tex";
1169  this->writeOutTable(sigOutFileName);
1170  }
1171 }
1172 
1173 void LauCPFitModel::printFitFractions(std::ostream& output)
1174 {
1175  // Print out Fit Fractions, total DP rate and mean efficiency
1176  // First for the B- events
1177  for (UInt_t i = 0; i < nSigComp_; i++) {
1178  const TString compName(coeffPars_[i]->name());
1179  output << negParent_ << " FitFraction for component " << i << " (" << compName << ") = " << negFitFrac_[i][i] << std::endl;
1180  }
1181  output << negParent_ << " overall DP rate (integral of matrix element squared) = " << negDPRate_ << std::endl;
1182  output << negParent_ << " average efficiency weighted by whole DP dynamics = " << negMeanEff_ << std::endl;
1183 
1184  // Then for the positive sample
1185  for (UInt_t i = 0; i < nSigComp_; i++) {
1186  const TString compName(coeffPars_[i]->name());
1187  const TString conjName(negSigModel_->getConjResName(compName));
1188  output << posParent_ << " FitFraction for component " << i << " (" << conjName << ") = " << posFitFrac_[i][i] << std::endl;
1189  }
1190  output << posParent_ << " overall DP rate (integral of matrix element squared) = " << posDPRate_ << std::endl;
1191  output << posParent_ << " average efficiency weighted by whole DP dynamics = " << posMeanEff_ << std::endl;
1192 }
1193 
1194 void LauCPFitModel::printAsymmetries(std::ostream& output)
1195 {
1196  for (UInt_t i = 0; i < nSigComp_; i++) {
1197  const TString compName(coeffPars_[i]->name());
1198  output << "Fit Fraction asymmetry for component " << i << " (" << compName << ") = " << fitFracAsymm_[i] << std::endl;
1199  }
1200  for (UInt_t i = 0; i < nSigComp_; i++) {
1201  const TString compName(coeffPars_[i]->name());
1202  output << "ACP for component " << i << " (" << compName << ") = " << acp_[i] << std::endl;
1203  }
1204 }
1205 
1206 void LauCPFitModel::writeOutTable(const TString& outputFile)
1207 {
1208  // Write out the results of the fit to a tex-readable table
1209  // TODO - need to include the yields in this table
1210  std::ofstream fout(outputFile);
1211  LauPrint print;
1212 
1213  std::cout << "INFO in LauCPFitModel::writeOutTable : Writing out results of the fit to the tex file " << outputFile << std::endl;
1214 
1215  if (this->useDP() == kTRUE) {
1216  // print the fit coefficients in one table
1217  coeffPars_.front()->printTableHeading(fout);
1218  for (UInt_t i = 0; i < nSigComp_; i++) {
1219  coeffPars_[i]->printTableRow(fout);
1220  }
1221  fout << "\\hline" << std::endl;
1222  fout << "\\end{tabular}" << std::endl << std::endl;
1223 
1224  // print the fit fractions and asymmetries in another
1225  fout << "\\begin{tabular}{|l|c|c|c|c|}" << std::endl;
1226  fout << "\\hline" << std::endl;
1227  fout << "Component & " << negParent_ << " Fit Fraction & " << posParent_ << " Fit Fraction & Fit Fraction Asymmetry & ACP \\\\" << std::endl;
1228  fout << "\\hline" << std::endl;
1229 
1230  Double_t negFitFracSum(0.0);
1231  Double_t posFitFracSum(0.0);
1232 
1233  for (UInt_t i = 0; i < nSigComp_; i++) {
1234  TString resName = coeffPars_[i]->name();
1235  resName = resName.ReplaceAll("_", "\\_");
1236 
1237  Double_t negFitFrac = negFitFrac_[i][i].value();
1238  Double_t posFitFrac = posFitFrac_[i][i].value();
1239  negFitFracSum += negFitFrac;
1240  posFitFracSum += posFitFrac;
1241 
1242  Double_t fitFracAsymm = fitFracAsymm_[i].value();
1243 
1244  Double_t acp = acp_[i].value();
1245  Double_t acpErr = acp_[i].error();
1246 
1247  fout << resName << " & $";
1248 
1249  print.printFormat(fout, negFitFrac);
1250  fout << "$ & $";
1251  print.printFormat(fout, posFitFrac);
1252  fout << "$ & $";
1253 
1254  print.printFormat(fout, fitFracAsymm);
1255  fout << "$ & $";
1256 
1257  print.printFormat(fout, acp);
1258  fout << " \\pm ";
1259  print.printFormat(fout, acpErr);
1260  fout << "$ \\\\" << std::endl;
1261  }
1262  fout << "\\hline" << std::endl;
1263 
1264  // Also print out sum of fit fractions
1265  fout << "Fit Fraction Sum & $";
1266  print.printFormat(fout, negFitFracSum);
1267  fout << "$ & $";
1268  print.printFormat(fout, posFitFracSum);
1269  fout << "$ & & \\\\" << std::endl;
1270  fout << "\\hline" << std::endl;
1271 
1272  fout << "DP rate & $";
1273  print.printFormat(fout, negDPRate_.value());
1274  fout << "$ & $";
1275  print.printFormat(fout, posDPRate_.value());
1276  fout << "$ & & \\\\" << std::endl;
1277 
1278  fout << "$< \\varepsilon > $ & $";
1279  print.printFormat(fout, negMeanEff_.value());
1280  fout << "$ & $";
1281  print.printFormat(fout, posMeanEff_.value());
1282  fout << "$ & & \\\\" << std::endl;
1283  fout << "\\hline" << std::endl;
1284  fout << "\\end{tabular}" << std::endl << std::endl;
1285  }
1286 
1287  if (!negSignalPdfs_.empty()) {
1288  fout << "\\begin{tabular}{|l|c|}" << std::endl;
1289  fout << "\\hline" << std::endl;
1290  if (useSCF_ == kTRUE) {
1291  fout << "\\Extra TM Signal PDFs' Parameters: & \\\\" << std::endl;
1292  } else {
1293  fout << "\\Extra Signal PDFs' Parameters: & \\\\" << std::endl;
1294  }
1295  this->printFitParameters(negSignalPdfs_, fout);
1296  if ( tagged_ ) {
1297  this->printFitParameters(posSignalPdfs_, fout);
1298  }
1299  if (useSCF_ == kTRUE && !negScfPdfs_.empty()) {
1300  fout << "\\hline" << std::endl;
1301  fout << "\\Extra SCF Signal PDFs' Parameters: & \\\\" << std::endl;
1302  this->printFitParameters(negScfPdfs_, fout);
1303  if ( tagged_ ) {
1304  this->printFitParameters(posScfPdfs_, fout);
1305  }
1306  }
1307  if (usingBkgnd_ == kTRUE && !negBkgndPdfs_.empty()) {
1308  fout << "\\hline" << std::endl;
1309  fout << "\\Extra Background PDFs' Parameters: & \\\\" << std::endl;
1310  for (LauBkgndPdfsList::const_iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) {
1311  this->printFitParameters(*iter, fout);
1312  }
1313  if ( tagged_ ) {
1314  for (LauBkgndPdfsList::const_iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) {
1315  this->printFitParameters(*iter, fout);
1316  }
1317  }
1318  }
1319  fout << "\\hline \n\\end{tabular}" << std::endl << std::endl;
1320  }
1321 }
1322 
1324 {
1325  // Update the number of signal events to be total-sum(background events)
1326  this->updateSigEvents();
1327 
1328  // Check whether we want to have randomised initial fit parameters for the signal model
1329  if (this->useRandomInitFitPars() == kTRUE) {
1330  std::cout << "INFO in LauCPFitModel::checkInitFitParams : Setting random parameters for the signal model" << std::endl;
1331  this->randomiseInitFitPars();
1332  }
1333 }
1334 
1336 {
1337  // Only randomise those parameters that are not fixed!
1338  std::cout << "INFO in LauCPFitModel::randomiseInitFitPars : Randomising the initial fit magnitudes and phases of the components..." << std::endl;
1339 
1340  for (UInt_t i = 0; i < nSigComp_; i++) {
1341  coeffPars_[i]->randomiseInitValues();
1342  }
1343 }
1344 
1345 std::pair<LauCPFitModel::LauGenInfo,Bool_t> LauCPFitModel::eventsToGenerate()
1346 {
1347  // Determine the number of events to generate for each hypothesis
1348  // If we're smearing then smear each one individually
1349 
1350  LauGenInfo nEvtsGen;
1351 
1352  // Keep track of whether any yield or asymmetry parameters are blinded
1353  Bool_t blind = kFALSE;
1354 
1355  // Signal
1356  Double_t evtWeight(1.0);
1357  Double_t nEvts = signalEvents_->genValue();
1358  if ( nEvts < 0.0 ) {
1359  evtWeight = -1.0;
1360  nEvts = TMath::Abs( nEvts );
1361  }
1362  if ( signalEvents_->blind() ) {
1363  blind = kTRUE;
1364  }
1365  Double_t asym(0.0);
1366  Double_t sigAsym(0.0);
1367  // need to include this as an alternative in case the DP isn't in the model
1368  if ( !this->useDP() || forceAsym_ ) {
1369  sigAsym = signalAsym_->genValue();
1370  if ( signalAsym_->blind() ) {
1371  blind = kTRUE;
1372  }
1373  } else {
1374  Double_t negRate = negSigModel_->getDPNorm();
1375  Double_t posRate = posSigModel_->getDPNorm();
1376  if (negRate+posRate>1e-30) {
1377  sigAsym = (negRate-posRate)/(negRate+posRate);
1378  }
1379  }
1380  asym = sigAsym;
1381  Int_t nPosEvts = static_cast<Int_t>((nEvts/2.0 * (1.0 - asym)) + 0.5);
1382  Int_t nNegEvts = static_cast<Int_t>((nEvts/2.0 * (1.0 + asym)) + 0.5);
1383  if (this->doPoissonSmearing()) {
1384  nNegEvts = LauRandom::randomFun()->Poisson(nNegEvts);
1385  nPosEvts = LauRandom::randomFun()->Poisson(nPosEvts);
1386  }
1387  nEvtsGen[std::make_pair("signal",-1)] = std::make_pair(nNegEvts,evtWeight);
1388  nEvtsGen[std::make_pair("signal",+1)] = std::make_pair(nPosEvts,evtWeight);
1389 
1390  // backgrounds
1391  const UInt_t nBkgnds = this->nBkgndClasses();
1392  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
1393  const TString& bkgndClass = this->bkgndClassName(bkgndID);
1394  const LauParameter* evtsPar = bkgndEvents_[bkgndID];
1395  const LauParameter* asymPar = bkgndAsym_[bkgndID];
1396  if ( evtsPar->blind() || asymPar->blind() ) {
1397  blind = kTRUE;
1398  }
1399  evtWeight = 1.0;
1400  nEvts = TMath::FloorNint( evtsPar->genValue() );
1401  if ( nEvts < 0 ) {
1402  evtWeight = -1.0;
1403  nEvts = TMath::Abs( nEvts );
1404  }
1405  asym = asymPar->genValue();
1406  nPosEvts = static_cast<Int_t>((nEvts/2.0 * (1.0 - asym)) + 0.5);
1407  nNegEvts = static_cast<Int_t>((nEvts/2.0 * (1.0 + asym)) + 0.5);
1408  if (this->doPoissonSmearing()) {
1409  nNegEvts = LauRandom::randomFun()->Poisson(nNegEvts);
1410  nPosEvts = LauRandom::randomFun()->Poisson(nPosEvts);
1411  }
1412  nEvtsGen[std::make_pair(bkgndClass,-1)] = std::make_pair(nNegEvts,evtWeight);
1413  nEvtsGen[std::make_pair(bkgndClass,+1)] = std::make_pair(nPosEvts,evtWeight);
1414  }
1415 
1416  // Print out the information on what we're generating, but only if none of the parameters are blind (otherwise we risk unblinding them!)
1417  if ( !blind ) {
1418  std::cout << "INFO in LauCPFitModel::eventsToGenerate : Generating toy MC with:" << std::endl;
1419  std::cout << " : Signal asymmetry = " << sigAsym << " and number of signal events = " << signalEvents_->genValue() << std::endl;
1420  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
1421  const TString& bkgndClass = this->bkgndClassName(bkgndID);
1422  const LauParameter* evtsPar = bkgndEvents_[bkgndID];
1423  const LauParameter* asymPar = bkgndAsym_[bkgndID];
1424  std::cout << " : " << bkgndClass << " asymmetry = " << asymPar->genValue() << " and number of " << bkgndClass << " events = " << evtsPar->genValue() << std::endl;
1425  }
1426  }
1427 
1428  return std::make_pair( nEvtsGen, blind );
1429 }
1430 
1432 {
1433  // Routine to generate toy Monte Carlo events according to the various models we have defined.
1434 
1435  // Determine the number of events to generate for each hypothesis
1436  std::pair<LauGenInfo,Bool_t> info = this->eventsToGenerate();
1437  LauGenInfo nEvts = info.first;
1438  const Bool_t blind = info.second;
1439 
1440  Bool_t genOK(kTRUE);
1441  Int_t evtNum(0);
1442 
1443  const UInt_t nBkgnds = this->nBkgndClasses();
1444  std::vector<TString> bkgndClassNames(nBkgnds);
1445  std::vector<TString> bkgndClassNamesGen(nBkgnds);
1446  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
1447  TString name( this->bkgndClassName(iBkgnd) );
1448  bkgndClassNames[iBkgnd] = name;
1449  bkgndClassNamesGen[iBkgnd] = "gen"+name;
1450  }
1451 
1452  const Bool_t storeSCFTruthInfo = ( useSCF_ || ( this->enableEmbedding() &&
1453  negSignalTree_ != 0 && negSignalTree_->haveBranch("mcMatch") &&
1454  posSignalTree_ != 0 && posSignalTree_->haveBranch("mcMatch") ) );
1455 
1456  // Loop over the hypotheses and generate the requested number of events for each one
1457  for (LauGenInfo::const_iterator iter = nEvts.begin(); iter != nEvts.end(); ++iter) {
1458 
1459  const TString& type(iter->first.first);
1460  curEvtCharge_ = iter->first.second;
1461  Double_t evtWeight( iter->second.second );
1462  Int_t nEvtsGen( iter->second.first );
1463 
1464  for (Int_t iEvt(0); iEvt<nEvtsGen; ++iEvt) {
1465 
1466  this->setGenNtupleDoubleBranchValue( "evtWeight", evtWeight );
1467  this->setGenNtupleDoubleBranchValue( "efficiency", 1.0 );
1468 
1469  if (type == "signal") {
1470  this->setGenNtupleIntegerBranchValue("genSig",1);
1471  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
1472  this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], 0 );
1473  }
1474  genOK = this->generateSignalEvent();
1475  if ( curEvtCharge_ > 0 ){
1476  this->setGenNtupleDoubleBranchValue( "efficiency", posSigModel_->getEvtEff() );
1477  } else {
1478  this->setGenNtupleDoubleBranchValue( "efficiency", negSigModel_->getEvtEff() );
1479  }
1480 
1481  } else {
1482  this->setGenNtupleIntegerBranchValue("genSig",0);
1483  if ( storeSCFTruthInfo ) {
1484  this->setGenNtupleIntegerBranchValue("genTMSig",0);
1485  this->setGenNtupleIntegerBranchValue("genSCFSig",0);
1486  }
1487  UInt_t bkgndID(0);
1488  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
1489  Int_t gen(0);
1490  if ( bkgndClassNames[iBkgnd] == type ) {
1491  gen = 1;
1492  bkgndID = iBkgnd;
1493  }
1494  this->setGenNtupleIntegerBranchValue( bkgndClassNamesGen[iBkgnd], gen );
1495  }
1496  genOK = this->generateBkgndEvent(bkgndID);
1497  }
1498  if (!genOK) {
1499  // If there was a problem with the generation then break out and return.
1500  // The problem model will have adjusted itself so that all should be OK next time.
1501  break;
1502  }
1503  if (this->useDP() == kTRUE) {
1504  this->setDPBranchValues();
1505  }
1506 
1507  // Store the event charge
1509 
1510  // Store the event number (within this experiment)
1511  // and then increment it
1512  this->setGenNtupleIntegerBranchValue("iEvtWithinExpt",evtNum);
1513  ++evtNum;
1514 
1515  this->fillGenNtupleBranches();
1516  if ( !blind && (iEvt%500 == 0) ) {
1517  std::cout << "INFO in LauCPFitModel::genExpt : Generated event number " << iEvt << " out of " << nEvtsGen << " " << type << " events." << std::endl;
1518  }
1519  }
1520 
1521  if (!genOK) {
1522  break;
1523  }
1524  }
1525 
1526  if (this->useDP() && genOK) {
1527 
1528  negSigModel_->checkToyMC(kTRUE,kTRUE);
1529  posSigModel_->checkToyMC(kTRUE,kTRUE);
1530 
1531  // Get the fit fractions if they're to be written into the latex table
1532  if (this->writeLatexTable()) {
1533  LauParArray negFitFrac = negSigModel_->getFitFractions();
1534  if (negFitFrac.size() != nSigComp_) {
1535  std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << negFitFrac.size() << std::endl;
1536  gSystem->Exit(EXIT_FAILURE);
1537  }
1538  for (UInt_t i(0); i<nSigComp_; ++i) {
1539  if (negFitFrac[i].size() != nSigComp_) {
1540  std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << negFitFrac[i].size() << std::endl;
1541  gSystem->Exit(EXIT_FAILURE);
1542  }
1543  }
1544  LauParArray posFitFrac = posSigModel_->getFitFractions();
1545  if (posFitFrac.size() != nSigComp_) {
1546  std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << posFitFrac.size() << std::endl;
1547  gSystem->Exit(EXIT_FAILURE);
1548  }
1549  for (UInt_t i(0); i<nSigComp_; ++i) {
1550  if (posFitFrac[i].size() != nSigComp_) {
1551  std::cerr << "ERROR in LauCPFitModel::genExpt : Fit Fraction array of unexpected dimension: " << posFitFrac[i].size() << std::endl;
1552  gSystem->Exit(EXIT_FAILURE);
1553  }
1554  }
1555 
1556  for (UInt_t i(0); i<nSigComp_; ++i) {
1557  for (UInt_t j(i); j<nSigComp_; ++j) {
1558  negFitFrac_[i][j].value(negFitFrac[i][j].value());
1559  posFitFrac_[i][j].value(posFitFrac[i][j].value());
1560  }
1561  }
1566  }
1567  }
1568 
1569  // If we're reusing embedded events or if the generation is being
1570  // reset then clear the lists of used events
1571  if (reuseSignal_ || !genOK) {
1572  if (negSignalTree_) {
1574  }
1575  if (posSignalTree_) {
1577  }
1578  }
1579  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
1580  LauEmbeddedData* data = negBkgndTree_[bkgndID];
1581  if (reuseBkgnd_[bkgndID] || !genOK) {
1582  if (data) {
1583  data->clearUsedList();
1584  }
1585  }
1586  }
1587  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
1588  LauEmbeddedData* data = posBkgndTree_[bkgndID];
1589  if (reuseBkgnd_[bkgndID] || !genOK) {
1590  if (data) {
1591  data->clearUsedList();
1592  }
1593  }
1594  }
1595 
1596  return genOK;
1597 }
1598 
1600 {
1601  // Generate signal event
1602  Bool_t genOK(kTRUE);
1603  Bool_t genSCF(kFALSE);
1604 
1605  LauIsobarDynamics* model(0);
1606  LauKinematics* kinematics(0);
1607  LauEmbeddedData* embeddedData(0);
1608  LauPdfList* sigPdfs(0);
1609  LauPdfList* scfPdfs(0);
1610 
1611  Bool_t doReweighting(kFALSE);
1612 
1613  if (curEvtCharge_<0) {
1614  model = negSigModel_;
1615  kinematics = negKinematics_;
1616  sigPdfs = &negSignalPdfs_;
1617  scfPdfs = &negScfPdfs_;
1618  if (this->enableEmbedding()) {
1619  embeddedData = negSignalTree_;
1620  doReweighting = useNegReweighting_;
1621  }
1622  } else {
1623  model = posSigModel_;
1624  kinematics = posKinematics_;
1625  if ( tagged_ ) {
1626  sigPdfs = &posSignalPdfs_;
1627  scfPdfs = &posScfPdfs_;
1628  } else {
1629  sigPdfs = &negSignalPdfs_;
1630  scfPdfs = &negScfPdfs_;
1631  }
1632  if (this->enableEmbedding()) {
1633  embeddedData = posSignalTree_;
1634  doReweighting = usePosReweighting_;
1635  }
1636  }
1637 
1638  if (this->useDP()) {
1639  if (embeddedData) {
1640  if (doReweighting) {
1641  // Select a (random) event from the generated data. Then store the
1642  // reconstructed DP co-ords, together with other pdf information,
1643  // as the embedded data.
1644  genOK = embeddedData->getReweightedEvent(model);
1645  } else {
1646  // Just get the information of a (randomly) selected event in the
1647  // embedded data
1648  embeddedData->getEmbeddedEvent(kinematics);
1649  }
1650  genSCF = this->storeSignalMCMatch( embeddedData );
1651  } else {
1652  genOK = model->generate();
1653  if ( genOK && useSCF_ ) {
1654  Double_t frac(0.0);
1655  if ( useSCFHist_ ) {
1656  frac = scfFracHist_->calcEfficiency( kinematics );
1657  } else {
1658  frac = scfFrac_.genValue();
1659  }
1660  if ( frac < LauRandom::randomFun()->Rndm() ) {
1661  this->setGenNtupleIntegerBranchValue("genTMSig",1);
1662  this->setGenNtupleIntegerBranchValue("genSCFSig",0);
1663  genSCF = kFALSE;
1664  } else {
1665  this->setGenNtupleIntegerBranchValue("genTMSig",0);
1666  this->setGenNtupleIntegerBranchValue("genSCFSig",1);
1667  genSCF = kTRUE;
1668 
1669  // Optionally smear the DP position
1670  // of the SCF event
1671  if ( scfMap_ != 0 ) {
1672  Double_t xCoord(0.0), yCoord(0.0);
1673  if ( kinematics->squareDP() ) {
1674  xCoord = kinematics->getmPrime();
1675  yCoord = kinematics->getThetaPrime();
1676  } else {
1677  xCoord = kinematics->getm13Sq();
1678  yCoord = kinematics->getm23Sq();
1679  }
1680 
1681  // Find the bin number where this event is generated
1682  Int_t binNo = scfMap_->binNumber( xCoord, yCoord );
1683 
1684  // Retrieve the migration histogram
1685  TH2* histo = scfMap_->trueHist( binNo );
1686 
1687  const LauAbsEffModel * effModel = model->getEffModel();
1688  do {
1689  // Get a random point from the histogram
1690  histo->GetRandom2( xCoord, yCoord );
1691 
1692  // Update the kinematics
1693  if ( kinematics->squareDP() ) {
1694  kinematics->updateSqDPKinematics( xCoord, yCoord );
1695  } else {
1696  kinematics->updateKinematics( xCoord, yCoord );
1697  }
1698  } while ( ! effModel->passVeto( kinematics ) );
1699  }
1700  }
1701  }
1702  }
1703  } else {
1704  if (embeddedData) {
1705  embeddedData->getEmbeddedEvent(0);
1706  genSCF = this->storeSignalMCMatch( embeddedData );
1707  } else if ( useSCF_ ) {
1708  Double_t frac = scfFrac_.genValue();
1709  if ( frac < LauRandom::randomFun()->Rndm() ) {
1710  this->setGenNtupleIntegerBranchValue("genTMSig",1);
1711  this->setGenNtupleIntegerBranchValue("genSCFSig",0);
1712  genSCF = kFALSE;
1713  } else {
1714  this->setGenNtupleIntegerBranchValue("genTMSig",0);
1715  this->setGenNtupleIntegerBranchValue("genSCFSig",1);
1716  genSCF = kTRUE;
1717  }
1718  }
1719  }
1720  if (genOK) {
1721  if ( useSCF_ ) {
1722  if ( genSCF ) {
1723  this->generateExtraPdfValues(scfPdfs, embeddedData);
1724  } else {
1725  this->generateExtraPdfValues(sigPdfs, embeddedData);
1726  }
1727  } else {
1728  this->generateExtraPdfValues(sigPdfs, embeddedData);
1729  }
1730  }
1731  // Check for problems with the embedding
1732  if (embeddedData && (embeddedData->nEvents() == embeddedData->nUsedEvents())) {
1733  std::cerr << "WARNING in LauCPFitModel::generateSignalEvent : Source of embedded signal events used up, clearing the list of used events." << std::endl;
1734  embeddedData->clearUsedList();
1735  }
1736 
1737  return genOK;
1738 }
1739 
1741 {
1742  // Generate Bkgnd event
1743  Bool_t genOK(kTRUE);
1744 
1745  LauAbsBkgndDPModel* model(0);
1746  LauEmbeddedData* embeddedData(0);
1747  LauPdfList* extraPdfs(0);
1748  LauKinematics* kinematics(0);
1749 
1750  if (curEvtCharge_<0) {
1751  model = negBkgndDPModels_[bkgndID];
1752  if (this->enableEmbedding()) {
1753  embeddedData = negBkgndTree_[bkgndID];
1754  }
1755  extraPdfs = &negBkgndPdfs_[bkgndID];
1756  kinematics = negKinematics_;
1757  } else {
1758  model = posBkgndDPModels_[bkgndID];
1759  if (this->enableEmbedding()) {
1760  embeddedData = posBkgndTree_[bkgndID];
1761  }
1762  if ( tagged_ ) {
1763  extraPdfs = &posBkgndPdfs_[bkgndID];
1764  } else {
1765  extraPdfs = &negBkgndPdfs_[bkgndID];
1766  }
1767  kinematics = posKinematics_;
1768  }
1769 
1770  if (this->useDP()) {
1771  if (embeddedData) {
1772  embeddedData->getEmbeddedEvent(kinematics);
1773  } else {
1774  if (model == 0) {
1775  const TString& bkgndClass = this->bkgndClassName(bkgndID);
1776  std::cerr << "ERROR in LauCPFitModel::generateBkgndEvent : Can't find the DP model for background class \"" << bkgndClass << "\"." << std::endl;
1777  gSystem->Exit(EXIT_FAILURE);
1778  }
1779  genOK = model->generate();
1780  }
1781  } else {
1782  if (embeddedData) {
1783  embeddedData->getEmbeddedEvent(0);
1784  }
1785  }
1786  if (genOK) {
1787  this->generateExtraPdfValues(extraPdfs, embeddedData);
1788  }
1789 
1790  // Check for problems with the embedding
1791  if (embeddedData && (embeddedData->nEvents() == embeddedData->nUsedEvents())) {
1792  const TString& bkgndClass = this->bkgndClassName(bkgndID);
1793  std::cerr << "WARNING in LauCPFitModel::generateBkgndEvent : Source of embedded " << bkgndClass << " events used up, clearing the list of used events." << std::endl;
1794  embeddedData->clearUsedList();
1795  }
1796 
1797  return genOK;
1798 }
1799 
1801 {
1802  // Setup the required ntuple branches
1803  this->addGenNtupleDoubleBranch("evtWeight");
1804  this->addGenNtupleIntegerBranch("genSig");
1805  this->addGenNtupleDoubleBranch("efficiency");
1806  if ( useSCF_ || ( this->enableEmbedding() &&
1807  negSignalTree_ != 0 && negSignalTree_->haveBranch("mcMatch") &&
1808  posSignalTree_ != 0 && posSignalTree_->haveBranch("mcMatch") ) ) {
1809  this->addGenNtupleIntegerBranch("genTMSig");
1810  this->addGenNtupleIntegerBranch("genSCFSig");
1811  }
1812  const UInt_t nBkgnds = this->nBkgndClasses();
1813  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
1814  TString name( this->bkgndClassName(iBkgnd) );
1815  name.Prepend("gen");
1816  this->addGenNtupleIntegerBranch(name);
1817  }
1818  this->addGenNtupleIntegerBranch("charge");
1819  if (this->useDP() == kTRUE) {
1820  this->addGenNtupleDoubleBranch("m12");
1821  this->addGenNtupleDoubleBranch("m23");
1822  this->addGenNtupleDoubleBranch("m13");
1823  this->addGenNtupleDoubleBranch("m12Sq");
1824  this->addGenNtupleDoubleBranch("m23Sq");
1825  this->addGenNtupleDoubleBranch("m13Sq");
1826  this->addGenNtupleDoubleBranch("cosHel12");
1827  this->addGenNtupleDoubleBranch("cosHel23");
1828  this->addGenNtupleDoubleBranch("cosHel13");
1830  this->addGenNtupleDoubleBranch("mPrime");
1831  this->addGenNtupleDoubleBranch("thPrime");
1832  }
1833  }
1834  for (LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter) {
1835  std::vector<TString> varNames = (*pdf_iter)->varNames();
1836  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
1837  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
1838  this->addGenNtupleDoubleBranch( (*var_iter) );
1839  }
1840  }
1841  }
1842 }
1843 
1845 {
1846  LauKinematics* kinematics(0);
1847  if (curEvtCharge_<0) {
1848  kinematics = negKinematics_;
1849  } else {
1850  kinematics = posKinematics_;
1851  }
1852 
1853  // Store all the DP information
1854  this->setGenNtupleDoubleBranchValue("m12", kinematics->getm12());
1855  this->setGenNtupleDoubleBranchValue("m23", kinematics->getm23());
1856  this->setGenNtupleDoubleBranchValue("m13", kinematics->getm13());
1857  this->setGenNtupleDoubleBranchValue("m12Sq", kinematics->getm12Sq());
1858  this->setGenNtupleDoubleBranchValue("m23Sq", kinematics->getm23Sq());
1859  this->setGenNtupleDoubleBranchValue("m13Sq", kinematics->getm13Sq());
1860  this->setGenNtupleDoubleBranchValue("cosHel12", kinematics->getc12());
1861  this->setGenNtupleDoubleBranchValue("cosHel23", kinematics->getc23());
1862  this->setGenNtupleDoubleBranchValue("cosHel13", kinematics->getc13());
1863  if (kinematics->squareDP()) {
1864  this->setGenNtupleDoubleBranchValue("mPrime", kinematics->getmPrime());
1865  this->setGenNtupleDoubleBranchValue("thPrime", kinematics->getThetaPrime());
1866  }
1867 }
1868 
1870 {
1871  LauKinematics* kinematics(0);
1872  if (curEvtCharge_<0) {
1873  kinematics = negKinematics_;
1874  } else {
1875  kinematics = posKinematics_;
1876  }
1877 
1878  if (!extraPdfs) {
1879  std::cerr << "ERROR in LauCPFitModel::generateExtraPdfValues : Null pointer to PDF list." << std::endl;
1880  gSystem->Exit(EXIT_FAILURE);
1881  }
1882 
1883  if (extraPdfs->empty()) {
1884  //std::cerr << "WARNING in LauCPFitModel::generateExtraPdfValues : PDF list is empty." << std::endl;
1885  return;
1886  }
1887 
1888  // Generate from the extra PDFs
1889  for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) {
1890  LauFitData genValues;
1891  if (embeddedData) {
1892  genValues = embeddedData->getValues( (*pdf_iter)->varNames() );
1893  } else {
1894  genValues = (*pdf_iter)->generate(kinematics);
1895  }
1896  for ( LauFitData::const_iterator var_iter = genValues.begin(); var_iter != genValues.end(); ++var_iter ) {
1897  TString varName = var_iter->first;
1898  if ( varName != "m13Sq" && varName != "m23Sq" ) {
1899  Double_t value = var_iter->second;
1900  this->setGenNtupleDoubleBranchValue(varName,value);
1901  }
1902  }
1903  }
1904 }
1905 
1907 {
1908  // Default to TM
1909  Bool_t genSCF(kFALSE);
1910  Int_t match(1);
1911 
1912  // Check that we have a valid pointer and that embedded data has
1913  // the mcMatch branch. If so then get the match value.
1914  if ( embeddedData && embeddedData->haveBranch("mcMatch") ) {
1915  match = TMath::Nint( embeddedData->getValue("mcMatch") );
1916  }
1917 
1918  // Set the variables accordingly.
1919  if (match) {
1920  this->setGenNtupleIntegerBranchValue("genTMSig",1);
1921  this->setGenNtupleIntegerBranchValue("genSCFSig",0);
1922  genSCF = kFALSE;
1923  } else {
1924  this->setGenNtupleIntegerBranchValue("genTMSig",0);
1925  this->setGenNtupleIntegerBranchValue("genSCFSig",1);
1926  genSCF = kTRUE;
1927  }
1928 
1929  return genSCF;
1930 }
1931 
1933 {
1934  // Update the signal parameters and then the total normalisation for the signal likelihood
1935  if (this->useDP() == kTRUE) {
1936  this->updateCoeffs();
1939  }
1940 
1941  // Update the signal fraction from the background fractions if not doing an extended fit
1942  if ( !this->doEMLFit() && !signalEvents_->fixed() ) {
1943  this->updateSigEvents();
1944  }
1945 }
1946 
1948 {
1949  // The background parameters will have been set from Minuit.
1950  // We need to update the signal events using these.
1951  Double_t nTotEvts = this->eventsPerExpt();
1952 
1953  signalEvents_->range(-2.0*nTotEvts,2.0*nTotEvts);
1954  for (LauBkgndYieldList::iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) {
1955  (*iter)->range(-2.0*nTotEvts,2.0*nTotEvts);
1956  }
1957 
1958  if (signalEvents_->fixed()) {
1959  return;
1960  }
1961 
1962  // Subtract background events (if any) from signal.
1963  Double_t signalEvents = nTotEvts;
1964  if (usingBkgnd_ == kTRUE) {
1965  for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) {
1966  signalEvents -= (*iter)->value();
1967  }
1968  }
1969  signalEvents_->value(signalEvents);
1970 }
1971 
1973 {
1974  // Fill the internal data trees of the signal and background models.
1975  // Note that we store the events of both charges in both the
1976  // negative and the positive models. It's only later, at the stage
1977  // when the likelihood is being calculated, that we separate them.
1978 
1979  LauFitDataTree* inputFitData = this->fitData();
1980 
1981  // First the Dalitz plot variables (m_ij^2)
1982  if (this->useDP() == kTRUE) {
1983 
1984  // need to append SCF smearing bins before caching DP amplitudes
1985  if ( scfMap_ != 0 ) {
1986  this->appendBinCentres( inputFitData );
1987  }
1988 
1989  negSigModel_->fillDataTree(*inputFitData);
1990  posSigModel_->fillDataTree(*inputFitData);
1991 
1992  if (usingBkgnd_ == kTRUE) {
1993  for (LauBkgndDPModelList::iterator iter = negBkgndDPModels_.begin(); iter != negBkgndDPModels_.end(); ++iter) {
1994  (*iter)->fillDataTree(*inputFitData);
1995  }
1996  for (LauBkgndDPModelList::iterator iter = posBkgndDPModels_.begin(); iter != posBkgndDPModels_.end(); ++iter) {
1997  (*iter)->fillDataTree(*inputFitData);
1998  }
1999  }
2000  }
2001 
2002  // ...and then the extra PDFs
2003  this->cacheInfo(negSignalPdfs_, *inputFitData);
2004  this->cacheInfo(negScfPdfs_, *inputFitData);
2005  for (LauBkgndPdfsList::iterator iter = negBkgndPdfs_.begin(); iter != negBkgndPdfs_.end(); ++iter) {
2006  this->cacheInfo((*iter), *inputFitData);
2007  }
2008  if ( tagged_ ) {
2009  this->cacheInfo(posSignalPdfs_, *inputFitData);
2010  this->cacheInfo(posScfPdfs_, *inputFitData);
2011  for (LauBkgndPdfsList::iterator iter = posBkgndPdfs_.begin(); iter != posBkgndPdfs_.end(); ++iter) {
2012  this->cacheInfo((*iter), *inputFitData);
2013  }
2014  }
2015 
2016  // the SCF fractions and jacobians
2017  if ( useSCF_ && useSCFHist_ ) {
2018  if ( !inputFitData->haveBranch( "m13Sq" ) || !inputFitData->haveBranch( "m23Sq" ) ) {
2019  std::cerr << "ERROR in LauCPFitModel::cacheInputFitVars : Input data does not contain DP branches and so can't cache the SCF fraction." << std::endl;
2020  gSystem->Exit(EXIT_FAILURE);
2021  }
2022 
2023  UInt_t nEvents = inputFitData->nEvents();
2024  recoSCFFracs_.clear();
2025  recoSCFFracs_.reserve( nEvents );
2026  if ( negKinematics_->squareDP() ) {
2027  recoJacobians_.clear();
2028  recoJacobians_.reserve( nEvents );
2029  }
2030  for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) {
2031  const LauFitData& dataValues = inputFitData->getData(iEvt);
2032  LauFitData::const_iterator m13_iter = dataValues.find("m13Sq");
2033  LauFitData::const_iterator m23_iter = dataValues.find("m23Sq");
2034  negKinematics_->updateKinematics( m13_iter->second, m23_iter->second );
2035  Double_t scfFrac = scfFracHist_->calcEfficiency( negKinematics_ );
2036  recoSCFFracs_.push_back( scfFrac );
2037  if ( negKinematics_->squareDP() ) {
2039  }
2040  }
2041  }
2042 
2043  // finally cache the event charge
2044  evtCharges_.clear();
2045  if ( tagged_ ) {
2046  if ( !inputFitData->haveBranch( tagVarName_ ) ) {
2047  std::cerr << "ERROR in LauCPFitModel::cacheInputFitVars : Input data does not contain branch \"" << tagVarName_ << "\"." << std::endl;
2048  gSystem->Exit(EXIT_FAILURE);
2049  }
2050  UInt_t nEvents = inputFitData->nEvents();
2051  evtCharges_.reserve( nEvents );
2052  for (UInt_t iEvt = 0; iEvt < nEvents; iEvt++) {
2053  const LauFitData& dataValues = inputFitData->getData(iEvt);
2054  LauFitData::const_iterator iter = dataValues.find( tagVarName_ );
2055  curEvtCharge_ = static_cast<Int_t>( iter->second );
2056  evtCharges_.push_back( curEvtCharge_ );
2057  }
2058  }
2059 }
2060 
2062 {
2063  // We'll be caching the DP amplitudes and efficiencies of the centres of the true bins.
2064  // To do so, we attach some fake points at the end of inputData, the number of the entry
2065  // minus the total number of events corresponding to the number of the histogram for that
2066  // given true bin in the LauScfMap object. (What this means is that when Laura is provided with
2067  // the LauScfMap object by the user, it's the latter who has to make sure that it contains the
2068  // right number of histograms and in exactly the right order!)
2069 
2070  // Get the x and y co-ordinates of the bin centres
2071  std::vector<Double_t> binCentresXCoords;
2072  std::vector<Double_t> binCentresYCoords;
2073  scfMap_->listBinCentres(binCentresXCoords, binCentresYCoords);
2074 
2075  // The SCF histograms could be in square Dalitz plot histograms.
2076  // The dynamics takes normal Dalitz plot coords, so we might have to convert them back.
2077  Bool_t sqDP = negKinematics_->squareDP();
2078  UInt_t nBins = binCentresXCoords.size();
2079  fakeSCFFracs_.clear();
2080  fakeSCFFracs_.reserve( nBins );
2081  if ( sqDP ) {
2082  fakeJacobians_.clear();
2083  fakeJacobians_.reserve( nBins );
2084  }
2085 
2086  for (UInt_t iBin = 0; iBin < nBins; ++iBin) {
2087 
2088  if ( sqDP ) {
2089  negKinematics_->updateSqDPKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]);
2090  binCentresXCoords[iBin] = negKinematics_->getm13Sq();
2091  binCentresYCoords[iBin] = negKinematics_->getm23Sq();
2093  } else {
2094  negKinematics_->updateKinematics(binCentresXCoords[iBin],binCentresYCoords[iBin]);
2095  }
2096 
2098  }
2099 
2100  // Set up inputFitVars_ object to hold the fake events
2101  inputData->appendFakePoints(binCentresXCoords,binCentresYCoords);
2102 }
2103 
2105 {
2106  // Find out whether we have B- or B+
2107  if ( tagged_ ) {
2108  curEvtCharge_ = evtCharges_[iEvt];
2109 
2110  // check that the charge is either +1 or -1
2111  if (TMath::Abs(curEvtCharge_)!=1) {
2112  std::cerr << "ERROR in LauCPFitModel::getTotEvtLikelihood : Charge/tag not accepted value: " << curEvtCharge_ << std::endl;
2113  if (curEvtCharge_>0) {
2114  curEvtCharge_ = +1;
2115  } else {
2116  curEvtCharge_ = -1;
2117  }
2118  std::cerr << " : Making it: " << curEvtCharge_ << "." << std::endl;
2119  }
2120  }
2121 
2122  // Get the DP likelihood for signal and backgrounds
2123  this->getEvtDPLikelihood(iEvt);
2124 
2125  // Get the combined extra PDFs likelihood for signal and backgrounds
2126  this->getEvtExtraLikelihoods(iEvt);
2127 
2128  // If appropriate, combine the TM and SCF likelihoods
2129  Double_t sigLike = sigDPLike_ * sigExtraLike_;
2130  if ( useSCF_ ) {
2131  Double_t scfFrac(0.0);
2132  if (useSCFHist_) {
2133  scfFrac = recoSCFFracs_[iEvt];
2134  } else {
2135  scfFrac = scfFrac_.unblindValue();
2136  }
2137  sigLike *= (1.0 - scfFrac);
2138  if ( (scfMap_ != 0) && (this->useDP() == kTRUE) ) {
2139  // if we're smearing the SCF DP PDF then the SCF frac
2140  // is already included in the SCF DP likelihood
2141  sigLike += (scfDPLike_ * scfExtraLike_);
2142  } else {
2143  sigLike += (scfFrac * scfDPLike_ * scfExtraLike_);
2144  }
2145  }
2146 
2147  // Get the correct event fractions depending on the charge
2148  // Signal asymmetry is built into the DP model... but when the DP
2149  // isn't in the fit we need an explicit parameter
2150  Double_t signalEvents = signalEvents_->unblindValue() * 0.5;
2151  if (this->useDP() == kFALSE) {
2152  signalEvents *= (1.0 - curEvtCharge_ * signalAsym_->unblindValue());
2153  }
2154 
2155  // Construct the total event likelihood
2156  Double_t likelihood(0.0);
2157  if (usingBkgnd_) {
2158  likelihood = sigLike*signalEvents;
2159  const UInt_t nBkgnds = this->nBkgndClasses();
2160  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
2161  Double_t bkgndEvents = bkgndEvents_[bkgndID]->unblindValue() * 0.5 * (1.0 - curEvtCharge_ * bkgndAsym_[bkgndID]->unblindValue());
2162  likelihood += bkgndEvents*bkgndDPLike_[bkgndID]*bkgndExtraLike_[bkgndID];
2163  }
2164  } else {
2165  likelihood = sigLike*0.5;
2166  }
2167  return likelihood;
2168 }
2169 
2171 {
2172  Double_t eventSum(0.0);
2173  eventSum += signalEvents_->unblindValue();
2174  if (usingBkgnd_) {
2175  for (LauBkgndYieldList::const_iterator iter = bkgndEvents_.begin(); iter != bkgndEvents_.end(); ++iter) {
2176  eventSum += (*iter)->unblindValue();
2177  }
2178  }
2179  return eventSum;
2180 }
2181 
2183 {
2184  // Function to return the signal and background likelihoods for the
2185  // Dalitz plot for the given event evtNo.
2186 
2187  if ( ! this->useDP() ) {
2188  // There's always going to be a term in the likelihood for the
2189  // signal, so we'd better not zero it.
2190  sigDPLike_ = 1.0;
2191  scfDPLike_ = 1.0;
2192 
2193  const UInt_t nBkgnds = this->nBkgndClasses();
2194  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
2195  if (usingBkgnd_ == kTRUE) {
2196  bkgndDPLike_[bkgndID] = 1.0;
2197  } else {
2198  bkgndDPLike_[bkgndID] = 0.0;
2199  }
2200  }
2201 
2202  return;
2203  }
2204 
2205  const UInt_t nBkgnds = this->nBkgndClasses();
2206  if ( tagged_ ) {
2207  if (curEvtCharge_==+1) {
2210 
2211  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
2212  if (usingBkgnd_ == kTRUE) {
2213  bkgndDPLike_[bkgndID] = posBkgndDPModels_[bkgndID]->getLikelihood(iEvt);
2214  } else {
2215  bkgndDPLike_[bkgndID] = 0.0;
2216  }
2217  }
2218  } else {
2221 
2222  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
2223  if (usingBkgnd_ == kTRUE) {
2224  bkgndDPLike_[bkgndID] = negBkgndDPModels_[bkgndID]->getLikelihood(iEvt);
2225  } else {
2226  bkgndDPLike_[bkgndID] = 0.0;
2227  }
2228  }
2229  }
2230  } else {
2233 
2235 
2236  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
2237  if (usingBkgnd_ == kTRUE) {
2238  bkgndDPLike_[bkgndID] = 0.5 * ( posBkgndDPModels_[bkgndID]->getLikelihood(iEvt) +
2239  negBkgndDPModels_[bkgndID]->getLikelihood(iEvt) );
2240  } else {
2241  bkgndDPLike_[bkgndID] = 0.0;
2242  }
2243  }
2244  }
2245 
2246  if ( useSCF_ == kTRUE ) {
2247  if ( scfMap_ == 0 ) {
2248  // we're not smearing the SCF DP position
2249  // so the likelihood is the same as the TM
2251  } else {
2252  // calculate the smeared SCF DP likelihood
2253  scfDPLike_ = this->getEvtSCFDPLikelihood(iEvt);
2254  }
2255  }
2256 
2257  // Calculate the signal normalisation
2258  // NB the 2.0 is there so that the 0.5 factor is applied to
2259  // signal and background in the same place otherwise you get
2260  // normalisation problems when you switch off the DP in the fit
2261  Double_t norm = negSigModel_->getDPNorm() + posSigModel_->getDPNorm();
2262  sigDPLike_ *= 2.0/norm;
2263  scfDPLike_ *= 2.0/norm;
2264 }
2265 
2267 {
2268  Double_t scfDPLike(0.0);
2269 
2270  Double_t recoJacobian(1.0);
2271  Double_t xCoord(0.0);
2272  Double_t yCoord(0.0);
2273 
2274  Bool_t squareDP = negKinematics_->squareDP();
2275  if ( squareDP ) {
2276  xCoord = negSigModel_->getEvtmPrime();
2277  yCoord = negSigModel_->getEvtthPrime();
2278  recoJacobian = recoJacobians_[iEvt];
2279  } else {
2280  xCoord = negSigModel_->getEvtm13Sq();
2281  yCoord = negSigModel_->getEvtm23Sq();
2282  }
2283 
2284  // Find the bin that our reco event falls in
2285  Int_t recoBin = scfMap_->binNumber( xCoord, yCoord );
2286 
2287  // Find out which true Bins contribute to the given reco bin
2288  const std::vector<Int_t>* trueBins = scfMap_->trueBins(recoBin);
2289 
2290  const Int_t nDataEvents = this->eventsPerExpt();
2291 
2292  // Loop over the true bins
2293  for (std::vector<Int_t>::const_iterator iter = trueBins->begin(); iter != trueBins->end(); ++iter)
2294  {
2295  Int_t trueBin = (*iter);
2296 
2297  // prob of a true event in the given true bin migrating to the reco bin
2298  Double_t pRecoGivenTrue = scfMap_->prob( recoBin, trueBin );
2299  Double_t pTrue(0.0);
2300 
2301  // We've cached the DP amplitudes and the efficiency for the
2302  // true bin centres, just after the data points
2303  if ( tagged_ ) {
2304  LauIsobarDynamics* sigModel(0);
2305  if (curEvtCharge_<0) {
2306  sigModel = negSigModel_;
2307  } else {
2308  sigModel = posSigModel_;
2309  }
2310 
2311  sigModel->calcLikelihoodInfo( nDataEvents + trueBin );
2312 
2313  pTrue = sigModel->getEvtIntensity();
2314  } else {
2315  posSigModel_->calcLikelihoodInfo( nDataEvents + trueBin );
2316  negSigModel_->calcLikelihoodInfo( nDataEvents + trueBin );
2317 
2318  pTrue = 0.5 * ( posSigModel_->getEvtIntensity() + negSigModel_->getEvtIntensity() );
2319  }
2320 
2321  // Get the cached SCF fraction (and jacobian if we're using the square DP)
2322  Double_t scfFraction = fakeSCFFracs_[ trueBin ];
2323  Double_t jacobian(1.0);
2324  if ( squareDP ) {
2325  jacobian = fakeJacobians_[ trueBin ];
2326  }
2327 
2328  scfDPLike += pTrue * jacobian * scfFraction * pRecoGivenTrue;
2329  }
2330 
2331  // Divide by the reco jacobian
2332  scfDPLike /= recoJacobian;
2333 
2334  return scfDPLike;
2335 }
2336 
2338 {
2339  // Function to return the signal and background likelihoods for the
2340  // extra variables for the given event evtNo.
2341 
2342  sigExtraLike_ = 1.0;
2343 
2344  const UInt_t nBkgnds = this->nBkgndClasses();
2345 
2346  if ( ! tagged_ || curEvtCharge_ < 0 ) {
2347  sigExtraLike_ = this->prodPdfValue( negSignalPdfs_, iEvt );
2348 
2349  if (useSCF_) {
2350  scfExtraLike_ = this->prodPdfValue( negScfPdfs_, iEvt );
2351  }
2352 
2353  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
2354  if (usingBkgnd_) {
2355  bkgndExtraLike_[bkgndID] = this->prodPdfValue( negBkgndPdfs_[bkgndID], iEvt );
2356  } else {
2357  bkgndExtraLike_[bkgndID] = 0.0;
2358  }
2359  }
2360  } else {
2361  sigExtraLike_ = this->prodPdfValue( posSignalPdfs_, iEvt );
2362 
2363  if (useSCF_) {
2364  scfExtraLike_ = this->prodPdfValue( posScfPdfs_, iEvt );
2365  }
2366 
2367  for ( UInt_t bkgndID(0); bkgndID < nBkgnds; ++bkgndID ) {
2368  if (usingBkgnd_) {
2369  bkgndExtraLike_[bkgndID] = this->prodPdfValue( posBkgndPdfs_[bkgndID], iEvt );
2370  } else {
2371  bkgndExtraLike_[bkgndID] = 0.0;
2372  }
2373  }
2374  }
2375 }
2376 
2378 {
2379  negCoeffs_.clear(); posCoeffs_.clear();
2380  negCoeffs_.reserve(nSigComp_); posCoeffs_.reserve(nSigComp_);
2381  for (UInt_t i = 0; i < nSigComp_; i++) {
2382  negCoeffs_.push_back(coeffPars_[i]->antiparticleCoeff());
2383  posCoeffs_.push_back(coeffPars_[i]->particleCoeff());
2384  }
2385 }
2386 
2388 {
2389  // add branches for storing the experiment number and the number of
2390  // the event within the current experiment
2391  this->addSPlotNtupleIntegerBranch("iExpt");
2392  this->addSPlotNtupleIntegerBranch("iEvtWithinExpt");
2393 
2394  // Store the efficiency of the event (for inclusive BF calculations).
2395  if (this->storeDPEff()) {
2396  this->addSPlotNtupleDoubleBranch("efficiency");
2398  this->addSPlotNtupleDoubleBranch("scffraction");
2399  }
2400  }
2401 
2402  // Store the total event likelihood for each species.
2403  if (useSCF_) {
2404  this->addSPlotNtupleDoubleBranch("sigTMTotalLike");
2405  this->addSPlotNtupleDoubleBranch("sigSCFTotalLike");
2406  this->addSPlotNtupleDoubleBranch("sigSCFFrac");
2407  } else {
2408  this->addSPlotNtupleDoubleBranch("sigTotalLike");
2409  }
2410  if (usingBkgnd_) {
2411  const UInt_t nBkgnds = this->nBkgndClasses();
2412  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2413  TString name( this->bkgndClassName(iBkgnd) );
2414  name += "TotalLike";
2415  this->addSPlotNtupleDoubleBranch(name);
2416  }
2417  }
2418 
2419  // Store the DP likelihoods
2420  if (this->useDP()) {
2421  if (useSCF_) {
2422  this->addSPlotNtupleDoubleBranch("sigTMDPLike");
2423  this->addSPlotNtupleDoubleBranch("sigSCFDPLike");
2424  } else {
2425  this->addSPlotNtupleDoubleBranch("sigDPLike");
2426  }
2427  if (usingBkgnd_) {
2428  const UInt_t nBkgnds = this->nBkgndClasses();
2429  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2430  TString name( this->bkgndClassName(iBkgnd) );
2431  name += "DPLike";
2432  this->addSPlotNtupleDoubleBranch(name);
2433  }
2434  }
2435  }
2436 
2437  // Store the likelihoods for each extra PDF
2438  if (useSCF_) {
2439  this->addSPlotNtupleBranches(&negSignalPdfs_, "sigTM");
2440  this->addSPlotNtupleBranches(&negScfPdfs_, "sigSCF");
2441  } else {
2442  this->addSPlotNtupleBranches(&negSignalPdfs_, "sig");
2443  }
2444  if (usingBkgnd_) {
2445  const UInt_t nBkgnds = this->nBkgndClasses();
2446  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2447  const TString& bkgndClass = this->bkgndClassName(iBkgnd);
2448  const LauPdfList* pdfList = &(negBkgndPdfs_[iBkgnd]);
2449  this->addSPlotNtupleBranches(pdfList, bkgndClass);
2450  }
2451  }
2452 }
2453 
2454 void LauCPFitModel::addSPlotNtupleBranches(const LauPdfList* extraPdfs, const TString& prefix)
2455 {
2456  if (extraPdfs) {
2457  // Loop through each of the PDFs
2458  for (LauPdfList::const_iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) {
2459 
2460  // Count the number of input variables that are not
2461  // DP variables (used in the case where there is DP
2462  // dependence for e.g. MVA)
2463  UInt_t nVars(0);
2464  std::vector<TString> varNames = (*pdf_iter)->varNames();
2465  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
2466  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
2467  ++nVars;
2468  }
2469  }
2470 
2471  if ( nVars == 1 ) {
2472  // If the PDF only has one variable then
2473  // simply add one branch for that variable
2474  TString varName = (*pdf_iter)->varName();
2475  TString name(prefix);
2476  name += varName;
2477  name += "Like";
2478  this->addSPlotNtupleDoubleBranch(name);
2479  } else if ( nVars == 2 ) {
2480  // If the PDF has two variables then we
2481  // need a branch for them both together and
2482  // branches for each
2483  TString allVars("");
2484  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
2485  allVars += (*var_iter);
2486  TString name(prefix);
2487  name += (*var_iter);
2488  name += "Like";
2489  this->addSPlotNtupleDoubleBranch(name);
2490  }
2491  TString name(prefix);
2492  name += allVars;
2493  name += "Like";
2494  this->addSPlotNtupleDoubleBranch(name);
2495  } else {
2496  std::cerr << "WARNING in LauCPFitModel::addSPlotNtupleBranches : Can't yet deal with 3D PDFs." << std::endl;
2497  }
2498  }
2499  }
2500 }
2501 
2502 Double_t LauCPFitModel::setSPlotNtupleBranchValues(LauPdfList* extraPdfs, const TString& prefix, UInt_t iEvt)
2503 {
2504  // Store the PDF value for each variable in the list
2505  Double_t totalLike(1.0);
2506  Double_t extraLike(0.0);
2507  if (extraPdfs) {
2508  for (LauPdfList::iterator pdf_iter = extraPdfs->begin(); pdf_iter != extraPdfs->end(); ++pdf_iter) {
2509 
2510  // calculate the likelihood for this event
2511  (*pdf_iter)->calcLikelihoodInfo(iEvt);
2512  extraLike = (*pdf_iter)->getLikelihood();
2513  totalLike *= extraLike;
2514 
2515  // Count the number of input variables that are not
2516  // DP variables (used in the case where there is DP
2517  // dependence for e.g. MVA)
2518  UInt_t nVars(0);
2519  std::vector<TString> varNames = (*pdf_iter)->varNames();
2520  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
2521  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
2522  ++nVars;
2523  }
2524  }
2525 
2526  if ( nVars == 1 ) {
2527  // If the PDF only has one variable then
2528  // simply store the value for that variable
2529  TString varName = (*pdf_iter)->varName();
2530  TString name(prefix);
2531  name += varName;
2532  name += "Like";
2533  this->setSPlotNtupleDoubleBranchValue(name, extraLike);
2534  } else if ( nVars == 2 ) {
2535  // If the PDF has two variables then we
2536  // store the value for them both together
2537  // and for each on their own
2538  TString allVars("");
2539  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
2540  allVars += (*var_iter);
2541  TString name(prefix);
2542  name += (*var_iter);
2543  name += "Like";
2544  Double_t indivLike = (*pdf_iter)->getLikelihood( (*var_iter) );
2545  this->setSPlotNtupleDoubleBranchValue(name, indivLike);
2546  }
2547  TString name(prefix);
2548  name += allVars;
2549  name += "Like";
2550  this->setSPlotNtupleDoubleBranchValue(name, extraLike);
2551  } else {
2552  std::cerr << "WARNING in LauCPFitModel::setSPlotNtupleBranchValues : Can't yet deal with 3D PDFs." << std::endl;
2553  }
2554  }
2555  }
2556  return totalLike;
2557 }
2558 
2560 {
2561  LauSPlot::NameSet nameSet;
2562  if (this->useDP()) {
2563  nameSet.insert("DP");
2564  }
2565  // Loop through all the signal PDFs
2566  for (LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter) {
2567  // Loop over the variables involved in each PDF
2568  std::vector<TString> varNames = (*pdf_iter)->varNames();
2569  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
2570  // If they are not DP coordinates then add them
2571  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
2572  nameSet.insert( (*var_iter) );
2573  }
2574  }
2575  }
2576  return nameSet;
2577 }
2578 
2580 {
2581  LauSPlot::NumbMap numbMap;
2582  if (!signalEvents_->fixed() && this->doEMLFit()) {
2583  numbMap["sig"] = signalEvents_->genValue();
2584  }
2585  if ( usingBkgnd_ ) {
2586  const UInt_t nBkgnds = this->nBkgndClasses();
2587  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2588  const TString& bkgndClass = this->bkgndClassName(iBkgnd);
2589  const LauParameter* par = bkgndEvents_[iBkgnd];
2590  if (!par->fixed()) {
2591  numbMap[bkgndClass] = par->genValue();
2592  }
2593  }
2594  }
2595  return numbMap;
2596 }
2597 
2599 {
2600  LauSPlot::NumbMap numbMap;
2601  if (signalEvents_->fixed() && this->doEMLFit()) {
2602  numbMap["sig"] = signalEvents_->genValue();
2603  }
2604  if ( usingBkgnd_ ) {
2605  const UInt_t nBkgnds = this->nBkgndClasses();
2606  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2607  const TString& bkgndClass = this->bkgndClassName(iBkgnd);
2608  const LauParameter* par = bkgndEvents_[iBkgnd];
2609  if (par->fixed()) {
2610  numbMap[bkgndClass] = par->genValue();
2611  }
2612  }
2613  }
2614  return numbMap;
2615 }
2616 
2618 {
2619  // This makes the assumption that the form of the positive and
2620  // negative PDFs are the same, which seems reasonable to me
2621 
2622  LauSPlot::TwoDMap twodimMap;
2623 
2624  for (LauPdfList::const_iterator pdf_iter = negSignalPdfs_.begin(); pdf_iter != negSignalPdfs_.end(); ++pdf_iter) {
2625  // Count the number of input variables that are not DP variables
2626  UInt_t nVars(0);
2627  std::vector<TString> varNames = (*pdf_iter)->varNames();
2628  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
2629  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
2630  ++nVars;
2631  }
2632  }
2633  if ( nVars == 2 ) {
2634  if (useSCF_) {
2635  twodimMap.insert( std::make_pair( "sigTM", std::make_pair( varNames[0], varNames[1] ) ) );
2636  } else {
2637  twodimMap.insert( std::make_pair( "sig", std::make_pair( varNames[0], varNames[1] ) ) );
2638  }
2639  }
2640  }
2641 
2642  if ( useSCF_ ) {
2643  for (LauPdfList::const_iterator pdf_iter = negScfPdfs_.begin(); pdf_iter != negScfPdfs_.end(); ++pdf_iter) {
2644  // Count the number of input variables that are not DP variables
2645  UInt_t nVars(0);
2646  std::vector<TString> varNames = (*pdf_iter)->varNames();
2647  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
2648  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
2649  ++nVars;
2650  }
2651  }
2652  if ( nVars == 2 ) {
2653  twodimMap.insert( std::make_pair( "sigSCF", std::make_pair( varNames[0], varNames[1] ) ) );
2654  }
2655  }
2656  }
2657 
2658  if (usingBkgnd_) {
2659  const UInt_t nBkgnds = this->nBkgndClasses();
2660  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2661  const TString& bkgndClass = this->bkgndClassName(iBkgnd);
2662  const LauPdfList& pdfList = negBkgndPdfs_[iBkgnd];
2663  for (LauPdfList::const_iterator pdf_iter = pdfList.begin(); pdf_iter != pdfList.end(); ++pdf_iter) {
2664  // Count the number of input variables that are not DP variables
2665  UInt_t nVars(0);
2666  std::vector<TString> varNames = (*pdf_iter)->varNames();
2667  for ( std::vector<TString>::const_iterator var_iter = varNames.begin(); var_iter != varNames.end(); ++var_iter ) {
2668  if ( (*var_iter) != "m13Sq" && (*var_iter) != "m23Sq" ) {
2669  ++nVars;
2670  }
2671  }
2672  if ( nVars == 2 ) {
2673  twodimMap.insert( std::make_pair( bkgndClass, std::make_pair( varNames[0], varNames[1] ) ) );
2674  }
2675  }
2676  }
2677  }
2678 
2679  return twodimMap;
2680 }
2681 
2683 {
2684  std::cout << "INFO in LauCPFitModel::storePerEvtLlhds : Storing per-event likelihood values..." << std::endl;
2685 
2686  // if we've not been using the DP model then we need to cache all
2687  // the info here so that we can get the efficiency from it
2688 
2689  LauFitDataTree* inputFitData = this->fitData();
2690 
2691  if (!this->useDP() && this->storeDPEff()) {
2694  negSigModel_->fillDataTree(*inputFitData);
2695  posSigModel_->fillDataTree(*inputFitData);
2696  }
2697 
2698  UInt_t evtsPerExpt(this->eventsPerExpt());
2699 
2700  LauIsobarDynamics* sigModel(0);
2701  LauPdfList* sigPdfs(0);
2702  LauPdfList* scfPdfs(0);
2703  LauBkgndPdfsList* bkgndPdfs(0);
2704 
2705  for (UInt_t iEvt = 0; iEvt < evtsPerExpt; ++iEvt) {
2706 
2707  this->setSPlotNtupleIntegerBranchValue("iExpt",this->iExpt());
2708  this->setSPlotNtupleIntegerBranchValue("iEvtWithinExpt",iEvt);
2709 
2710  // Find out whether we have B- or B+
2711  if ( tagged_ ) {
2712  const LauFitData& dataValues = inputFitData->getData(iEvt);
2713  LauFitData::const_iterator iter = dataValues.find("charge");
2714  curEvtCharge_ = static_cast<Int_t>(iter->second);
2715 
2716  if (curEvtCharge_==+1) {
2717  sigModel = posSigModel_;
2718  sigPdfs = &posSignalPdfs_;
2719  scfPdfs = &posScfPdfs_;
2720  bkgndPdfs = &posBkgndPdfs_;
2721  } else {
2722  sigModel = negSigModel_;
2723  sigPdfs = &negSignalPdfs_;
2724  scfPdfs = &negScfPdfs_;
2725  bkgndPdfs = &negBkgndPdfs_;
2726  }
2727  } else {
2728  sigPdfs = &negSignalPdfs_;
2729  scfPdfs = &negScfPdfs_;
2730  bkgndPdfs = &negBkgndPdfs_;
2731  }
2732 
2733  // the DP information
2734  this->getEvtDPLikelihood(iEvt);
2735  if (this->storeDPEff()) {
2736  if (!this->useDP()) {
2739  }
2740  if ( tagged_ ) {
2741  this->setSPlotNtupleDoubleBranchValue("efficiency",sigModel->getEvtEff());
2743  this->setSPlotNtupleDoubleBranchValue("scffraction",sigModel->getEvtScfFraction());
2744  }
2745  } else {
2749  }
2750  }
2751  }
2752  if (this->useDP()) {
2754  if (useSCF_) {
2756  this->setSPlotNtupleDoubleBranchValue("sigTMDPLike",sigDPLike_);
2757  this->setSPlotNtupleDoubleBranchValue("sigSCFDPLike",scfDPLike_);
2758  } else {
2759  this->setSPlotNtupleDoubleBranchValue("sigDPLike",sigDPLike_);
2760  }
2761  if (usingBkgnd_) {
2762  const UInt_t nBkgnds = this->nBkgndClasses();
2763  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2764  TString name = this->bkgndClassName(iBkgnd);
2765  name += "DPLike";
2766  this->setSPlotNtupleDoubleBranchValue(name,bkgndDPLike_[iBkgnd]);
2767  }
2768  }
2769  } else {
2770  sigTotalLike_ = 1.0;
2771  if (useSCF_) {
2772  scfTotalLike_ = 1.0;
2773  }
2774  if (usingBkgnd_) {
2775  const UInt_t nBkgnds = this->nBkgndClasses();
2776  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2777  bkgndTotalLike_[iBkgnd] = 1.0;
2778  }
2779  }
2780  }
2781 
2782  // the signal PDF values
2783  if ( useSCF_ ) {
2784  sigTotalLike_ *= this->setSPlotNtupleBranchValues(sigPdfs, "sigTM", iEvt);
2785  scfTotalLike_ *= this->setSPlotNtupleBranchValues(scfPdfs, "sigSCF", iEvt);
2786  } else {
2787  sigTotalLike_ *= this->setSPlotNtupleBranchValues(sigPdfs, "sig", iEvt);
2788  }
2789 
2790  // the background PDF values
2791  if (usingBkgnd_) {
2792  const UInt_t nBkgnds = this->nBkgndClasses();
2793  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2794  const TString& bkgndClass = this->bkgndClassName(iBkgnd);
2795  LauPdfList& pdfs = (*bkgndPdfs)[iBkgnd];
2796  bkgndTotalLike_[iBkgnd] *= this->setSPlotNtupleBranchValues(&(pdfs), bkgndClass, iEvt);
2797  }
2798  }
2799 
2800  // the total likelihoods
2801  if (useSCF_) {
2802  Double_t scfFrac(0.0);
2803  if ( useSCFHist_ ) {
2804  scfFrac = recoSCFFracs_[iEvt];
2805  } else {
2806  scfFrac = scfFrac_.unblindValue();
2807  }
2808  this->setSPlotNtupleDoubleBranchValue("sigSCFFrac",scfFrac);
2809  sigTotalLike_ *= ( 1.0 - scfFrac );
2810  if ( scfMap_ == 0 ) {
2811  scfTotalLike_ *= scfFrac;
2812  }
2813  this->setSPlotNtupleDoubleBranchValue("sigTMTotalLike",sigTotalLike_);
2814  this->setSPlotNtupleDoubleBranchValue("sigSCFTotalLike",scfTotalLike_);
2815  } else {
2816  this->setSPlotNtupleDoubleBranchValue("sigTotalLike",sigTotalLike_);
2817  }
2818  if (usingBkgnd_) {
2819  const UInt_t nBkgnds = this->nBkgndClasses();
2820  for ( UInt_t iBkgnd(0); iBkgnd < nBkgnds; ++iBkgnd ) {
2821  TString name = this->bkgndClassName(iBkgnd);
2822  name += "TotalLike";
2824  }
2825  }
2826  // fill the tree
2827  this->fillSPlotNtupleBranches();
2828  }
2829  std::cout << "INFO in LauCPFitModel::storePerEvtLlhds : Finished storing per-event likelihood values." << std::endl;
2830 }
2831 
2832 void LauCPFitModel::embedNegSignal(const TString& fileName, const TString& treeName,
2833  Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment,
2834  Bool_t useReweighting)
2835 {
2836  if (negSignalTree_) {
2837  std::cerr << "ERROR in LauCPFitModel::embedNegSignal : Already embedding signal from a file." << std::endl;
2838  return;
2839  }
2840 
2841  if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
2842  std::cerr << "WARNING in LauCPFitModel::embedNegSignal : Conflicting options provided, will not reuse events at all." << std::endl;
2843  reuseEventsWithinExperiment = kFALSE;
2844  }
2845 
2846  negSignalTree_ = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment);
2847  Bool_t dataOK = negSignalTree_->findBranches();
2848  if (!dataOK) {
2849  delete negSignalTree_; negSignalTree_ = 0;
2850  std::cerr << "ERROR in LauCPFitModel::embedNegSignal : Problem creating data tree for embedding." << std::endl;
2851  return;
2852  }
2853  reuseSignal_ = reuseEventsWithinEnsemble;
2854  useNegReweighting_ = useReweighting;
2855  if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);}
2856 }
2857 
2858 void LauCPFitModel::embedNegBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName,
2859  Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment)
2860 {
2861  if ( ! this->validBkgndClass( bkgndClass ) ) {
2862  std::cerr << "ERROR in LauCPFitModel::embedBkgnd : Invalid background class \"" << bkgndClass << "\"." << std::endl;
2863  std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl;
2864  return;
2865  }
2866 
2867  UInt_t bkgndID = this->bkgndClassID( bkgndClass );
2868 
2869  if (negBkgndTree_[bkgndID]) {
2870  std::cerr << "ERROR in LauCPFitModel::embedNegBkgnd : Already embedding background from a file." << std::endl;
2871  return;
2872  }
2873 
2874  if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
2875  std::cerr << "WARNING in LauCPFitModel::embedNegBkgnd : Conflicting options provided, will not reuse events at all." << std::endl;
2876  reuseEventsWithinExperiment = kFALSE;
2877  }
2878 
2879  negBkgndTree_[bkgndID] = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment);
2880  Bool_t dataOK = negBkgndTree_[bkgndID]->findBranches();
2881  if (!dataOK) {
2882  delete negBkgndTree_[bkgndID]; negBkgndTree_[bkgndID] = 0;
2883  std::cerr << "ERROR in LauCPFitModel::embedNegBkgnd : Problem creating data tree for embedding." << std::endl;
2884  return;
2885  }
2886  reuseBkgnd_[bkgndID] = reuseEventsWithinEnsemble;
2887  if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);}
2888 }
2889 
2890 void LauCPFitModel::embedPosSignal(const TString& fileName, const TString& treeName,
2891  Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment,
2892  Bool_t useReweighting)
2893 {
2894  if (posSignalTree_) {
2895  std::cerr << "ERROR in LauCPFitModel::embedPosSignal : Already embedding signal from a file." << std::endl;
2896  return;
2897  }
2898 
2899  if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
2900  std::cerr << "WARNING in LauCPFitModel::embedPosSignal : Conflicting options provided, will not reuse events at all." << std::endl;
2901  reuseEventsWithinExperiment = kFALSE;
2902  }
2903 
2904  posSignalTree_ = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment);
2905  Bool_t dataOK = posSignalTree_->findBranches();
2906  if (!dataOK) {
2907  delete posSignalTree_; posSignalTree_ = 0;
2908  std::cerr << "ERROR in LauCPFitModel::embedPosSignal : Problem creating data tree for embedding." << std::endl;
2909  return;
2910  }
2911  reuseSignal_ = reuseEventsWithinEnsemble;
2912  usePosReweighting_ = useReweighting;
2913  if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);}
2914 }
2915 
2916 void LauCPFitModel::embedPosBkgnd(const TString& bkgndClass, const TString& fileName, const TString& treeName,
2917  Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment)
2918 {
2919  if ( ! this->validBkgndClass( bkgndClass ) ) {
2920  std::cerr << "ERROR in LauCPFitModel::embedBkgnd : Invalid background class \"" << bkgndClass << "\"." << std::endl;
2921  std::cerr << " : Background class names must be provided in \"setBkgndClassNames\" before any other background-related actions can be performed." << std::endl;
2922  return;
2923  }
2924 
2925  UInt_t bkgndID = this->bkgndClassID( bkgndClass );
2926 
2927  if (posBkgndTree_[bkgndID]) {
2928  std::cerr << "ERROR in LauCPFitModel::embedPosBkgnd : Already embedding background from a file." << std::endl;
2929  return;
2930  }
2931 
2932  if (!reuseEventsWithinEnsemble && reuseEventsWithinExperiment) {
2933  std::cerr << "WARNING in LauCPFitModel::embedPosBkgnd : Conflicting options provided, will not reuse events at all." << std::endl;
2934  reuseEventsWithinExperiment = kFALSE;
2935  }
2936 
2937  posBkgndTree_[bkgndID] = new LauEmbeddedData(fileName,treeName,reuseEventsWithinExperiment);
2938  Bool_t dataOK = posBkgndTree_[bkgndID]->findBranches();
2939  if (!dataOK) {
2940  delete posBkgndTree_[bkgndID]; posBkgndTree_[bkgndID] = 0;
2941  std::cerr << "ERROR in LauCPFitModel::embedPosBkgnd : Problem creating data tree for embedding." << std::endl;
2942  return;
2943  }
2944  reuseBkgnd_[bkgndID] = reuseEventsWithinEnsemble;
2945  if (this->enableEmbedding() == kFALSE) {this->enableEmbedding(kTRUE);}
2946 }
2947 
2948 void LauCPFitModel::weightEvents( const TString& /*dataFileName*/, const TString& /*dataTreeName*/ )
2949 {
2950  std::cerr << "ERROR in LauCPFitModel::weightEvents : Method not available for this fit model." << std::endl;
2951  return;
2952 }
2953 
2954 
2955 void LauCPFitModel::savePDFPlots(const TString& label)
2956 {
2957  savePDFPlotsWave(label, 0);
2958  savePDFPlotsWave(label, 1);
2959  savePDFPlotsWave(label, 2);
2960 
2961  std::cout << "LauCPFitModel::plot" << std::endl;
2962 // ((LauIsobarDynamics*)negSigModel_)->plot();
2963 
2964 
2965 
2966  //Double_t minm13 = negSigModel_->getKinematics()->getm13Min();
2967  Double_t minm13 = 0.0;
2968  Double_t maxm13 = negSigModel_->getKinematics()->getm13Max();
2969  //Double_t minm23 = negSigModel_->getKinematics()->getm23Min();
2970  Double_t minm23 = 0.0;
2971  Double_t maxm23 = negSigModel_->getKinematics()->getm23Max();
2972 
2973  Double_t mins13 = minm13*minm13;
2974  Double_t maxs13 = maxm13*maxm13;
2975  Double_t mins23 = minm23*minm23;
2976  Double_t maxs23 = maxm23*maxm23;
2977 
2978  Double_t s13, s23, posChPdf, negChPdf;
2979 
2980  TString xLabel = "s13";
2981  TString yLabel = "s23";
2982 
2983  if (negSigModel_->getDaughters()->gotSymmetricalDP()) { xLabel = "sHigh"; yLabel = "sLow";}
2984 
2985  Int_t n13=200.00, n23=200.00;
2986  Double_t delta13, delta23;
2987  delta13 = (maxs13 - mins13)/n13;
2988  delta23 = (maxs23 - mins23)/n23;
2989  UInt_t nAmp = negSigModel_->getnCohAmp();
2990  for (UInt_t resID = 0; resID <= nAmp; ++resID)
2991  {
2992  TGraph2D *posDt = new TGraph2D();
2993  TGraph2D *negDt = new TGraph2D();
2994  TGraph2D *acpDt = new TGraph2D();
2995 
2996  TString resName = "TotalAmp";
2997  if (resID != nAmp){
2998  TString tStrResID = Form("%d", resID);
2999  const LauIsobarDynamics* model = negSigModel_;
3000  const LauAbsResonance* resonance = model->getResonance(resID);
3001  resName = resonance->getResonanceName();
3002  std::cout << "resName = " << resName << std::endl;
3003  }
3004 
3005 
3006  resName.ReplaceAll("(", "");
3007  resName.ReplaceAll(")", "");
3008  resName.ReplaceAll("*", "Star");
3009 
3010  posDt->SetName(resName+label);
3011  posDt->SetTitle(resName+" ("+label+") Positive");
3012  negDt->SetName(resName+label);
3013  negDt->SetTitle(resName+" ("+label+") Negative");
3014  acpDt->SetName(resName+label);
3015  acpDt->SetTitle(resName+" ("+label+") Asymmetry");
3016 
3017  Int_t count=0;
3018  for (Int_t i=0; i<n13; i++) {
3019  s13 = mins13 + i*delta13;
3020  for (Int_t j=0; j<n23; j++) {
3021  s23 = mins23 + j*delta23;
3022  if (negSigModel_->getKinematics()->withinDPLimits2(s23, s13))
3023  {
3024  if (negSigModel_->getDaughters()->gotSymmetricalDP() && (s13>s23) ) continue;
3025 
3026  negSigModel_->calcLikelihoodInfo(s13, s23);
3027  posSigModel_->calcLikelihoodInfo(s13, s23);
3028 
3029  LauComplex negChAmp = negSigModel_->getEvtDPAmp();
3030  LauComplex posChAmp = posSigModel_->getEvtDPAmp();
3031 
3032  if (resID != nAmp){
3033  negChAmp = negSigModel_->getFullAmplitude(resID);
3034  posChAmp = posSigModel_->getFullAmplitude(resID);
3035  }
3036  negChPdf = negChAmp.abs2();
3037  posChPdf = posChAmp.abs2();
3038  negDt->SetPoint(count,s23,s13,negChPdf); // s23=sHigh, s13 = sLow
3039  posDt->SetPoint(count,s23,s13,posChPdf); // s23=sHigh, s13 = sLow
3040  acpDt->SetPoint(count,s23,s13, negChPdf - posChPdf); // s23=sHigh, s13 = sLow
3041  count++;
3042  }
3043  }
3044  }
3045  gStyle->SetPalette(1);
3046  TCanvas *posC = new TCanvas("c"+resName+label + "Positive",resName+" ("+label+") Positive",0,0,600,400);
3047  posDt->GetXaxis()->SetTitle(xLabel);
3048  posDt->GetYaxis()->SetTitle(yLabel);
3049  posDt->Draw("SURF1");
3050  posDt->GetXaxis()->SetTitle(xLabel);
3051  posDt->GetYaxis()->SetTitle(yLabel);
3052  posC->SaveAs("plot_2D_"+resName + "_"+label+"Positive.C");
3053 
3054  TCanvas *negC = new TCanvas("c"+resName+label + "Negative",resName+" ("+label+") Negative",0,0,600,400);
3055  negDt->GetXaxis()->SetTitle(xLabel);
3056  negDt->GetYaxis()->SetTitle(yLabel);
3057  negDt->Draw("SURF1");
3058  negDt->GetXaxis()->SetTitle(xLabel);
3059  negDt->GetYaxis()->SetTitle(yLabel);
3060  negC->SaveAs("plot_2D_"+resName + "_"+label+"Negative.C");
3061 
3062  TCanvas *acpC = new TCanvas("c"+resName+label + "Asymmetry",resName+" ("+label+") Asymmetry",0,0,600,400);
3063  acpDt->GetXaxis()->SetTitle(xLabel);
3064  acpDt->GetYaxis()->SetTitle(yLabel);
3065  acpDt->Draw("SURF1");
3066  acpDt->GetXaxis()->SetTitle(xLabel);
3067  acpDt->GetYaxis()->SetTitle(yLabel);
3068  acpC->SaveAs("plot_2D_"+resName + "_"+label+"Asymmetry.C");
3069  }
3070 }
3071 
3072 void LauCPFitModel::savePDFPlotsWave(const TString& label, const Int_t& spin)
3073 {
3074 
3075  std::cout << "label = "<< label << ", spin = "<< spin << std::endl;
3076 
3077  TString tStrResID = "S_Wave";
3078  if (spin == 1) tStrResID = "P_Wave";
3079  if (spin == 2) tStrResID = "D_Wave";
3080 
3081  TString xLabel = "s13";
3082  TString yLabel = "s23";
3083 
3084  std::cout << "LauSimpleFitModel::savePDFPlotsWave: "<< tStrResID << std::endl;
3085 
3086  Double_t minm13 = 0.0;
3087  Double_t maxm13 = negSigModel_->getKinematics()->getm13Max();
3088  Double_t minm23 = 0.0;
3089  Double_t maxm23 = negSigModel_->getKinematics()->getm23Max();
3090 
3091  Double_t mins13 = minm13*minm13;
3092  Double_t maxs13 = maxm13*maxm13;
3093  Double_t mins23 = minm23*minm23;
3094  Double_t maxs23 = maxm23*maxm23;
3095 
3096  Double_t s13, s23, posChPdf, negChPdf;
3097  TGraph2D *posDt = new TGraph2D();
3098  TGraph2D *negDt = new TGraph2D();
3099  TGraph2D *acpDt = new TGraph2D();
3100 
3101 
3102  posDt->SetName(tStrResID+label);
3103  posDt->SetTitle(tStrResID+" ("+label+") Positive");
3104  negDt->SetName(tStrResID+label);
3105  negDt->SetTitle(tStrResID+" ("+label+") Negative");
3106  acpDt->SetName(tStrResID+label);
3107  acpDt->SetTitle(tStrResID+" ("+label+") Asymmetry");
3108 
3109  Int_t n13=200.00, n23=200.00;
3110  Double_t delta13, delta23;
3111  delta13 = (maxs13 - mins13)/n13;
3112  delta23 = (maxs23 - mins23)/n23;
3113  UInt_t nAmp = negSigModel_->getnCohAmp();
3114 
3115  Int_t count=0;
3116  for (Int_t i=0; i<n13; i++)
3117  {
3118  s13 = mins13 + i*delta13;
3119  for (Int_t j=0; j<n23; j++)
3120  {
3121  s23 = mins23 + j*delta23;
3122  if (negSigModel_->getKinematics()->withinDPLimits2(s23, s13))
3123  {
3124  if (negSigModel_->getDaughters()->gotSymmetricalDP() && (s13>s23) ) continue;
3125 
3126  LauComplex negChAmp(0,0);
3127  LauComplex posChAmp(0,0);
3128  Bool_t noWaveRes = kTRUE;
3129  negSigModel_->calcLikelihoodInfo(s13, s23);
3130  for (UInt_t resID = 0; resID < nAmp; ++resID)
3131  {
3132  const LauIsobarDynamics* model = negSigModel_;
3133  const LauAbsResonance* resonance = model->getResonance(resID);
3134  Int_t spin_res = resonance->getSpin();
3135  if (spin != spin_res) continue;
3136  noWaveRes = kFALSE;
3137  negChAmp += negSigModel_->getFullAmplitude(resID);
3138  posChAmp += posSigModel_->getFullAmplitude(resID);
3139  }
3140 
3141  if (noWaveRes) return;
3142 
3143  negChPdf = negChAmp.abs2();
3144  posChPdf = posChAmp.abs2();
3145 
3146  negDt->SetPoint(count,s23,s13,negChPdf); // s23=sHigh, s13 = sLow
3147  posDt->SetPoint(count,s23,s13,posChPdf); // s23=sHigh, s13 = sLow
3148  acpDt->SetPoint(count,s23,s13, negChPdf - posChPdf); // s23=sHigh, s13 = sLow
3149  count++;
3150 
3151  }
3152  }
3153  }
3154  gStyle->SetPalette(1);
3155  TCanvas *posC = new TCanvas("c"+tStrResID+label + "Positive",tStrResID+" ("+label+") Positive",0,0,600,400);
3156  posDt->GetXaxis()->SetTitle(xLabel);
3157  posDt->GetYaxis()->SetTitle(yLabel);
3158  posDt->Draw("SURF1");
3159  posDt->GetXaxis()->SetTitle(xLabel);
3160  posDt->GetYaxis()->SetTitle(yLabel);
3161  posC->SaveAs("plot_2D_"+tStrResID + "_"+label+"Positive.C");
3162 
3163  TCanvas *negC = new TCanvas("c"+tStrResID+label + "Negative",tStrResID+" ("+label+") Negative",0,0,600,400);
3164  negDt->GetXaxis()->SetTitle(xLabel);
3165  negDt->GetYaxis()->SetTitle(yLabel);
3166  negDt->Draw("SURF1");
3167  negDt->GetXaxis()->SetTitle(xLabel);
3168  negDt->GetYaxis()->SetTitle(yLabel);
3169  negC->SaveAs("plot_2D_"+tStrResID + "_"+label+"Negative.C");
3170 
3171  TCanvas *acpC = new TCanvas("c"+tStrResID+label + "Asymmetry",tStrResID+" ("+label+") Asymmetry",0,0,600,400);
3172  acpDt->GetXaxis()->SetTitle(xLabel);
3173  acpDt->GetYaxis()->SetTitle(yLabel);
3174  acpDt->Draw("SURF1");
3175  acpDt->GetXaxis()->SetTitle(xLabel);
3176  acpDt->GetYaxis()->SetTitle(yLabel);
3177  acpC->SaveAs("plot_2D_"+tStrResID + "_"+label+"Asymmetry.C");
3178 
3179 
3180 }
3181 
3182 
3183 
3184 
3185 
3186 
3187 
Double_t range() const
The range allowed for the parameter.
void generateExtraPdfValues(LauPdfList *extraPdfs, LauEmbeddedData *embeddedData)
Generate from the extra PDFs.
void modifyDataTree()
Recache the amplitude values for those that have changed.
Bool_t generateSignalEvent()
Generate signal event.
virtual void addSPlotNtupleIntegerBranch(const TString &name)
Add a branch to the sPlot tree for storing an integer.
Double_t getm23Max() const
Get the m23 maximum defined as (mParent - m1)
The abstract interface for a background Dalitz plot model.
Bool_t squareDP() const
Are the square Dalitz plot co-ordinates being calculated?
std::vector< LauParameter > acp_
A_CP parameter.
virtual LauSPlot::NameSet variableNames() const
Returns the names of all variables in the fit.
Double_t getc23() const
Get the cosine of the helicity angle theta23.
TRandom * randomFun()
Access the singleton random number generator with a particular seed.
Definition: LauRandom.cc:20
const LauParameter & getDPRate() const
Retrieve the overall Dalitz plot rate.
std::vector< LauParameter > LauParameterList
List of parameters.
Bool_t fixed() const
Check whether the parameter is fixed or floated.
LauKinematics * negKinematics_
The B- Dalitz plot kinematics object.
UInt_t nEvents() const
Retrieve the number of events.
UInt_t eventsPerExpt() const
Obtain the total number of events in the current experiment.
virtual void printAsymmetries(std::ostream &output)
Print the asymmetries.
Bool_t writeLatexTable() const
Determine whether writing out of the latex table is enabled.
LauPdfList negSignalPdfs_
The B- signal PDFs.
void addSPlotNtupleBranches(const LauPdfList *extraPdfs, const TString &prefix)
Add sPlot branches for the extra PDFs.
const TString & getResonanceName() const
Get the name of the resonance.
Bool_t forceAsym_
Option to force an asymmetry.
Double_t scfTotalLike_
Total SCF likelihood.
void setExtraPdfParameters()
Set the fit parameters for the extra PDFs.
void updateCoeffs(const std::vector< LauComplex > &coeffs)
Update the complex coefficients for the resonances.
void updateSqDPKinematics(Double_t mPrime, Double_t thetaPrime)
Update all kinematic quantities based on the square DP co-ordinates m&#39; and theta&#39;.
LauBkgndDPModelList posBkgndDPModels_
The B+ background Dalitz plot models.
void setEffHisto(const TH2 *effHisto, Bool_t useInterpolation=kTRUE, Bool_t fluctuateBins=kFALSE, Double_t avEff=-1.0, Double_t absError=-1.0, Bool_t useUpperHalfOnly=kFALSE, Bool_t squareDP=kFALSE)
Set the efficiency variation across the phase space using a predetermined 2D histogram.
Definition: LauEffModel.cc:55
void cacheInfo(LauPdfList &pdfList, const LauFitDataTree &theData)
Have all PDFs in the list cache the data.
virtual void setGenNtupleIntegerBranchValue(const TString &name, Int_t value)
Set the value of an integer branch in the gen tree.
File containing declaration of LauAsymmCalc class.
ClassImp(LauAbsCoeffSet)
UInt_t nNormPar_
Number of normalisation parameters (yields, asymmetries)
LauEmbeddedData * posSignalTree_
The B+ signal event tree.
Bool_t getReweightedEvent(LauIsobarDynamics *dynamics)
Retrieve an event from the data sample, applying an accept/reject based on the given DP model...
LauParameter()
Default constructor.
Definition: LauParameter.cc:30
const LauParameter & getMeanEff() const
Retrieve the mean efficiency across the Dalitz plot.
Double_t getm23() const
Get the m23 invariant mass.
Int_t curEvtCharge_
Current event charge.
Bool_t withinDPLimits2(Double_t m13Sq, Double_t m23Sq) const
Check whether a given (m13Sq,m23Sq) point is within the kinematic limits of the Dalitz plot (alternat...
void calcExtraFractions(Bool_t initValues=kFALSE)
Calculate the CP-conserving and CP-violating fit fractions.
const TString & name() const
The parameter name.
virtual LauParameter acp()=0
Calculate the CP asymmetry.
const LauKinematics * getKinematics() const
Retrieve the Dalitz plot kinematics.
Double_t getmPrime() const
Get m&#39; value.
Class that defines the particular 3-body decay under study.
Definition: LauDaughters.hh:33
UInt_t addFitParameters(LauPdfList &pdfList)
Add parameters of the PDFs in the list to the list of all fit parameters.
Class for calculating the asymmetry between two variables.
Definition: LauAsymmCalc.hh:25
LauEmbeddedData * negSignalTree_
The B- signal event tree.
Double_t getDPNorm() const
Retrieve the normalisation factor for the log-likelihood function.
Bool_t useDP() const
Is the Dalitz plot term in the likelihood.
Double_t getc13() const
Get the cosine of the helicity angle theta13.
File containing declaration of LauAbsCoeffSet class.
void clearUsedList()
Clear the list of used events.
Bool_t useNegReweighting_
Boolean to use reweighting for B-.
void calcExtraInfo(const Bool_t init=kFALSE)
Calculate the fit fractions, mean efficiency and total DP rate.
TH2 * trueHist(Int_t trueBin)
Retrieve the migration histogram for trueBin.
Definition: LauScfMap.cc:176
std::vector< LauComplex > negCoeffs_
The complex coefficients for B-.
LauBkgndPdfsList posBkgndPdfs_
The B+ background PDFs.
std::multimap< TString, std::pair< TString, TString > > TwoDMap
Type to associate the name of the species that have 2D PDFs with the names of the two variables invol...
Definition: LauSPlot.hh:68
LauParArray negFitFrac_
The B- fit fractions.
void listBinCentres(std::vector< Double_t > &xCoords, std::vector< Double_t > &yCoords) const
Create lists of the co-ordinates of the centres of true bins.
Definition: LauScfMap.cc:114
virtual void getEvtExtraLikelihoods(UInt_t iEvt)
Determine the signal and background likelihood for the extra variables for a given event...
Double_t sigDPLike_
Signal DP likelihood value.
File containing declaration of LauDaughters class.
const std::vector< Int_t > * trueBins(Int_t recoBin) const
Find which true bins contribute to the given reco bin.
Definition: LauScfMap.cc:155
LauPdfList negScfPdfs_
The B- SCF PDFs.
Bool_t useSCF_
Is the signal split into TM and SCF.
virtual Bool_t genExpt()
Toy MC generation and fitting overloaded functions.
virtual void setGenNtupleDoubleBranchValue(const TString &name, Double_t value)
Set the value of a double branch in the gen tree.
TString negParent_
Name of the parent particle.
TString posParent_
Name of the parent particle.
void embedNegSignal(const TString &fileName, const TString &treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment=kFALSE, Bool_t useReweighting=kFALSE)
Embed full simulation events for the B- signal, rather than generating toy from the PDFs...
File containing declaration of LauScfMap class.
Double_t getEvtthPrime() const
Retrieve the square Dalitz plot coordinate, theta&#39;, for the current event.
std::pair< LauGenInfo, Bool_t > eventsToGenerate()
Determine the number of events to generate for each hypothesis.
std::vector< Double_t > fakeSCFFracs_
The cached values of the SCF fraction for each bin centre.
TString getConjResName(const TString &resName) const
Retrieve the name of the charge conjugate of a named resonance.
std::vector< std::vector< LauParameter > > LauParArray
Type to define an array of parameters.
Int_t fitStatus() const
Access the fit status information.
virtual void printParValues() const =0
Print the current values of the parameters.
Bool_t storeSignalMCMatch(LauEmbeddedData *embeddedData)
Store the MC truth info on the TM/SCF nature of the embedded signal event.
Bool_t usingBkgnd_
Background boolean.
File containing declaration of LauPrint class.
Pure abstract base class for defining the efficiency description across the signal Dalitz plot...
Double_t prodPdfValue(LauPdfList &pdfList, UInt_t iEvt)
Calculate the product of the per-event likelihoods of the PDFs in the list.
std::vector< LauAbsPdf * > LauPdfList
List of Pdfs.
std::map< TString, Double_t > LauFitData
Type for holding event data.
LauBkgndYieldList bkgndAsym_
Background asymmetries(s)
LauComplex getFullAmplitude(const Int_t resID) const
Retrieve the Amplitude of resonance resID.
Double_t getm23Sq() const
Get the m23 invariant mass square.
LauIsobarDynamics * negSigModel_
The B- signal Dalitz plot model.
const LauParArray & getFitFractions() const
Retrieve the fit fractions for the amplitude components.
void recalculateNormalisation()
recalculate Normalization
Bool_t squareDP() const
Determine to use or not the square Dalitz plot.
Definition: LauDaughters.hh:78
LauParameter negDPRate_
The average DP rate for B-.
Double_t getEvtScfFraction() const
Retrieve the fraction of events that are poorly reconstructed (the self cross feed fraction) for the ...
Class to define various output print commands.
Definition: LauPrint.hh:29
Double_t getValue(const TString &name) const
Get the value of a specified branch.
std::vector< Double_t > bkgndTotalLike_
Total background likelihood(s)
void calcLikelihoodInfo(const UInt_t iEvt)
Calculate the likelihood (and all associated information) for the given event number.
virtual void fillGenNtupleBranches()
Fill the gen tuple branches.
std::vector< Double_t > recoSCFFracs_
The cached values of the SCF fraction for each event.
LauParameter posDPRate_
The average DP rate for B+.
void updateFitNtuple()
Update the fit ntuple.
std::set< LauParameter * > LauParameterPSet
Set of parameter pointers.
File containing declaration of LauKinematics class.
virtual void setSPlotNtupleDoubleBranchValue(const TString &name, Double_t value)
Set the value of a double branch in the sPlot tree.
File containing declaration of LauEmbeddedData class.
std::vector< Double_t > bkgndExtraLike_
Background likelihood value(s) from extra PDFs.
void setupGenNtupleBranches()
Setup the required ntuple branches.
void printFitParameters(const LauPdfList &pdfList, std::ostream &fout) const
Print the fit parameters for all PDFs in the list.
Double_t getm13Max() const
Get the m13 maximum defined as (mParent - m2)
Double_t scfExtraLike_
SCF likelihood from extra PDFs.
Bool_t haveBranch(const TString &name) const
Boolean to determine whether branch exists.
File containing declaration of LauCPFitModel class.
Bool_t reuseSignal_
Boolean to reuse signal events.
LauParArray posFitFrac_
The B+ fit fractions.
Bool_t usingScfModel() const
Check whether a self cross feed fraction model is being used.
const LauAbsResonance * getResonance(const UInt_t resIndex) const
Retrieve a resonance by its index.
virtual void cacheInputFitVars()
Read in the input fit data variables, e.g. m13Sq and m23Sq.
void setSignalDPParameters()
Set the fit parameters for the DP model.
Double_t getEvtmPrime() const
Retrieve the square Dalitz plot coordinate, m&#39;, for the current event.
void randomiseInitFitPars()
Randomise the initial fit parameters.
void appendBinCentres(LauFitDataTree *inputData)
Append fake data points to the inputData for each bin in the SCF smearing matrix. ...
virtual void savePDFPlotsWave(const TString &label, const Int_t &spin)
Save the pdf Plots for the sum of resonances of a given spin.
File containing declaration of LauIsobarDynamics class.
virtual UInt_t index() const
Retrieve the index number of the coefficient set.
void updateKinematics(Double_t m13Sq, Double_t m23Sq)
Update all kinematic quantities based on the DP co-ordinates m13Sq and m23Sq.
void fillDataTree(const LauFitDataTree &fitDataTree)
Fill the internal data structure that caches the resonance dynamics.
virtual void checkInitFitParams()
Check the initial fit parameters.
const LauParameterList & extraPars() const
Access the extra variables.
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:232
virtual void recalculateNormalisation()
Recalculate Normalization the signal DP models.
std::vector< LauParameter * > LauParameterPList
List of parameter pointers.
const Bool_t tagged_
IS the analysis tagged?
UInt_t nExtraPdfPar_
Number of extra PDF parameters.
Bool_t gotSymmetricalDP() const
Is Dalitz plot symmetric, i.e. 2 identical particles.
Definition: LauDaughters.hh:66
virtual void finaliseFitResults(const TString &tablePrefixName)
Get the fit results and store them.
Double_t getEvtm23Sq() const
Retrieve the invariant mass squared of the second and third daughters in the current event...
Bool_t blind() const
The blinding state.
virtual void printFitFractions(std::ostream &output)
Print the fit fractions, total DP rate and mean efficiency.
Double_t calcEfficiency(const LauKinematics *kinematics) const
Determine the efficiency for a given point in the Dalitz plot.
Definition: LauEffModel.cc:261
LauParArray negFitFracEffUnCorr_
Fit B- fractions (uncorrected for the efficiency)
Class for defining a CP fit model.
Abstract interface to the fitting and toy MC model.
std::vector< LauParameter * > & getFloatingParameters()
Retrieve the floating parameters of the resonance models.
UInt_t iExpt() const
Obtain the number of the current experiment.
const TString tagVarName_
Event charge.
LauParameter * signalEvents_
Signal yield.
LauParArray posFitFracEffUnCorr_
Fit B+ fractions (uncorrected for the efficiency)
virtual void addGenNtupleIntegerBranch(const TString &name)
Add a branch to the gen tree for storing an integer.
const LauComplex & getEvtDPAmp() const
Retrieve the total amplitude for the current event.
std::vector< Int_t > evtCharges_
Vector to store event charges.
const LauFitNtuple * fitNtuple() const
Access the fit ntuple.
Int_t binNumber(Double_t xCoord, Double_t yCoord) const
Find the global bin number for the given co-ordinates.
Definition: LauScfMap.cc:144
Bool_t doPoissonSmearing() const
Determine whether Poisson smearing is enabled for the toy MC generation.
Double_t getc12() const
Get the cosine of the helicity angle theta12.
Double_t getm13() const
Get the m13 invariant mass.
std::vector< LauPdfList > LauBkgndPdfsList
Typedef for a vector of background PDFs.
void calcAsymmetries(Bool_t initValues=kFALSE)
Calculate the CP asymmetries.
std::map< TString, Double_t > NumbMap
Type to associate a category name with a double precision number, e.g. a yield or PDF value for a giv...
Definition: LauSPlot.hh:62
Bool_t doEMLFit() const
Determine whether an extended maximum likelihood fit it being performed.
const LauDaughters * getDaughters() const
Retrieve the daughters.
LauScfMap * scfMap_
The smearing matrix for the SCF DP PDF.
File containing declaration of LauComplex class.
Double_t sigExtraLike_
Signal likelihood from extra PDFs.
LauFitData getValues(const std::vector< TString > &names) const
Get values of specified branches.
const LauParArray & getFitFractionsEfficiencyUncorrected() const
Retrieve the fit fractions for the amplitude components.
virtual void setNBkgndEvents(LauParameter *nBkgndEvents)
Set the background event yield(s)
virtual void initialise()
Initialise the fit.
virtual LauSPlot::NumbMap fixdSpeciesNames() const
Returns the names and yields of species that are fixed in the fit.
Class for defining the abstract interface for complex coefficient classes.
Double_t nll() const
Access the current NLL value.
Double_t sigTotalLike_
Total signal likelihood.
void storeCorrMatrix(UInt_t iExpt, Double_t NLL, Int_t fitStatus, const TMatrixD &covMatrix)
Store the correlation matrix and other fit information.
Definition: LauFitNtuple.cc:61
void clearFitParVectors()
Clear the vectors containing fit parameters.
virtual void setAmpCoeffSet(LauAbsCoeffSet *coeffSet)
Set the DP amplitude coefficients.
Class for defining the fit parameter objects.
Definition: LauParameter.hh:35
Class to store the data for embedding in toy experiments.
UInt_t getnTotAmp() const
Retrieve the total number of amplitude components.
virtual void addSPlotNtupleDoubleBranch(const TString &name)
Add a branch to the sPlot tree for storing a double.
UInt_t nSigComp_
Number of signal components.
virtual void setupSPlotNtupleBranches()
Add branches to store experiment number and the event number within the experiment.
void clearExtraVarVectors()
Clear the vectors containing extra ntuple variables.
LauParameter * signalAsym_
Signal asymmetry.
void getEmbeddedEvent(LauKinematics *kinematics)
Retrieve an event from the data sample.
void splitSignalComponent(const TH2 *dpHisto, const Bool_t upperHalf=kFALSE, const Bool_t fluctuateBins=kFALSE, LauScfMap *scfMap=0)
Split the signal component into well-reconstructed and mis-reconstructed parts.
virtual void savePDFPlots(const TString &label)
Save the pdf Plots for all the resonances.
const LauAbsEffModel * getEffModel() const
Retrieve the model for the efficiency across the Dalitz plot.
std::vector< Double_t > bkgndDPLike_
Background DP likelihood value(s)
void embedNegBkgnd(const TString &bgClass, const TString &fileName, const TString &treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment=kFALSE)
Embed full simulation events for the given background class, rather than generating toy from the PDFs...
LauBkgndEmbDataList negBkgndTree_
The B- background event tree.
void appendFakePoints(const std::vector< Double_t > &xCoords, const std::vector< Double_t > &yCoords)
Add fake events to the data.
File containing declaration of LauAbsPdf class.
Bool_t storeDPEff() const
Determine whether the efficiency information should be stored in the sPlot ntuple.
LauBkgndReuseEventsList reuseBkgnd_
Vector of booleans to reuse background events.
Double_t getEvtIntensity() const
Retrieve the total intensity multiplied by the efficiency for the current event.
std::vector< LauAbsCoeffSet * > coeffPars_
Magnitudes and Phases.
LauParameter posMeanEff_
The mean efficiency for B+ model.
UInt_t bkgndClassID(const TString &className) const
The number assigned to a background class.
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.
Bool_t useRandomInitFitPars() const
Determine whether the initial values of the fit parameters, in particular the isobar coefficient para...
File containing declaration of LauEffModel class.
const LauFitDataTree * fitData() const
Access the data store.
LauParArray CPCFitFrac_
The CP conserving fit fraction.
virtual void setNSigEvents(LauParameter *nSigEvents)
Set the signal event yield.
virtual void weightEvents(const TString &dataFileName, const TString &dataTreeName)
Weight events based on the DP model.
Bool_t validBkgndClass(const TString &className) const
Check if the given background class is in the list.
Bool_t usePosReweighting_
Boolean to use reweighting for B+.
Bool_t generateBkgndEvent(UInt_t bgID)
Generate background event.
virtual void writeOutTable(const TString &outputFile)
Write the fit results in latex table format.
Double_t getm12Sq() const
Get the m12 invariant mass square.
Class that implements the efficiency description across the signal Dalitz plot.
Definition: LauEffModel.hh:37
Int_t resonanceIndex(const TString &resName) const
Retrieve the index for the given resonance.
Abstract class for defining type for resonance amplitude models (Breit-Wigner, Flatte etc...
TString getNameParent() const
Get name of the parent particle.
const LauParameterPSet & resPars() const
Access the fit variables which affect the DP normalisation.
UInt_t nUsedEvents() const
Retrieve the number of events that have already been sampled.
Double_t getm13Sq() const
Get the m13 invariant mass square.
void storeParsAndErrors(const std::vector< LauParameter * > &fitVars, const std::vector< LauParameter > &extraVars)
Store parameters and their errors.
virtual void updateCoeffs()
Update the coefficients.
virtual void setSPlotNtupleIntegerBranchValue(const TString &name, Int_t value)
Set the value of an integer branch in the sPlot tree.
Double_t setSPlotNtupleBranchValues(LauPdfList *extraPdfs, const TString &prefix, UInt_t iEvt)
Set the branches for the sPlot ntuple with extra PDFs.
Double_t initValue() const
The initial value of the parameter.
virtual ~LauCPFitModel()
Destructor.
std::vector< LauComplex > posCoeffs_
The complex coefficients for B+.
virtual void initialiseDPModels()
Initialise the signal DP models.
void updateSigEvents()
Update the signal events after Minuit sets background parameters.
Class for defining signal dynamics using the isobar model.
Double_t getm12() const
Get the m12 invariant mass.
virtual void fillSPlotNtupleBranches()
Fill the sPlot tuple.
virtual void setupBkgndVectors()
Define the length of the background vectors.
File containing LauConstants namespace.
void setSignalPdfs(LauAbsPdf *negPdf, LauAbsPdf *posPdf)
Set the signal PDFs.
void setFitNEvents()
Set the initial yields.
virtual LauSPlot::TwoDMap twodimPDFs() const
Returns the species and variables for all 2D PDFs in the fit.
virtual LauSPlot::NumbMap freeSpeciesNames() const
Returns the names and yields of species that are free in the fit.
LauEffModel * scfFracHist_
The histogram giving the DP-dependence of the SCF fraction.
void printFormat(std::ostream &stream, Double_t value) const
Method to choose the printing format to a specified level of precision.
Definition: LauPrint.cc:32
Double_t unblindValue() const
The unblinded value of the parameter.
ToyMCStatus checkToyMC(Bool_t printErrorMessages=kTRUE, Bool_t printInfoMessages=kFALSE)
Check the status of the toy MC generation.
Class to store the results from the fit into an ntuple.
Definition: LauFitNtuple.hh:42
UInt_t getnCohAmp() const
Retrieve the number of coherent amplitude components.
UInt_t nSigDPPar_
Number of signal DP parameters.
Bool_t haveBranch(const TString &name) const
Check if the named branch is stored.
virtual void propagateParUpdates()
Calculate things that depend on the fit parameters after they have been updated by Minuit...
Class for representing the 4D smearing matrix for mis-reconstructed signal (self cross feed) ...
Definition: LauScfMap.hh:29
virtual void storePerEvtLlhds()
Store the per event likelihood values.
Double_t scfDPLike_
SCF DP likelihood value.
Double_t getThetaPrime() const
Get theta&#39; value.
Class for defining a complex number.
Definition: LauComplex.hh:47
void updatePull()
Call to update the bias and pull values.
Double_t getEvtEff() const
Retrieve the efficiency for the current event.
UInt_t nBkgndClasses() const
Returns the number of background classes.
const TString & bkgndClassName(UInt_t classID) const
Get the name of a background class from the number.
std::vector< Double_t > recoJacobians_
The cached values of the sqDP jacobians for each event.
Bool_t enableEmbedding() const
Determine whether embedding of events is enabled in the generation.
virtual Double_t getEventSum() const
Get the total number of events.
virtual TString name() const
Retrieve the name of the coefficient set.
Class for defining the abstract interface for PDF classes.
Definition: LauAbsPdf.hh:41
LauIsobarDynamics * posSigModel_
The B+ signal Dalitz plot model.
const TMatrixD & covarianceMatrix() const
Access the fit covariance matrix.
const LauParameterPList & fitPars() const
Access the fit variables.
LauPdfList posScfPdfs_
The B+ SCF PDFs.
LauBkgndYieldList bkgndEvents_
Background yield(s)
Class for calculating 3-body kinematic quantities.
Double_t value() const
The value of the parameter.
LauBkgndDPModelList negBkgndDPModels_
The B- background Dalitz plot models.
UInt_t nEvents() const
Retrieve the number of events.
LauParArray CPVFitFrac_
The CP violating fit fraction.
virtual void addGenNtupleDoubleBranch(const TString &name)
Add a branch to the gen tree for storing a double.
LauPdfList posSignalPdfs_
The B+ signal PDFs.
void updateFitParameters(LauPdfList &pdfList)
Update the fit parameters for all PDFs in the list.
void embedPosBkgnd(const TString &bgClass, const TString &fileName, const TString &treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment=kFALSE)
Embed full simulation events for the given background class, rather than generating toy from the PDFs...
std::vector< Double_t > fakeJacobians_
The cached values of the sqDP jacobians for each true bin.
virtual const TString & baseName() const
Retrieve the base name of the coefficient set.
Double_t getAsymmetry()
Retrieve the asymmetry.
Definition: LauAsymmCalc.hh:48
virtual Double_t getEvtSCFDPLikelihood(UInt_t iEvt)
Calculate the SCF likelihood for the DP for a given event.
const std::vector< LauParameter > & getExtraParameters() const
Retrieve any extra parameters/quantities (e.g. K-matrix total fit fractions)
Bool_t findBranches()
Find and read the branches in data tree.
Int_t getSpin() const
Get the spin of the resonance.
File containing declaration of LauAbsBkgndDPModel class.
void setSCFPdfs(LauAbsPdf *negPdf, LauAbsPdf *posPdf)
Set the SCF PDF for a given variable.
std::map< std::pair< TString, Int_t >, std::pair< Int_t, Double_t > > LauGenInfo
Define a map to be used to store a category name and numbers.
Bool_t useSCFHist_
Is the SCF fraction DP-dependent.
LauParameter negMeanEff_
The mean efficiency for B- model.
void setBkgndPdfs(const TString &bkgndClass, LauAbsPdf *negPdf, LauAbsPdf *posPdf)
Set the background PDFs.
Double_t prob(Int_t recoBin, Int_t trueBin) const
Probability of a true event in the given true bin migrating to the reco bin.
Definition: LauScfMap.cc:165
void initialise(const std::vector< LauComplex > &coeffs)
Initialise the Dalitz plot dynamics.
virtual Double_t getTotEvtLikelihood(UInt_t iEvt)
Get the total likelihood for each event.
virtual void getEvtDPLikelihood(UInt_t iEvt)
Calculate the signal and background likelihoods for the DP for a given event.
Double_t getEvtm13Sq() const
Retrieve the invariant mass squared of the first and third daughters in the current event...
Double_t genValue() const
The value generated for the parameter.
LauBkgndEmbDataList posBkgndTree_
The B+ background event tree.
void setBkgndDPModels(const TString &bkgndClass, LauAbsBkgndDPModel *negModel, LauAbsBkgndDPModel *posModel)
Set the background DP models.
LauBkgndPdfsList negBkgndPdfs_
The B- background PDFs.
Class to store the input fit variables.
LauParameter scfFrac_
The (global) SCF fraction parameter.
std::set< TString > NameSet
Type to store names, e.g. of the discriminating/control variables.
Definition: LauSPlot.hh:59
File containing declaration of LauFitNtuple class.
void setDPBranchValues()
Store all of the DP information.
LauKinematics * posKinematics_
The B+ Dalitz plot kinematics object.
void embedPosSignal(const TString &fileName, const TString &treeName, Bool_t reuseEventsWithinEnsemble, Bool_t reuseEventsWithinExperiment=kFALSE, Bool_t useReweighting=kFALSE)
Embed full simulation events for the B+ signal, rather than generating toy from the PDFs...
std::vector< LauParameter > fitFracAsymm_
The fit fraction asymmetries.
virtual Bool_t generate()=0
Generate a toy MC event from the model.
void setExtraNtupleVars()
Set-up other parameters that are derived from the fit results, e.g. fit fractions.
virtual Bool_t passVeto(const LauKinematics *kinematics) const =0
Determine whether the given DP position is outside the vetoes.