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

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