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