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

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