laura is hosted by Hepforge, IPPP Durham
Laura++  3.6.0
A maximum likelihood fitting package for performing Dalitz-plot analysis.
LauFitNtuple.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 "LauFitNtuple.hh"
30 
31 #include "LauAbsFitter.hh"
32 #include "LauFitter.hh"
33 #include "LauParamFixed.hh"
34 #include "LauParameter.hh"
35 
36 #include "TFile.h"
37 #include "TMath.h"
38 #include "TMatrixD.h"
39 #include "TSystem.h"
40 #include "TTree.h"
41 
42 #include <iostream>
43 
44 LauFitNtuple::LauFitNtuple( const TString& fileName, Bool_t storeAsymErrors ) :
45  rootFileName_( fileName ),
46  rootFile_( 0 ),
47  fitResults_( 0 ),
48  definedFitTree_( kFALSE ),
49  storeAsymErrors_( storeAsymErrors ),
50  fitStatus_( { -1, 0.0, 0.0 } ),
51  nFitPars_( 0 ),
52  nFreePars_( 0 ),
53  nExtraPars_( 0 ),
54  iExpt_( 0 )
55 {
56  rootFile_ = TFile::Open( rootFileName_, "recreate" );
57  rootFile_->cd();
58  fitResults_ = new TTree( "fitResults", "fitResults" );
59  fitResults_->SetDirectory( rootFile_ );
60 
61  fitVars_.clear();
62  constrainedVars_.clear();
63  extraVars_.clear();
64 }
65 
67 {
68  if ( rootFile_ && rootFile_->IsOpen() ) {
69  delete fitResults_;
70  fitResults_ = 0;
71  }
72  delete rootFile_;
73  rootFile_ = 0;
74 }
75 
76 void LauFitNtuple::storeCorrMatrix( const UInt_t iExpt,
77  const LauAbsFitter::FitStatus& fitStatus,
78  const TMatrixD& covMatrix )
79 {
80  // store the minimised NLL value, correlation matrix status and experiment number
81  iExpt_ = iExpt;
82  fitStatus_ = fitStatus;
83 
84  // make the correlation matrix the correct dimensions
85  if ( definedFitTree_ == kFALSE ) {
86  corrMatrix_.clear();
87  corrMatrix_.resize( nFitPars_ );
88  for ( UInt_t i = 0; i < nFitPars_; ++i ) {
89  corrMatrix_[i].resize( nFitPars_ );
90  }
91  }
92 
93  // under certain circumstances, e.g. if the fit has failed in the first
94  // stage of a two-stage fit, the covariance matrix might not have the
95  // expected dimensions, or it might even be empty
96  Bool_t needsPadding = kFALSE;
97  const UInt_t nElements = covMatrix.GetNoElements();
98  if ( nElements == 0 ) {
99 
100  // if it's empty we can just make a diagonal matrix
101  std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received empty covariance matrix - will store diagonal correlation matrix"
102  << std::endl;
103  for ( UInt_t i = 0; i < nFitPars_; ++i ) {
104  for ( UInt_t j = 0; j < nFitPars_; ++j ) {
105  if ( i == j ) {
106  corrMatrix_[i][j] = 1.0;
107  } else {
108  corrMatrix_[i][j] = 0.0;
109  }
110  }
111  }
112  return;
113 
114  } else if ( nElements != nFreePars_ * nFreePars_ ) {
115 
116  UInt_t dimension = covMatrix.GetNrows();
117  UInt_t nSecondStage = 0;
118  for ( UInt_t i = 0; i < nFitPars_; ++i ) {
119  if ( fitVars_[i]->secondStage() ) {
120  ++nSecondStage;
121  }
122  }
123 
124  if ( ( dimension + nSecondStage ) == nFreePars_ ) {
125  needsPadding = kTRUE;
126  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"
127  << std::endl;
128  std::cerr << " : nFitPars_ = " << nFitPars_
129  << std::endl;
130  std::cerr << " : nFreePars_ = " << nFreePars_
131  << std::endl;
132  std::cerr << " : nSecondStage = "
133  << nSecondStage << std::endl;
134  std::cerr << " : covMatrix size = " << dimension
135  << std::endl;
136  } else {
137  std::cerr << "WARNING in LauFitNtuple::storeCorrMatrix : received smaller covariance matrix than expected, for unknown reasons - will store diagonal correlation matrix"
138  << std::endl;
139  std::cerr << " : nFitPars_ = " << nFitPars_
140  << std::endl;
141  std::cerr << " : nFreePars_ = " << nFreePars_
142  << std::endl;
143  std::cerr << " : nSecondStage = "
144  << nSecondStage << std::endl;
145  std::cerr << " : covMatrix size = " << dimension
146  << std::endl;
147  for ( UInt_t i = 0; i < nFitPars_; ++i ) {
148  for ( UInt_t j = 0; j < nFitPars_; ++j ) {
149  if ( i == j ) {
150  corrMatrix_[i][j] = 1.0;
151  } else {
152  corrMatrix_[i][j] = 0.0;
153  }
154  }
155  }
156  return;
157  }
158  }
159 
160  // calculate the correlation matrix information from the fitter covariance matrix
161  Bool_t iFixed( kFALSE );
162  Bool_t jFixed( kFALSE );
163  Bool_t iSecondStage( kFALSE );
164  Bool_t jSecondStage( kFALSE );
165  UInt_t iFree( 0 );
166  UInt_t jFree( 0 );
167 
168  for ( UInt_t i = 0; i < nFitPars_; ++i ) {
169 
170  iFixed = fitVars_[i]->fixed();
171  iSecondStage = fitVars_[i]->secondStage();
172 
173  // reset the "j" free parameter counter
174  jFree = 0;
175 
176  // NB the supplied covariance matrix is of dimension nFreePars_ x nFreePars_
177  for ( UInt_t j = 0; j < nFitPars_; ++j ) {
178 
179  jFixed = fitVars_[j]->fixed();
180  jSecondStage = fitVars_[j]->secondStage();
181 
182  if ( i == j ) {
183  corrMatrix_[i][j] = 1.0;
184  } else if ( iFixed == kTRUE || jFixed == kTRUE ) {
185  corrMatrix_[i][j] = 0.0;
186  } else if ( needsPadding && ( iSecondStage || jSecondStage ) ) {
187  corrMatrix_[i][j] = 0.0;
188  } else {
189  Double_t r_ij = covMatrix( iFree, jFree );
190  Double_t r_ii = covMatrix( iFree, iFree );
191  Double_t r_jj = covMatrix( jFree, jFree );
192  Double_t denom = r_ii * r_jj;
193  if ( denom < 0.0 ) {
194  r_ij = 0.0;
195  denom = 1.0;
196  }
197  denom = TMath::Sqrt( denom );
198  if ( denom < 1e-30 ) {
199  r_ij = 0.0;
200  denom = 1.0;
201  }
202  corrMatrix_[i][j] = r_ij / denom;
203  }
204 
205  if ( ! jFixed && ! ( needsPadding && jSecondStage ) ) {
206  ++jFree;
207  }
208  }
209 
210  if ( ! iFixed && ! ( needsPadding && iSecondStage ) ) {
211  ++iFree;
212  }
213  }
214 }
215 
216 void LauFitNtuple::storeParsAndErrors( const std::vector<LauParameter*>& fitVars,
217  const std::set<TString>& constrainedVars,
218  const std::vector<LauParameter>& extraVars )
219 {
220  fitVars_ = fitVars;
221  UInt_t nFitPars = fitVars_.size();
222 
223  // the number of parameters being given to us should be the same as the number from the last fit
224  // OR it's the first time so the "last" number is zero
225  if ( nFitPars_ != 0 && nFitPars_ != nFitPars ) {
226  std::cerr << "ERROR in LauFitNtuple::storeParsAndErrors : expected total number of parameters ("
227  << nFitPars_ << ") not the same as the number provided (" << nFitPars << ")."
228  << std::endl;
229  gSystem->Exit( EXIT_FAILURE );
230  }
231 
232  LauParamFixed pred;
233  UInt_t nFreePars = nFitPars - std::count_if( fitVars_.begin(), fitVars_.end(), pred );
234 
235  // the number of free parameters being given to us should be the same as the number from the last fit
236  // OR it's the first time so the "last" number is zero
237  // (NB we check whether nFitPars_ is zero for this since it is possible to have zero free parameters, albeit rather daft)
238  if ( nFitPars_ != 0 && nFreePars_ != nFreePars ) {
239  std::cerr << "ERROR in LauFitNtuple::storeParsAndErrors : expected number of free parameters ("
240  << nFreePars_ << ") not the same as the number provided (" << nFreePars << ")."
241  << std::endl;
242  gSystem->Exit( EXIT_FAILURE );
243  }
244 
245  nFitPars_ = nFitPars;
246  nFreePars_ = nFreePars;
247 
248  constrainedVars_ = constrainedVars;
249 
250  extraVars_ = extraVars;
251  nExtraPars_ = extraVars_.size();
252 }
253 
255 {
256  // Now create and fill the stored fit results into an ntuple (TTree)
257  if ( definedFitTree_ == kFALSE ) {
258 
259  std::cout << "INFO in LauFitNtuple::updateFitNtuple : totNoPars = " << nFitPars_ << std::endl;
260 
261  // Add experiment number as a branch
262  fitResults_->Branch( "iExpt", &iExpt_, "iExpt/I" );
263  fitResults_->Branch( "fitStatus", &fitStatus_.status, "fitStatus/I" );
264 
265  // Add NLL (negative log-likelihood) and EDM values from fit
266  fitResults_->Branch( "NLL", &fitStatus_.NLL, "NLL/D" );
267  fitResults_->Branch( "EDM", &fitStatus_.EDM, "EDM/D" );
268 
269  for ( UInt_t i = 0; i < nFitPars_; i++ ) {
270 
271  TString parName = fitVars_[i]->name();
272  TString parNameD( parName );
273  parNameD += "/D";
274  fitResults_->Branch( parName.Data(), &fitVars_[i]->value_, parNameD.Data() );
275 
276  TString parInitName( parName );
277  parInitName += "_True";
278  TString parInitNameD( parInitName );
279  parInitNameD += "/D";
280  fitResults_->Branch( parInitName.Data(), &fitVars_[i]->genValue_, parInitNameD.Data() );
281 
282  if ( ! fitVars_[i]->fixed() ) {
283  TString parErrName( parName );
284  parErrName += "_Error";
285  TString parErrNameD( parErrName );
286  parErrNameD += "/D";
287  fitResults_->Branch( parErrName.Data(), &fitVars_[i]->error_, parErrNameD.Data() );
288 
289  if ( storeAsymErrors_ ) {
290  TString parNegErrName( parName );
291  parNegErrName += "_NegError";
292  TString parNegErrNameD( parNegErrName );
293  parNegErrNameD += "/D";
294  fitResults_->Branch( parNegErrName.Data(),
295  &fitVars_[i]->negError_,
296  parNegErrNameD.Data() );
297 
298  TString parPosErrName( parName );
299  parPosErrName += "_PosError";
300  TString parPosErrNameD( parPosErrName );
301  parPosErrNameD += "/D";
302  fitResults_->Branch( parPosErrName.Data(),
303  &fitVars_[i]->posError_,
304  parPosErrNameD.Data() );
305  }
306 
307  TString parPullName( parName );
308  parPullName += "_Pull";
309  TString parPullNameD( parPullName );
310  parPullNameD += "/D";
311  fitResults_->Branch( parPullName.Data(), &fitVars_[i]->pull_, parPullNameD.Data() );
312 
313  if ( fitVars_[i]->gaussConstraint() ||
314  constrainedVars_.find( parName ) != constrainedVars_.end() ) {
315  TString parConstMeanName( parName );
316  parConstMeanName += "_ConstraintMean";
317  TString parConstMeanNameD( parConstMeanName );
318  parConstMeanNameD += "/D";
319  fitResults_->Branch( parConstMeanName.Data(),
320  &fitVars_[i]->constraintMean_,
321  parConstMeanNameD.Data() );
322  }
323  }
324 
325  // Now add in the correlation matrix values (only for floating parameters)
326  if ( ! fitVars_[i]->fixed() ) {
327  // First the global correlation coeffs
328  TString parGCCName( parName );
329  parGCCName += "_GCC";
330  TString parGCCNameD( parGCCName );
331  parGCCNameD += "/D";
332  fitResults_->Branch( parGCCName.Data(), &fitVars_[i]->gcc_, parGCCNameD.Data() );
333 
334  if ( ! corrMatrix_.empty() ) {
335  // Then the rest
336  for ( UInt_t j = 0; j < nFitPars_; j++ ) {
337  if ( ! fitVars_[j]->fixed() && i != j ) {
338  TString parName2 = fitVars_[j]->name();
339  TString corrName( "corr__" );
340  corrName += parName;
341  corrName += "__";
342  corrName += parName2;
343 
344  TString corrNameD( corrName );
345  corrNameD += "/D";
346  fitResults_->Branch( corrName.Data(),
347  &corrMatrix_[i][j],
348  corrNameD.Data() );
349  }
350  }
351  }
352  }
353  }
354 
355  // Update extra parameter values...
356  for ( UInt_t i = 0; i < nExtraPars_; i++ ) {
357 
358  TString parName = extraVars_[i].name();
359  TString parNameD( parName );
360  parNameD += "/D";
361  fitResults_->Branch( parName.Data(), &extraVars_[i].value_, parNameD.Data() );
362 
363  TString parInitName( parName );
364  parInitName += "_True";
365  TString parInitNameD( parInitName );
366  parInitNameD += "/D";
367  fitResults_->Branch( parInitName.Data(), &extraVars_[i].genValue_, parInitNameD.Data() );
368 
369  //TString parErrName(parName); parErrName += "_Error";
370  //TString parErrNameD(parErrName); parErrNameD += "/D";
371  //fitResults_->Branch(parErrName.Data(), &extraVars_[i].error_, parErrNameD.Data());
372 
373  // Also find the fit fraction pull and store it
374  //TString pullName(parName); pullName += "_Pull";
375  //TString pullNameD(pullName); pullNameD += "/D";
376  //fitResults_->Branch(pullName.Data(), &extraVars_[i].pull_, pullNameD.Data());
377  }
378 
379  definedFitTree_ = kTRUE;
380  }
381 
382  std::cout << "INFO in LauFitNtuple::updateFitNtuple : Stored fit values for experiment "
383  << iExpt_ << "\n";
384  std::cout << " : fitStatus = " << fitStatus_.status
385  << std::endl;
386  std::cout << " : NLL = " << fitStatus_.NLL
387  << std::endl;
388  std::cout << " : EDM = " << fitStatus_.EDM
389  << std::endl;
390 
391  fitResults_->Fill();
392 }
393 
395 {
396  // Write out the fit ntuple to the appropriate root file
397  rootFile_->cd();
398  fitResults_->Write( "", TObject::kOverwrite );
399  rootFile_->Close();
400  delete rootFile_;
401  rootFile_ = 0;
402 }
Bool_t storeAsymErrors_
Flags whether or not to store the asymmetric error information.
UInt_t nExtraPars_
Number of extra parameters.
File containing declaration of LauFitter class.
Struct to store fit status information.
Definition: LauAbsFitter.hh:54
File containing declaration of LauAbsFitter class.
std::vector< LauParameter * > fitVars_
Fit variables.
File containing declaration of LauParamFixed class.
TFile * rootFile_
Root file.
TTree * fitResults_
Fit results.
File containing declaration of LauParameter class.
std::vector< LauParameter > extraVars_
Extra variables.
File containing declaration of LauFitNtuple class.
virtual ~LauFitNtuple()
Destructor.
Definition: LauFitNtuple.cc:66
void storeCorrMatrix(const UInt_t iExpt, const LauAbsFitter::FitStatus &fitStatus, const TMatrixD &covMatrix)
Store the correlation matrix and other fit information.
Definition: LauFitNtuple.cc:76
Bool_t secondStage() const
Check whether the parameter should be floated only in the second stage of a two stage fit.
std::set< TString > constrainedVars_
Fit variables that are included in a multi-dimensional constraint.
UInt_t nFreePars_
Number of free parameters.
Bool_t definedFitTree_
Flags whether the fit tree has been defined.
Int_t iExpt_
Experiment number.
LauAbsFitter::FitStatus fitStatus_
Status of fit.
void writeOutFitResults()
Write out fit results.
Bool_t fixed() const
Check whether the parameter is fixed or floated.
Double_t NLL
The negative log-likelihood.
Definition: LauAbsFitter.hh:58
std::vector< std::vector< Double_t > > corrMatrix_
Correlation matrix.
Predicate to allow counting of the number of fixed parameters.
void storeParsAndErrors(const std::vector< LauParameter * > &fitVars, const std::set< TString > &constrainedVars, const std::vector< LauParameter > &extraVars)
Store parameters and their errors.
Bool_t gaussConstraint() const
Check whether a Gaussian constraints is applied.
LauFitNtuple(const TString &fileName, Bool_t storeAsymErrors)
Constructor.
Definition: LauFitNtuple.cc:44
Double_t EDM
The estimated distance to the minimum.
Definition: LauAbsFitter.hh:60
void updateFitNtuple()
Update the fit ntuple.
Int_t status
The status code of the fit.
Definition: LauAbsFitter.hh:56
UInt_t nFitPars_
Number of fit parameters.