laura is hosted by Hepforge, IPPP Durham
Laura++  3.6.0
A maximum likelihood fitting package for performing Dalitz-plot analysis.
LauFitDataTree.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 "LauFitDataTree.hh"
30 
31 #include "TFile.h"
32 #include "TLeaf.h"
33 #include "TString.h"
34 #include "TSystem.h"
35 
36 #include <cmath>
37 #include <cstdlib>
38 #include <iostream>
39 
40 LauFitDataTree::LauFitDataTree( const TString& rootFileName, const TString& rootTreeName ) :
41  rootFileName_( rootFileName ),
42  rootTreeName_( rootTreeName ),
43  rootFile_( 0 ),
44  rootTree_( 0 ),
45  eventList_( 0 )
46 {
47  if ( rootFileName_ != "" && rootTreeName_ != "" ) {
48  this->openFileAndTree();
49  }
50 }
51 
53 {
54  if ( rootFile_ && rootFile_->IsOpen() ) {
55  delete rootTree_;
56  rootTree_ = 0;
57  delete eventList_;
58  eventList_ = 0;
59  }
60  delete rootFile_;
61  rootFile_ = 0;
62 }
63 
65 {
66  // first check whether we've already opened up the file or not
67  if ( ! rootFile_ ) {
68  // if not, first check the filename and if all ok create the file
69  if ( rootFileName_ == "" ) {
70  std::cerr << "ERROR in LauFitDataTree::openFileAndTree : Bad filename supplied, not creating file or tree."
71  << std::endl;
72  return;
73  }
74  rootFile_ = TFile::Open( rootFileName_, "read" );
75  if ( ! rootFile_ || rootFile_->IsZombie() || ! rootFile_->IsOpen() ) {
76  std::cerr << "ERROR in LauFitDataTree::openFileAndTree : Problem opening file \""
77  << rootFileName_ << "\" for reading." << std::endl;
78  return;
79  }
80  }
81  // check whether we've already created the tree
82  if ( ! rootTree_ ) {
83  // if not change to the file's directory and grab the tree
84  rootFile_->cd();
85  rootTree_ = dynamic_cast<TTree*>( rootFile_->Get( rootTreeName_ ) );
86  if ( ! rootTree_ ) {
87  std::cerr << "ERROR in LauFitDataTree::openFileAndTree : Problem reading tree \""
88  << rootTreeName_ << "\" from file." << std::endl;
89  return;
90  }
91  rootTree_->SetDirectory( rootFile_ );
92  }
93 }
94 
96 {
97  if ( ! rootTree_ ) {
98  std::cerr << "ERROR in LauFitDataTree::findBranches : Invalid pointer to data tree."
99  << std::endl;
100  return kFALSE;
101  }
102 
103  // this method should only be called once
104  if ( ! leafNames_.empty() ) {
105  std::cerr << "ERROR in LauFitDataTree::findBranches : Branches already found, not running again."
106  << std::endl;
107  return kFALSE;
108  }
109 
110  leafNames_.clear();
111  eventData_.clear();
112  eventDataOut_.clear();
113  leaves_.clear();
114  treeEvents_.clear();
115  fakeEvents_.clear();
116 
117  const UInt_t numBranches( this->nBranches() );
118  eventData_.reserve( numBranches );
119 
120  TObjArray* pLeaves = rootTree_->GetListOfLeaves();
121  if ( ! pLeaves ) {
122  std::cerr << "ERROR in LauFitDataTree::findBranches : Problem retrieving leaves from the tree."
123  << std::endl;
124  return kFALSE;
125  }
126  TObjArray& leaves = *pLeaves;
127 
128  const UInt_t numLeaves = static_cast<UInt_t>( leaves.GetEntries() );
129  if ( numBranches != numLeaves ) {
130  std::cerr << "ERROR in LauFitDataTree::findBranches : List of leaves is not the same size as the number of branches - this is strange!"
131  << std::endl;
132  std::cerr << " : There are " << numLeaves
133  << " leaves and " << numBranches << " branches" << std::endl;
134  return kFALSE;
135  }
136 
137  for ( UInt_t iLeaf = 0; iLeaf < numBranches; ++iLeaf ) {
138 
139  TLeaf* leaf = dynamic_cast<TLeaf*>( leaves[iLeaf] );
140 
141  // we can't deal with arrays
142  Int_t size = leaf->GetNdata();
143  if ( size != 1 ) {
144  std::cerr << "ERROR in LauFitDataTree::findBranches : Tree has array branches, can't deal with those."
145  << std::endl;
146  return kFALSE;
147  }
148 
149  // find the name and type of the leaf
150  TString name = leaf->GetName();
151 
152  // initialise an entry in the maps to hold the value
153  leafNames_[name] = iLeaf;
154  leaves_.push_back( leaf );
155  eventData_.push_back( 0.0 );
156  eventDataOut_[name] = 0.0;
157  }
158 
159  const UInt_t numEvents( this->nTotalEvents() );
160 
161  std::cout << "INFO in LauFitDataTree::findBranches : Finished finding data tree branches."
162  << std::endl;
163  std::cout << " : Tree contains " << numBranches
164  << " branches and a total of " << numEvents << " events." << std::endl;
165 
166  return kTRUE;
167 }
168 
170 {
171  // Check that we have a valid tree to read from
172  if ( ! rootTree_ ) {
173  std::cerr << "ERROR in LauFitDataTree::readExperimentData : Invalid pointer to data tree."
174  << std::endl;
175  return;
176  }
177 
178  rootFile_->cd();
179 
180  // If the event list doesn't exist, create it
181  if ( ! eventList_ ) {
182  eventList_ = new TEventList( "elist", "elist" );
183  eventList_->SetDirectory( rootFile_ );
184  }
185 
186  // Reset the event list so it contains no entries
187  eventList_->Reset();
188 
189  // Check that the tree contains the iExpt branch
190  if ( ! this->haveBranch( "iExpt" ) ) {
191  // If it doesn't, check which experiment we've been asked to read
192  if ( iExpt == 0 ) {
193  // If it's experiment 0, assume that we should read all events in the tree (but print a warning since this is an assumption)
194  std::cerr << "WARNING in LauFitDataTree::readExperimentData : Tree does not contain \"iExpt\" branch, will read all data in the tree"
195  << std::endl;
196  this->readAllData();
197  return;
198  } else {
199  // Otherwise we can't really do anything, so print an error and return
200  std::cerr << "ERROR in LauFitDataTree::readExperimentData : Tree does not contain \"iExpt\" branch and experiment requested is > 0, will not read anything"
201  << std::endl;
202  return;
203  }
204  }
205 
206  // Fill the event list with the entries for the requested experiment
207  TString listName( eventList_->GetName() );
208  listName.Prepend( ">>" );
209  TString selection( "iExpt==" );
210  selection += iExpt;
211 
212  std::cout << "INFO in LauFitDataTree::readExperimentData : Setting tree to experiment number "
213  << iExpt << "." << std::endl;
214  rootTree_->Draw( listName, selection );
215  std::cout << " : Found " << this->nEvents()
216  << " events." << std::endl;
217 
218  // Load the data
219  this->loadData();
220 }
221 
223 {
224  if ( rootTree_ ) {
225  return static_cast<UInt_t>( rootTree_->GetNbranches() );
226  } else if ( ! fakeEvents_.empty() ) {
227  std::vector<LauEventData>::const_iterator fakeIter = fakeEvents_.begin();
228  return ( *fakeIter ).size();
229  } else {
230  return 0;
231  }
232 }
233 
234 void LauFitDataTree::appendFakePoints( const std::vector<Double_t>& xCoords,
235  const std::vector<Double_t>& yCoords )
236 {
237  if ( xCoords.size() != yCoords.size() ) {
238  std::cerr << "ERROR in LauFitDataTree::appendFakePoints : The co-ordinate vectors are not the same size!"
239  << std::endl;
240  gSystem->Exit( EXIT_FAILURE );
241  }
242 
243  // clear the list of fake events and reserve enough space
244  fakeEvents_.clear();
245  fakeEvents_.reserve( xCoords.size() );
246 
247  // loop over the event data zeroing everything
248  for ( LauEventData::iterator iter = eventData_.begin(); iter != eventData_.end(); ++iter ) {
249  *iter = 0.0;
250  }
251 
252  // find the vector indices for the DP co-ordinates
253  LauNameIndexMap::const_iterator iter = leafNames_.find( "m13Sq" );
254  if ( iter == leafNames_.end() ) {
255  std::cerr << "ERROR in LauFitDataTree::appendFakePoints : Can't find entry \"m13Sq\" in event data map."
256  << std::endl;
257  gSystem->Exit( EXIT_FAILURE );
258  }
259  UInt_t m13SqIdx = iter->second;
260 
261  iter = leafNames_.find( "m23Sq" );
262  if ( iter == leafNames_.end() ) {
263  std::cerr << "ERROR in LauFitDataTree::appendFakePoints : Can't find entry \"m23Sq\" in event data map."
264  << std::endl;
265  gSystem->Exit( EXIT_FAILURE );
266  }
267  UInt_t m23SqIdx = iter->second;
268 
269  // TODO - is this really needed? Comment out for now.
270  /*
271  // and a fake tagCat which we don't care about, but the program
272  // needs a number here for comptibility with conventional events.
273  iter = leafNames_.find( "tagCat" );
274  if ( iter == leafNames_.end() ) {
275  std::cerr << "ERROR in LauFitDataTree::appendFakePoints : Can't find entry \"tagCat\" in event data map." << std::endl;
276  gSystem->Exit(EXIT_FAILURE);
277  }
278  UInt_t tagCatIdx = iter->second;
279  */
280 
281  for ( UInt_t iEvt = 0; iEvt < xCoords.size(); ++iEvt ) {
282 
283  // set the values
284  eventData_[m13SqIdx] = xCoords[iEvt];
285  eventData_[m23SqIdx] = yCoords[iEvt];
286  //eventData_[ tagCatIdx ] = 0.0;
287 
288  // append to the list of fake events
289  fakeEvents_.push_back( eventData_ );
290  }
291 }
292 
293 Bool_t LauFitDataTree::haveBranch( const TString& name ) const
294 {
295  LauNameIndexMap::const_iterator iter = leafNames_.find( name );
296  return ( iter != leafNames_.end() );
297 }
298 
300 {
301  rootTree_->SetBranchStatus( "*", 0 );
302 }
303 
305 {
306  rootTree_->SetBranchStatus( "*", 1 );
307 }
308 
309 void LauFitDataTree::enableBranch( const TString& name ) const
310 {
311  if ( this->haveBranch( name ) ) {
312  rootTree_->SetBranchStatus( name, 1 );
313  }
314 }
315 
316 void LauFitDataTree::disableBranch( const TString& name ) const
317 {
318  if ( this->haveBranch( name ) ) {
319  rootTree_->SetBranchStatus( name, 0 );
320  }
321 }
322 
324 {
325  // Clear any data from previous expts
326  treeEvents_.clear();
327 
328  // Reserve enough space in the vector
329  Long64_t nEvts = this->nEvents();
330  treeEvents_.reserve( nEvts );
331 
332  const UInt_t nLeaves = this->nBranches();
333 
334  // Loop through the tree and store the data
335  for ( Long64_t iEvt( 0 ); iEvt < nEvts; ++iEvt ) {
336 
337  // Find which entry from the full tree contains the requested event
338  Long64_t iEntry = eventList_ ? eventList_->GetEntry( iEvt ) : iEvt;
339  if ( iEntry < 0 ) { // this shouldn't happen, but just in case...
340  std::cerr << "ERROR in LauFitDataTree::loadData : Requested event not found."
341  << std::endl;
342  gSystem->Exit( EXIT_FAILURE );
343  }
344 
345  // Then retrieve that entry from the tree
346  rootTree_->GetEntry( iEntry );
347 
348  // Copy the leaf values into eventData_
349  for ( UInt_t iLeaf( 0 ); iLeaf < nLeaves; ++iLeaf ) {
350 
351  const TLeaf* leaf = leaves_[iLeaf];
352 
353  Double_t value = leaf->GetValue();
354  if ( std::isnan( value ) || std::isinf( value ) ) {
355  std::cerr << "ERROR in LauFitDataTree::loadData : Event " << iEvt
356  << " has infinite or NaN entry for variable " << leaf->GetName()
357  << std::endl;
358  gSystem->Exit( EXIT_FAILURE );
359  }
360 
361  eventData_[iLeaf] = value;
362  }
363 
364  // Store the event in the vector
365  treeEvents_.push_back( eventData_ );
366  }
367 }
368 
370 {
371  delete eventList_;
372  eventList_ = 0;
373  this->loadData();
374 }
375 
376 const LauFitData& LauFitDataTree::getData( UInt_t iEvt ) const
377 {
378  // For a given event, within the current experiment,
379  // retrieve the input fit variables
380 
381  const UInt_t numTreeEvents = this->nEvents();
382  const UInt_t numFakeEvents = this->nFakeEvents();
383 
384  // Does the requested event come from the tree or from the fake events list?
385  if ( iEvt < numTreeEvents ) {
386  if ( iEvt > treeEvents_.size() ) { // this shouldn't happen, but just in case...
387  std::cerr << "ERROR in LauFitDataTree::getData : Requested event, " << iEvt
388  << ", not found." << std::endl;
389  gSystem->Exit( EXIT_FAILURE );
390  }
391  // Retrieve that event from the vector
392  eventData_ = treeEvents_[iEvt];
393  } else if ( iEvt < ( numTreeEvents + numFakeEvents ) ) {
394  // Find the entry from the fake events list contains the requested event
395  UInt_t iEntry = iEvt - numTreeEvents;
396  // Copy the entry into eventData_
397  eventData_ = fakeEvents_[iEntry];
398  } else {
399  std::cerr << "ERROR in LauFitDataTree::getData : Requested event " << iEvt
400  << " not found for " << rootTreeName_ << std::endl;
401  gSystem->Exit( EXIT_FAILURE );
402  }
403 
404  for ( LauNameIndexMap::const_iterator iter = leafNames_.begin(); iter != leafNames_.end();
405  ++iter ) {
406  const TString& name = iter->first;
407  UInt_t index = iter->second;
408 
409  LauFitData::iterator outIter = eventDataOut_.find( name );
410  if ( outIter == eventDataOut_.end() ) {
411  std::cerr << "ERROR in LauFitDataTree::getData : Something very strange happening."
412  << std::endl;
413  gSystem->Exit( EXIT_FAILURE );
414  }
415 
416  outIter->second = eventData_[index];
417  }
418  return eventDataOut_;
419 }
LauFitDataTree(const TString &rootFileName, const TString &rootTreeName)
Constructor.
TString rootTreeName_
The name of the tree ocntaining the data.
void readExperimentData(UInt_t iExpt)
Read events only for the given experiment.
Double_t value() const
The value of the parameter.
UInt_t nBranches() const
Obtain the number of branches in the tree.
const LauFitData & getData(UInt_t iEvt) const
Retrieve the data for a given event.
LauLeafList leaves_
The leaf objects.
void appendFakePoints(const std::vector< Double_t > &xCoords, const std::vector< Double_t > &yCoords)
Add fake events to the data.
Bool_t findBranches()
Find all of the branches in the tree.
LauEventData eventData_
Stores the current event.
File containing declaration of LauFitDataTree class.
void disableBranch(const TString &name) const
Disable the named branch.
void enableBranch(const TString &name) const
Enable the named branch.
Bool_t haveBranch(const TString &name) const
Check if the named branch is stored.
TString rootFileName_
The name of the file containing the data.
UInt_t nFakeEvents() const
Retrieve the number of fake events.
void readAllData()
Read all events from the tree.
LauFitData eventDataOut_
Stores the current event (for external use)
void loadData()
Load events from the tree.
TEventList * eventList_
A list of the events in the current experiment.
void enableAllBranches() const
Enable all branches.
void openFileAndTree()
Open the file and tree.
const TString & name() const
The parameter name.
UInt_t nTotalEvents() const
Retrieve the total number of events.
void disableAllBranches() const
Disable all branches.
std::vector< LauEventData > fakeEvents_
The fake events, which are not from the tree.
std::map< TString, Double_t > LauFitData
Type for holding event data.
LauNameIndexMap leafNames_
Stores the mapping from the leaf names to the vector indices.
std::vector< LauEventData > treeEvents_
The events read from the tree.
TTree * rootTree_
The tree containing the data.
TFile * rootFile_
The file containing the data.
virtual ~LauFitDataTree()
Destructor.
UInt_t nEvents() const
Retrieve the number of events.