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

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