laura is hosted by Hepforge, IPPP Durham
Laura++  v3r1
A maximum likelihood fitting package for performing Dalitz-plot analysis.
LauFitNtuple.cc
Go to the documentation of this file.
1 
2 // Copyright University of Warwick 2004 - 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 // Authors:
7 // Thomas Latham
8 // John Back
9 // Paul Harrison
10 
15 #include <iostream>
16 
17 #include "TFile.h"
18 #include "TMath.h"
19 #include "TMatrixD.h"
20 #include "TSystem.h"
21 #include "TTree.h"
22 
23 #include "LauAbsFitter.hh"
24 #include "LauFitNtuple.hh"
25 #include "LauFitter.hh"
26 #include "LauParameter.hh"
27 #include "LauParamFixed.hh"
28 
30 
31 
32 LauFitNtuple::LauFitNtuple(const TString& fileName, Bool_t storeAsymErrors) :
33  rootFileName_(fileName),
34  rootFile_(0),
35  fitResults_(0),
36  definedFitTree_(kFALSE),
37  storeAsymErrors_(storeAsymErrors),
38  fitStatus_(0),
39  nFitPars_(0),
40  nFreePars_(0),
41  nExtraPars_(0),
42  NLL_(0.0),
43  iExpt_(0)
44 {
45  rootFile_ = TFile::Open(rootFileName_, "recreate");
46  rootFile_->cd();
47  fitResults_ = new TTree("fitResults", "fitResults");
48  fitResults_->SetDirectory(rootFile_);
49 
50  fitVars_.clear(); extraVars_.clear();
51 }
52 
54 {
55  if (rootFile_ && rootFile_->IsOpen()) {
56  delete fitResults_; fitResults_ = 0;
57  }
58  delete rootFile_; rootFile_ = 0;
59 }
60 
61 void LauFitNtuple::storeCorrMatrix( UInt_t iExpt, Double_t NLL, Int_t fitStatus, const TMatrixD& covMatrix )
62 {
63  // store the minimised NLL value, correlation matrix status and experiment number
64  iExpt_ = iExpt;
65  NLL_ = NLL;
66  fitStatus_ = fitStatus;
67 
68  // make the correlation matrix the correct dimensions
69  if (definedFitTree_ == kFALSE) {
70  corrMatrix_.clear();
71  corrMatrix_.resize(nFitPars_);
72  for (UInt_t i = 0; i < nFitPars_; ++i) {corrMatrix_[i].resize(nFitPars_);}
73  }
74 
75  // under certain circumstances, e.g. if the fit has failed in the first
76  // stage of a two-stage fit, the covariance matrix might not have the
77  // expected dimensions, or it might even be empty
78  Bool_t needsPadding = kFALSE;
79  const UInt_t nElements = covMatrix.GetNoElements();
80  if ( nElements == 0 ) {
81 
82  // if it's empty we can just make a diagonal matrix
83  std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received empty covariance matrix - will store diagonal correlation matrix" << std::endl;
84  for (UInt_t i = 0; i < nFitPars_; ++i) {
85  for (UInt_t j = 0; j < nFitPars_; ++j) {
86  if (i == j) {
87  corrMatrix_[i][j] = 1.0;
88  } else {
89  corrMatrix_[i][j] = 0.0;
90  }
91  }
92  }
93  return;
94 
95  } else if ( nElements != nFreePars_*nFreePars_ ) {
96 
97  UInt_t dimension = covMatrix.GetNrows();
98  UInt_t nSecondStage = 0;
99  for (UInt_t i = 0; i < nFitPars_; ++i) {
100  if ( fitVars_[i]->secondStage() ) {
101  ++nSecondStage;
102  }
103  }
104 
105  if ( (dimension + nSecondStage) == nFreePars_ ) {
106  needsPadding = kTRUE;
107  std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received smaller covariance matrix than expected, likely due to failure of first stage fit - will pad the correlation matrix" << std::endl;
108  std::cerr << " : nFitPars_ = " << nFitPars_ << std::endl;
109  std::cerr << " : nFreePars_ = " << nFreePars_ << std::endl;
110  std::cerr << " : nSecondStage = " << nSecondStage << std::endl;
111  std::cerr << " : covMatrix size = " << dimension << std::endl;
112  } else {
113  std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received smaller covariance matrix than expected, for unknown reasons - will store diagonal correlation matrix" << std::endl;
114  std::cerr << " : nFitPars_ = " << nFitPars_ << std::endl;
115  std::cerr << " : nFreePars_ = " << nFreePars_ << std::endl;
116  std::cerr << " : nSecondStage = " << nSecondStage << std::endl;
117  std::cerr << " : covMatrix size = " << dimension << std::endl;
118  for (UInt_t i = 0; i < nFitPars_; ++i) {
119  for (UInt_t j = 0; j < nFitPars_; ++j) {
120  if (i == j) {
121  corrMatrix_[i][j] = 1.0;
122  } else {
123  corrMatrix_[i][j] = 0.0;
124  }
125  }
126  }
127  return;
128  }
129 
130  }
131 
132  // calculate the correlation matrix information from the fitter covariance matrix
133  Bool_t iFixed(kFALSE);
134  Bool_t jFixed(kFALSE);
135  Bool_t iSecondStage(kFALSE);
136  Bool_t jSecondStage(kFALSE);
137  UInt_t iFree(0);
138  UInt_t jFree(0);
139 
140  for (UInt_t i = 0; i < nFitPars_; ++i) {
141 
142  iFixed = fitVars_[i]->fixed();
143  iSecondStage = fitVars_[i]->secondStage();
144 
145  // reset the "j" free parameter counter
146  jFree = 0;
147 
148  // NB the supplied covariance matrix is of dimension nFreePars_ x nFreePars_
149  for (UInt_t j = 0; j < nFitPars_; ++j) {
150 
151  jFixed = fitVars_[j]->fixed();
152  jSecondStage = fitVars_[j]->secondStage();
153 
154  if (i == j) {
155  corrMatrix_[i][j] = 1.0;
156  } else if (iFixed == kTRUE || jFixed == kTRUE) {
157  corrMatrix_[i][j] = 0.0;
158  } else if ( needsPadding && ( iSecondStage || jSecondStage ) ) {
159  corrMatrix_[i][j] = 0.0;
160  } else {
161  Double_t r_ij = covMatrix(iFree,jFree);
162  Double_t r_ii = covMatrix(iFree,iFree);
163  Double_t r_jj = covMatrix(jFree,jFree);
164  Double_t denom = r_ii * r_jj;
165  if (denom < 0.0) {
166  r_ij = 0.0;
167  denom = 1.0;
168  }
169  denom = TMath::Sqrt(denom);
170  if (denom < 1e-30) {
171  r_ij = 0.0;
172  denom = 1.0;
173  }
174  corrMatrix_[i][j] = r_ij / denom;
175  }
176 
177  if ( !jFixed && !(needsPadding && jSecondStage) ) {
178  ++jFree;
179  }
180  }
181 
182  if ( !iFixed && !(needsPadding && iSecondStage) ) {
183  ++iFree;
184  }
185  }
186 }
187 
188 void LauFitNtuple::storeParsAndErrors(const std::vector<LauParameter*>& fitVars, const std::vector<LauParameter>& extraVars)
189 {
190  fitVars_ = fitVars;
191  UInt_t nFitPars = fitVars_.size();
192 
193  // the number of parameters being given to us should be the same as the number from the last fit
194  // OR it's the first time so the "last" number is zero
195  if (nFitPars_ != 0 && nFitPars_ != nFitPars) {
196  std::cerr << "ERROR in LauFitNtuple::storeParsAndErrors : expected total number of parameters (" << nFitPars_
197  << ") not the same as the number provided (" << nFitPars << ")." << std::endl;
198  gSystem->Exit(EXIT_FAILURE);
199  }
200 
201  LauParamFixed pred;
202  UInt_t nFreePars = nFitPars - std::count_if(fitVars_.begin(),fitVars_.end(),pred);
203 
204  // the number of free parameters being given to us should be the same as the number from the last fit
205  // OR it's the first time so the "last" number is zero
206  // (NB we check whether nFitPars_ is zero for this since it is possible to have zero free parameters, albeit rather daft)
207  if (nFitPars_ != 0 && nFreePars_ != nFreePars) {
208  std::cerr << "ERROR in LauFitNtuple::storeParsAndErrors : expected number of free parameters (" << nFreePars_
209  << ") not the same as the number provided (" << nFreePars << ")." << std::endl;
210  gSystem->Exit(EXIT_FAILURE);
211  }
212 
213  nFitPars_ = nFitPars;
214  nFreePars_ = nFreePars;
215 
216  extraVars_ = extraVars;
217  nExtraPars_ = extraVars_.size();
218 }
219 
221 {
222  // Now create and fill the stored fit results into an ntuple (TTree)
223  if (definedFitTree_ == kFALSE) {
224 
225  std::cout << "INFO in LauFitNtuple::updateFitNtuple : totNoPars = " << nFitPars_ << std::endl;
226 
227  // Add experiment number as a branch
228  fitResults_->Branch("iExpt", &iExpt_, "iExpt/I");
229  fitResults_->Branch("fitStatus", &fitStatus_, "fitStatus/I");
230 
231  // Add NLL (negative log-likelihood) value from fit
232  fitResults_->Branch("NLL", &NLL_, "NLL/D");
233 
234  for (UInt_t i = 0; i < nFitPars_; i++) {
235 
236  TString parName = fitVars_[i]->name();
237  TString parNameD(parName); parNameD += "/D";
238  fitResults_->Branch(parName.Data(), &fitVars_[i]->value_, parNameD.Data());
239 
240  TString parInitName(parName); parInitName += "_True";
241  TString parInitNameD(parInitName); parInitNameD += "/D";
242  fitResults_->Branch(parInitName.Data(), &fitVars_[i]->genValue_, parInitNameD.Data());
243 
244  if (!fitVars_[i]->fixed()) {
245  TString parErrName(parName); parErrName += "_Error";
246  TString parErrNameD(parErrName); parErrNameD += "/D";
247  fitResults_->Branch(parErrName.Data(), &fitVars_[i]->error_, parErrNameD.Data());
248 
249  if ( storeAsymErrors_ ) {
250  TString parNegErrName(parName); parNegErrName += "_NegError";
251  TString parNegErrNameD(parNegErrName); parNegErrNameD += "/D";
252  fitResults_->Branch(parNegErrName.Data(), &fitVars_[i]->negError_, parNegErrNameD.Data());
253 
254  TString parPosErrName(parName); parPosErrName += "_PosError";
255  TString parPosErrNameD(parPosErrName); parPosErrNameD += "/D";
256  fitResults_->Branch(parPosErrName.Data(), &fitVars_[i]->posError_, parPosErrNameD.Data());
257  }
258 
259  TString parPullName(parName); parPullName += "_Pull";
260  TString parPullNameD(parPullName); parPullNameD += "/D";
261  fitResults_->Branch(parPullName.Data(), &fitVars_[i]->pull_, parPullNameD.Data());
262  }
263 
264  // Now add in the correlation matrix values (only for floating parameters)
265  if (!fitVars_[i]->fixed()) {
266  // First the global correlation coeffs
267  TString parGCCName(parName); parGCCName += "_GCC";
268  TString parGCCNameD(parGCCName); parGCCNameD += "/D";
269  fitResults_->Branch(parGCCName.Data(), &fitVars_[i]->gcc_, parGCCNameD.Data());
270 
271  if ( ! corrMatrix_.empty() ) {
272  // Then the rest
273  for (UInt_t j = 0; j < nFitPars_; j++) {
274  if (!fitVars_[j]->fixed() && i!=j) {
275  TString parName2 = fitVars_[j]->name();
276  TString corrName("corr__");
277  corrName += parName; corrName += "__"; corrName += parName2;
278 
279  TString corrNameD(corrName); corrNameD += "/D";
280  fitResults_->Branch(corrName.Data(), &corrMatrix_[i][j], corrNameD.Data());
281  }
282  }
283  }
284  }
285  }
286 
287  // Update extra parameter values...
288  for (UInt_t i = 0; i < nExtraPars_; i++) {
289 
290  TString parName = extraVars_[i].name();
291  TString parNameD(parName); parNameD += "/D";
292  fitResults_->Branch(parName.Data(), &extraVars_[i].value_, parNameD.Data());
293 
294  TString parInitName(parName); parInitName += "_True";
295  TString parInitNameD(parInitName); parInitNameD += "/D";
296  fitResults_->Branch(parInitName.Data(), &extraVars_[i].genValue_, parInitNameD.Data());
297 
298  //TString parErrName(parName); parErrName += "_Error";
299  //TString parErrNameD(parErrName); parErrNameD += "/D";
300  //fitResults_->Branch(parErrName.Data(), &extraVars_[i].error_, parErrNameD.Data());
301 
302  // Also find the fit fraction pull and store it
303  //TString pullName(parName); pullName += "_Pull";
304  //TString pullNameD(pullName); pullNameD += "/D";
305  //fitResults_->Branch(pullName.Data(), &extraVars_[i].pull_, pullNameD.Data());
306 
307  }
308 
309  definedFitTree_ = kTRUE;
310 
311  }
312 
313  std::cout << "NLL = " << NLL_ << std::endl;
314 
315  fitResults_->Fill();
316 }
317 
319 {
320  // Write out the fit ntuple to the appropriate root file
321  rootFile_->cd();
322  fitResults_->Write("",TObject::kOverwrite);
323  rootFile_->Close();
324  delete rootFile_; rootFile_ = 0;
325 }
326 
Bool_t definedFitTree_
Flags whether the fit tree has been defined.
std::vector< LauParameter * > fitVars_
Fit variables.
Definition: LauFitNtuple.hh:92
Bool_t fixed() const
Check whether the parameter is fixed or floated.
File containing declaration of LauParamFixed class.
Int_t iExpt_
Experiment number.
ClassImp(LauAbsCoeffSet)
UInt_t nExtraPars_
Number of extra parameters.
File containing declaration of LauAbsFitter class.
std::vector< std::vector< Double_t > > corrMatrix_
Correlation matrix.
Definition: LauFitNtuple.hh:97
std::vector< LauParameter > extraVars_
Extra variables.
Definition: LauFitNtuple.hh:94
void updateFitNtuple()
Update the fit ntuple.
TFile * rootFile_
Root file.
Definition: LauFitNtuple.hh:87
File containing declaration of LauFitter class.
UInt_t nFitPars_
Number of fit parameters.
void writeOutFitResults()
Write out fit results.
File containing declaration of LauParameter class.
Predicate to allow counting of the number of fixed parameters.
Bool_t secondStage() const
Check whether the parameter should be floated only in the second stage of a two stage fit...
void storeCorrMatrix(UInt_t iExpt, Double_t NLL, Int_t fitStatus, const TMatrixD &covMatrix)
Store the correlation matrix and other fit information.
Definition: LauFitNtuple.cc:61
Double_t NLL_
Minimised negative log likelihood.
virtual ~LauFitNtuple()
Destructor.
Definition: LauFitNtuple.cc:53
void storeParsAndErrors(const std::vector< LauParameter * > &fitVars, const std::vector< LauParameter > &extraVars)
Store parameters and their errors.
TTree * fitResults_
Fit results.
Definition: LauFitNtuple.hh:89
Class to store the results from the fit into an ntuple.
Definition: LauFitNtuple.hh:42
Int_t fitStatus_
Status of fit.
UInt_t nFreePars_
Number of free parameters.
File containing declaration of LauFitNtuple class.
Bool_t storeAsymErrors_
Flags whether or not to store the asymmetric error information.