source: tags/Mars-V0.4/mbase/MReadTree.cc

Last change on this file was 895, checked in by tbretz, 23 years ago
*** empty log message ***
File size: 12.0 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 cout << " " << fChain->LoadTree(fNumEntry) << " "<<flush;
231
232 fNumEntry++;
233
234 return kTRUE;
235}
236
237// --------------------------------------------------------------------------
238//
239// Get the Event with the current EventNumber fNumEntry
240//
241Bool_t MReadTree::GetEvent()
242{
243 fChain->GetEntry(fNumEntry);
244
245 return kTRUE;
246}
247
248// --------------------------------------------------------------------------
249//
250// Decrease the number of the event which is read by Process() next
251// by one or more
252//
253Bool_t MReadTree::DecEventNum(UInt_t dec)
254{
255 //!
256 //! this function makes Process() read the event one (or more) before
257 //! the actual position (event) in the tree
258 //!
259 if (fNumEntry < dec/*+1*/)
260 {
261 *fLog << "MReadTree::SetPrevEvent: WARNING: " << fNumEntry/*-1*/ << "-" << dec << " out of Range." << endl;
262 return kFALSE;
263 }
264
265 fNumEntry -= dec/*+1*/;
266 return kTRUE;
267}
268
269// --------------------------------------------------------------------------
270//
271// Increase the number of the event which is read by Process() next
272// by one or more
273//
274Bool_t MReadTree::IncEventNum(UInt_t inc)
275{
276 //!
277 //! this function makes Process() read the next (or more) after
278 //! the actual position (event) in the tree
279 //! (Be careful: IncEventNum() or IncEventNum(1) does not chenge anything
280 //! in the standard behaviour of the task)
281 //!
282 if (fNumEntry+inc/*-1*/ >= fNumEntries)
283 {
284 *fLog << "MReadTree::SkipEvents: WARNING: " << fNumEntry/*-1*/ << "+" << inc << " out of Range." << endl;
285 return kFALSE;
286 }
287
288 fNumEntry += inc/*-1*/;
289 return kTRUE;
290}
291
292// --------------------------------------------------------------------------
293//
294// this function makes Process() read event number nr next
295//
296// Remark: You can use this function after instatiating you MReadTree-object
297// to set the event number from which you want to start reading.
298//
299Bool_t MReadTree::SetEventNum(UInt_t nr)
300{
301 if (nr>=fNumEntries)
302 {
303 *fLog << "MReadTree::SetEventNum: WARNING: " << nr << " out of Range." << endl;
304 return kFALSE;
305 }
306
307 fNumEntry = nr;
308 return kTRUE;
309}
310
311// --------------------------------------------------------------------------
312//
313// This function checks if the Branch Name is part of the Veto List.
314// This means, that the preprocess doesn't enable the branch.
315//
316Bool_t MReadTree::HasVeto(const char *name) const
317{
318 const size_t nlen = strlen(name)+1;
319
320 char *pos = fVetoList->GetArray();
321 size_t len = fVetoList->GetSize();
322
323 //
324 // now we compare the 'strings' in the list word by word
325 // (string or word in this context means a zero terminated
326 // array of chars
327 //
328
329 for (;;)
330 {
331 //
332 // Search for the first byte of the name
333 //
334 char *c = (char*)memchr(pos, name[0], len);
335
336 //
337 // if we don't find the first byte, the list cannot contain 'name'
338 //
339 if (!c)
340 return kFALSE;
341
342 //
343 // calculate and check how many bytes remains in the list
344 //
345 len -= c-pos;
346
347 //
348 // if there are not enough bytes to match the query we are done
349 //
350 if (len<nlen)
351 return kFALSE;
352
353 //
354 // check if the next 'nlen' byte (including the trailing '\0'
355 // are matching
356 //
357 if (!memcmp(c, name, nlen))
358 return kTRUE;
359
360 //
361 // we didn't find the string, goto the next 'string'
362 //
363 pos = (char*)memchr(c, '\0', len);
364
365 //
366 // check if there is a 'next' string really
367 //
368 if (!pos)
369 return kFALSE;
370
371 //
372 // calculate the remaining length
373 //
374 len -= pos-c;
375
376 //
377 // if there are not enough bytes to match the query we are done
378 //
379 if (len<nlen)
380 return kFALSE;
381 }
382}
383
384
385// --------------------------------------------------------------------------
386//
387// If you don't want that a branch is enabled within the PreProcess you
388// can set a veto for enabeling the branch. (This means also the
389// corresponding object won't be created automatically)
390//
391// This functionality is for experienced users which don't want to
392// read in branches which are not processed in the program (for
393// speed reasons)
394//
395void MReadTree::VetoBranch(const char *name)
396{
397 //
398 // Add this file as the last entry of the list
399 // (including the trailing '\0')
400 //
401 const int sz = fVetoList->GetSize();
402 const int tsz = strlen(name)+1;
403
404 fVetoList->Set(sz+tsz);
405
406 memcpy(fVetoList->GetArray()+sz, name, tsz);
407}
Note: See TracBrowser for help on using the repository browser.