source: trunk/MagicSoft/Mars/mbase/MReadTree.cc@ 1020

Last change on this file since 1020 was 1020, checked in by tbretz, 23 years ago
*** empty log message ***
File size: 13.3 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 12/2000 (tbretz@uni-sw.gwdg.de)
19!
20! Copyright: MAGIC Software Development, 2000-2001
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26// //
27// MReadTree //
28// //
29// This tasks opens all branches in a specified tree and creates the //
30// corresponding parameter containers if not already existing in the //
31// parameter list. //
32// //
33// The Process function reads one events from the tree. To go through the //
34// events of one tree make sure that the event number is increased from //
35// outside. It makes also possible to go back by decreasing the number. //
36// //
37// If you don't want to start reading the first event you have to call //
38// MReadTree::SetEventNum after instantiating your MReadTree-object. //
39// //
40// To make reading much faster (up to a factor of 10 to 20) you can //
41// ensure that only the data you are really processing is enabled by //
42// calling MReadTree::UseLeaf. //
43// //
44// FIXME: An automatic enabeling scheme would be nice. //
45// Can we use TBranch::SetAutoDelete? //
46// //
47// Later we'll use TChain::SetNotify to notify MReadTree if the TChain //
48// starts to read a new file. //
49// //
50/////////////////////////////////////////////////////////////////////////////
51
52#include "MReadTree.h"
53
54#include <fstream.h>
55
56#include <TChain.h>
57#include <TGProgressBar.h>
58#include <TChainElement.h>
59#include <TOrdCollection.h>
60
61#include "MLog.h"
62#include "MLogManip.h"
63
64#include "MTime.h"
65#include "MParList.h"
66#include "MTaskList.h"
67
68ClassImp(MReadTree);
69
70// --------------------------------------------------------------------------
71//
72// Default constructor. It creates an TChain instance which represents the
73// the Tree you want to read and adds the given file (if you gave one).
74// More files can be added using MReadTree::AddFile.
75// Also an empty veto list is created. This list is used if you want to
76// veto (disable or "don't enable") a branch in the tree.
77//
78MReadTree::MReadTree(const char *tname, const char *fname,
79 const char *name, const char *title)
80 : fNumEntry(0), fBranchChoosing(kFALSE), fAutoEnable(kTRUE)
81{
82 fName = name ? name : "MReadTree";
83 fTitle = title ? title : "Task to loop over all events in one single tree";
84
85 fVetoList = new TOrdCollection;
86 fVetoList->SetOwner();
87
88 //
89 // open the input stream
90 //
91 fChain = new TChain(tname);
92
93 if (fname)
94 fChain->Add(fname);
95}
96
97// --------------------------------------------------------------------------
98//
99// Destructor. It deletes the TChain and veto list object
100//
101MReadTree::~MReadTree()
102{
103 //
104 // Delete all the pointers to pointers to the objects where the
105 // branche data gets stored.
106 //
107 TIter Next(fChain->GetStatus());
108
109 TChainElement *element = NULL;
110 while ((element=(TChainElement*)Next()))
111 delete (MParContainer**)element->GetBaddress();
112
113 //
114 // Delete the chain and the veto list
115 //
116 delete fChain;
117 delete fVetoList;
118}
119
120// --------------------------------------------------------------------------
121//
122// If you want to read the given tree over several files you must add
123// the files here before PreProcess is called. Be careful: If the tree
124// doesn't have the same contents (branches) it may confuse your
125// program (trees which are are not existing in later files are not read
126// anymore, tree wich are not existing in the first file are never read)
127//
128// Name may use the wildcarding notation, eg "xxx*.root" means all files
129// starting with xxx in the current file system directory.
130//
131Int_t MReadTree::AddFile(const char *fname)
132{
133 //
134 // FIXME! A check is missing whether the file already exists or not.
135 //
136 //
137 // returns the number of file which were added
138 //
139 return fChain->Add(fname);
140}
141
142void MReadTree::EnableBranchChoosing()
143{
144 if (fBranchChoosing)
145 return;
146
147 *fLog << "Branch choosing method enabled (only enabled branches are read)." << endl;
148 fChain->SetBranchStatus("*", kFALSE);
149 fBranchChoosing = kTRUE;
150}
151
152// --------------------------------------------------------------------------
153//
154// The first time this function is called all branches are disabled.
155// The given branch is enabled. By enabling only the branches you
156// are processing you can speed up your calculation many times (up to
157// a factor of 10 or 20)
158//
159void MReadTree::EnableBranch(const char *name)
160{
161 EnableBranchChoosing();
162 fChain->SetBranchStatus(name, kTRUE);
163}
164
165// --------------------------------------------------------------------------
166//
167// This is the implementation of the Auto Enabling Scheme.
168// For more information see MTask::AddBranchToList.
169// This function loops over all tasks in the tasklist and enables
170// all branches which are requested by the tasks.
171//
172// To enable 'unknown' branches which are not in the Branchlist of
173// the tasks you can call EnableBranch
174//
175void MReadTree::EnableBranches(MParList *plist)
176{
177 //
178 // if auto enabling is off reject the request
179 //
180 if (!fAutoEnable)
181 return;
182
183 //
184 // check whether branch choosing must be switched on
185 //
186 EnableBranchChoosing();
187
188 //
189 // request the tasklist from the parameter list.
190 // FIXME: Tasklist can have a different name
191 //
192 const MTaskList *tlist = (MTaskList*)plist->FindObject("MTaskList");
193 if (!tlist)
194 {
195 *fLog << "Cannot use auto enabeling scheme for branches. 'MTaskList' not found." << endl;
196 return;
197 }
198
199 //
200 // Loo over all tasks in the task list.
201 //
202 MTask *task;
203 TIter NextTask(tlist->GetList());
204 while ((task=(MTask*)NextTask()))
205 {
206 //
207 // Loop over all branches of this task
208 //
209 TNamed *branch;
210 TIter NextBranch(task->GetListOfBranches());
211 while ((branch=(TNamed*)NextBranch()))
212 {
213 //
214 // Get branch name to enable and enable the branch
215 //
216 const char *name = branch->GetName();
217
218 *fLog << "Enabeling '" << name << "'." << endl;
219
220 fChain->SetBranchStatus(name, kTRUE);
221 }
222 }
223}
224
225// --------------------------------------------------------------------------
226//
227// The PreProcess loops (till now) over the branches in the given tree.
228// It checks if the corresponding containers (containers with the same
229// name than the branch name) are existing in the Parameter Container List.
230// If not, a container of objec type 'branch-name' is created (everything
231// after the last semicolon in the branch name is stripped). Only
232// branches which don't have a veto (see VetoBranch) are enabled If the
233// object isn't found in the root dictionary (a list of classes known by the
234// root environment) the branch is skipped and an error message is printed
235// out.
236//
237Bool_t MReadTree::PreProcess(MParList *pList)
238{
239 //
240 // get number of events in this tree
241 //
242 fNumEntries = (UInt_t)fChain->GetEntries();
243
244 if (!fNumEntries)
245 {
246 *fLog << dbginf << "No entries found in chain (file/s)." << endl;
247 return kFALSE;
248 }
249
250 //
251 // output logging information
252 //
253 *fLog << fNumEntries << " entries found in file(s)." << endl;
254
255 //
256 // Get all branches of this tree and
257 // create the Iterator to loop over all branches
258 //
259 TIter Next(fChain->GetListOfBranches());
260 TBranch *branch=NULL;
261
262 Int_t num=0;
263 //
264 // loop over all tasks for processing
265 //
266 while ( (branch=(TBranch*)Next()) )
267 {
268 //
269 // Get Name of Branch
270 //
271 const char *name = branch->GetName();
272
273 //
274 // Check if enabeling the branch is allowed
275 //
276 if (fVetoList->FindObject(name))
277 {
278 *fLog << "Branch " << name << " has veto... skipped." << endl;
279 continue;
280 }
281
282 //
283 // Create a pointer to the pointer to the object in which the
284 // branch data is stored. The pointers are stored in the TChain
285 // object and we get the pointers from there to delete it.
286 //
287 MParContainer **pcont = new MParContainer*;
288
289 //
290 // check if object is existing in the list
291 //
292 *pcont=pList->FindCreateObj(name);
293
294 if (!*pcont)
295 {
296 //
297 // if class is not existing in the (root) environment
298 // we cannot proceed reading this branch
299 //
300 *fLog << dbginf << "Warning: Class '" << name << "' not existing in dictionary. Branch skipped." << endl;
301 continue;
302 }
303
304 //
305 // here pcont is a pointer the to container in which the data from
306 // the actual branch should be stored - enable branch.
307 //
308 fChain->SetBranchAddress(name, pcont);
309
310 *fLog << "Branch " << name << " setup for reading." << endl;
311
312 num++;
313 }
314
315 *fLog << "MReadTree setup " << num << " branches." << endl;
316
317 EnableBranches(pList);
318
319 if (fProgress)
320 fProgress->SetRange(0, fNumEntries);
321
322 return kTRUE;
323}
324
325// --------------------------------------------------------------------------
326//
327// The Process-function reads one event from the tree (this contains all
328// enabled branches) and increases the position in the file by one event.
329// (Remark: The position can also be set by some member functions
330// If the end of the file is reached the Eventloop is stopped.
331//
332Bool_t MReadTree::Process()
333{
334 return fChain->GetEntry(fNumEntry++) != 0;
335}
336
337// --------------------------------------------------------------------------
338//
339// Get the Event with the current EventNumber fNumEntry
340//
341Bool_t MReadTree::GetEvent()
342{
343 return fChain->GetEntry(fNumEntry) != 0;
344}
345
346// --------------------------------------------------------------------------
347//
348// Decrease the number of the event which is read by Process() next
349// by one or more
350//
351Bool_t MReadTree::DecEventNum(UInt_t dec)
352{
353 //!
354 //! this function makes Process() read the event one (or more) before
355 //! the actual position (event) in the tree
356 //!
357 if (fNumEntry < dec/*+1*/)
358 {
359 *fLog << "MReadTree::SetPrevEvent: WARNING: " << fNumEntry/*-1*/ << "-" << dec << " out of Range." << endl;
360 return kFALSE;
361 }
362
363 fNumEntry -= dec/*+1*/;
364 return kTRUE;
365}
366
367// --------------------------------------------------------------------------
368//
369// Increase the number of the event which is read by Process() next
370// by one or more
371//
372Bool_t MReadTree::IncEventNum(UInt_t inc)
373{
374 //!
375 //! this function makes Process() read the next (or more) after
376 //! the actual position (event) in the tree
377 //! (Be careful: IncEventNum() or IncEventNum(1) does not chenge anything
378 //! in the standard behaviour of the task)
379 //!
380 if (fNumEntry+inc/*-1*/ >= fNumEntries)
381 {
382 *fLog << "MReadTree::SkipEvents: WARNING: " << fNumEntry/*-1*/ << "+" << inc << " out of Range." << endl;
383 return kFALSE;
384 }
385
386 fNumEntry += inc/*-1*/;
387 return kTRUE;
388}
389
390// --------------------------------------------------------------------------
391//
392// this function makes Process() read event number nr next
393//
394// Remark: You can use this function after instatiating you MReadTree-object
395// to set the event number from which you want to start reading.
396//
397Bool_t MReadTree::SetEventNum(UInt_t nr)
398{
399 if (nr>=fNumEntries)
400 {
401 *fLog << "MReadTree::SetEventNum: WARNING: " << nr << " out of Range." << endl;
402 return kFALSE;
403 }
404
405 fNumEntry = nr;
406 return kTRUE;
407}
408
409// --------------------------------------------------------------------------
410//
411// If you don't want that an object is created for this branch
412// and/or the branch address is set in the Preprocessing of
413// MReadTree use VetoBranch. This saves mainly memory space.
414//
415void MReadTree::VetoBranch(const char *name)
416{
417 TNamed *branch = new TNamed(name, "");
418 fVetoList->Add(branch);
419}
Note: See TracBrowser for help on using the repository browser.