source: trunk/MagicSoft/Mars/mfileio/MReadTree.cc@ 5368

Last change on this file since 5368 was 5160, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 32.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 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2003
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// If the chain switches from one file to another file all //
45// TObject::Notify() functions are called of TObject objects which were //
46// added to the Notifier list view MReadTree::AddNotify. If MReadTree //
47// is the owner (viw MReadTree::SetOwner) all this objects are deleted //
48// by the destructor of MReadTree //
49// //
50/////////////////////////////////////////////////////////////////////////////
51#include "MReadTree.h"
52
53#include <fstream>
54
55#include <TFile.h> // TFile::GetName
56#include <TSystem.h> // gSystem->ExpandPath
57#include <TChainElement.h>
58#include <TOrdCollection.h>
59
60#include "MChain.h"
61#include "MFilter.h"
62#include "MParList.h"
63#include "MTaskList.h"
64
65#include "MLog.h"
66#include "MLogManip.h"
67
68
69ClassImp(MReadTree);
70
71using namespace std;
72
73// --------------------------------------------------------------------------
74//
75// Default constructor. Don't use it.
76//
77MReadTree::MReadTree()
78 : fNumEntry(0), fNumEntries(0), fBranchChoosing(kFALSE), fAutoEnable(kTRUE)
79{
80 fName = "MRead";
81 fTitle = "Task to loop over all events in one single tree";
82
83 fVetoList = NULL;
84 fNotify = NULL;
85
86 fChain = NULL;
87}
88
89// --------------------------------------------------------------------------
90//
91// Constructor. It creates an TChain instance which represents the
92// the Tree you want to read and adds the given file (if you gave one).
93// More files can be added using MReadTree::AddFile.
94// Also an empty veto list is created. This list is used if you want to
95// veto (disable or "don't enable") a branch in the tree, it vetos also
96// the creation of the corresponding object.
97// An empty list of TObjects are also created. This objects are called
98// at any time the TChain starts to read from another file.
99//
100MReadTree::MReadTree(const char *tname, const char *fname,
101 const char *name, const char *title)
102 : fNumEntry(0), fNumEntries(0), fBranchChoosing(kFALSE), fAutoEnable(kTRUE)
103{
104 fName = name ? name : "MRead";
105 fTitle = title ? title : "Task to loop over all events in one single tree";
106
107 fVetoList = new TList;
108 fVetoList->SetOwner();
109
110 fNotify = new TList;
111
112 //
113 // open the input stream
114 //
115 fChain = new MChain(tname);
116
117 // root 3.02:
118 // In TChain::Addfile remove the limitation that the file name must contain
119 // the string ".root". ".root" is necessary only in case one wants to specify
120 // a Tree in a subdirectory of a Root file with eg, the format:
121
122 if (fname)
123 AddFile(fname);
124// if (fChain->Add(fname)>0)
125// SetBit(kChainWasChanged);
126}
127
128// --------------------------------------------------------------------------
129//
130// Destructor. It deletes the TChain and veto list object
131//
132MReadTree::~MReadTree()
133{
134 //
135 // Delete all the pointers to pointers to the objects where the
136 // branche data gets stored. FIXME: When PreProcessed twice this
137 // creates a memory leak!
138 //
139 TIter Next(fChain->GetStatus());
140
141 TChainElement *element = NULL;
142 while ((element=(TChainElement*)Next()))
143 if (element->GetBaddress())
144 delete (MParContainer**)element->GetBaddress();
145
146 //
147 // Delete the chain and the veto list
148 //
149#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,00)
150 if (fChain->GetFile())
151 delete fChain->GetFile();
152#endif
153 delete fChain;
154
155 delete fNotify;
156 delete fVetoList;
157}
158
159Byte_t MReadTree::IsFileValid(const char *name)
160{
161 ifstream fin(name);
162 if (!fin)
163 return 0;
164
165 Char_t c[4];
166 fin.read(c, 4);
167 if (!fin)
168 return 0;
169
170 return c[0]=='r'&& c[1]=='o' && c[2]=='o' && c[3]=='t' ? 1 : 0;
171}
172
173// --------------------------------------------------------------------------
174//
175// This check whether all branches in the tree have the same size. If
176// this is not the case the events in the different branches cannot
177// be ordered correctly.
178//
179Bool_t MReadTree::CheckBranchSize()
180{
181 TArrayI entries(fChain->GetStatus()->GetSize());
182 Int_t num=0;
183
184 // Loop over all branches which have a corresponding container
185 TIter Next(fChain->GetStatus());
186
187 TChainElement *element = NULL;
188 while ((element=(TChainElement*)Next()))
189 {
190 // Get branch name and find pointer to corresponding branch
191 const TString name = element->GetName();
192 const TBranch *b = fChain->FindBranch(name);
193
194 // Skip element without corresponding branches (like "*")
195 if (!b)
196 continue;
197
198 entries[num++] = (Int_t)b->GetEntries();
199 }
200
201 // Check the number of entries of the branches pair-wise
202 for (int i=0; i<num; i++)
203 for (int j=i; j<num; j++)
204 {
205 if (entries[i]==entries[j])
206 continue;
207
208 *fLog << err << "ERROR - File corruption detected:" << endl;
209 *fLog << " Due to several circumstances (such at a bug in MReadTree or wrong" << endl;
210 *fLog << " usage of the file UPDATE mode) you may have produced a file in which" << endl;
211 *fLog << " at least two branches in the same tree (" << fChain->GetName() << ") have different" << endl;
212 *fLog << " number of entries. Sorry, but this file (" << GetFileName() << ")" << endl;
213 *fLog << " is unusable." << endl;
214 return kFALSE;
215 }
216
217 return kTRUE;
218}
219
220// --------------------------------------------------------------------------
221//
222// If the owner flag is set all TObjects which are scheduled via
223// AddNotify are deleted by the destructor of MReadTree
224//
225void MReadTree::SetOwner(Bool_t flag)
226{
227 flag ? fNotify->SetBit(kIsOwner) : fNotify->ResetBit(kIsOwner);
228}
229
230// --------------------------------------------------------------------------
231//
232// This function is called each time MReadTree changes the file to read
233// from. It calls all TObject::Notify() functions which are scheduled
234// via AddNotify.
235//
236Bool_t MReadTree::Notify()
237{
238 //
239 // Do a consistency check for all branches
240 //
241 if (!CheckBranchSize())
242 return kFALSE;
243
244 *fLog << inf << GetDescriptor() << ": Switching to #" << GetFileIndex();
245 *fLog << " '" << GetFileName() << "' (before event #";
246 *fLog << GetNumEntry()-1 << ")" << endl;
247
248 if (!fNotify)
249 return kTRUE;
250
251 TIter Next(fNotify);
252 TObject *o=NULL;
253 while ((o=Next()))
254 if (!o->Notify())
255 {
256 *fLog << err << "Calling Notify() for object " << o->GetName() << " failed... abort." << endl;
257 return kFALSE;
258 }
259
260 return kTRUE;
261}
262
263// --------------------------------------------------------------------------
264//
265// If you want to read the given tree over several files you must add
266// the files here before PreProcess is called. Be careful: If the tree
267// doesn't have the same contents (branches) it may confuse your
268// program (trees which are are not existing in later files are not read
269// anymore, tree wich are not existing in the first file are never read)
270//
271// Name may use the wildcarding notation, eg "xxx*.root" means all files
272// starting with xxx in the current file system directory.
273//
274// AddFile returns the number of files added to the chain.
275//
276// For more information see TChain::Add
277//
278Int_t MReadTree::AddFile(const char *fname, Int_t entries)
279{
280#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,01)
281 //
282 // This is a workaround to get rid of crashed if the file doesn't
283 // exist due to non initialized TFile::fProcessIDs
284 //
285 // (Code taken from TFile::TFile
286 //
287 TString newname; // char-array must overcome comming block
288
289 if (strrchr(fname, '?') || strrchr(fname, '*'))
290 {
291 *fLog << warn;
292 *fLog<< "WARNING: Using widcards with older root versions:" << endl;
293 *fLog << " You may encounter crashes closing the files..." << endl;
294 }
295 else
296 {
297 const char *name;
298
299 if ((name = gSystem->ExpandPathName(fname)))
300 {
301 newname = name;
302 delete [] name;
303 }
304
305 if (newname.IsNull())
306 {
307 *fLog << err << dbginf << "Error expanding path " << fname << "." << endl;
308 return 0;
309 }
310
311 if (gSystem->AccessPathName(newname, kFileExists))
312 {
313 *fLog << err << "ERROR - File '" << fname << "' does not exist." << endl;
314 return 0;
315 }
316
317 fname = newname.Data();
318 }
319#endif
320
321 //
322 // FIXME! A check is missing whether the file already exists or not.
323 //
324 const Int_t numfiles = fChain->Add(fname, entries<0?TChain::kBigNumber:entries);
325
326 if (numfiles>0)
327 {
328 SetBit(kChainWasChanged);
329 *fLog << inf << GetDescriptor() << " - AddFile: " << numfiles << " files added from " << fname << "." << endl;
330 }
331 else
332 *fLog << warn << "WARNING: '" << fname << "' not added to " << GetDescriptor() << endl;
333
334 return numfiles;
335}
336
337/*
338 // --------------------------------------------------------------------------
339 //
340 //
341 Int_t MReadTree::AddFile(const TChainElement &obj)
342 {
343 return AddFile(obj.GetTitle(), obj.GetEntries());
344 }
345*/
346
347// --------------------------------------------------------------------------
348//
349// Adds all files from another MReadTree to this instance
350//
351// Returns the number of file which were added
352//
353Int_t MReadTree::AddFiles(const MReadTree &read)
354{
355 const Int_t rc = fChain->Add(read.fChain);
356
357 if (rc>0)
358 SetBit(kChainWasChanged);
359
360 /*
361 Int_t rc = 0;
362
363 TIter Next(read.fChain->GetListOfFiles());
364 TObject *obj = NULL;
365 while ((obj=Next()))
366 rc += AddFile(*(TChainElement*)obj);
367 */
368
369 return rc;
370}
371
372// --------------------------------------------------------------------------
373//
374// Sort the files by their file-names
375//
376void MReadTree::SortFiles()
377{
378 fChain->GetListOfFiles()->Sort();
379}
380
381// --------------------------------------------------------------------------
382//
383// This function is called if Branch choosing method should get enabled.
384// Branch choosing means, that only the enabled branches are read into
385// memory. To use an enableing scheme we have to disable all branches first.
386// This is done, if this function is called the first time.
387//
388void MReadTree::EnableBranchChoosing()
389{
390 if (fBranchChoosing)
391 return;
392
393 *fLog << inf << GetDescriptor() << ": Branch choosing enabled (only enabled branches are read)." << endl;
394 fChain->SetBranchStatus("*", kFALSE);
395 fBranchChoosing = kTRUE;
396}
397
398// --------------------------------------------------------------------------
399//
400// The first time this function is called all branches are disabled.
401// The given branch is enabled. By enabling only the branches you
402// are processing you can speed up your calculation many times (up to
403// a factor of 10 or 20)
404//
405void MReadTree::EnableBranch(const char *name)
406{
407 if (fChain->GetListOfFiles()->GetEntries()==0)
408 {
409 *fLog << err << "Chain contains no file... Branch '";
410 *fLog << name << "' ignored." << endl;
411 return;
412 }
413
414 EnableBranchChoosing();
415
416 TNamed branch(name, "");
417 SetBranchStatus(&branch, kTRUE);
418}
419
420// --------------------------------------------------------------------------
421//
422// Set branch status of branch name
423//
424void MReadTree::SetBranchStatus(const char *name, Bool_t status)
425{
426 fChain->SetBranchStatus(name, status);
427
428 *fLog << inf << (status ? "Enabled" : "Disabled");
429 *fLog << " subbranch '" << name << "'." << endl;
430}
431
432// --------------------------------------------------------------------------
433//
434// Checks whether a branch with the given name exists in the chain
435// and sets the branch status of this branch corresponding to status.
436//
437void MReadTree::SetBranchStatus(TObject *branch, Bool_t status)
438{
439 //
440 // Get branch name
441 //
442 const char *name = branch->GetName();
443
444 //
445 // Check whether this branch really exists
446 //
447 TString bn(name);
448 if (bn.EndsWith("*"))
449 bn.Remove(bn.Length()-1);
450
451 if (fChain->GetBranch(bn))
452 SetBranchStatus(name, status);
453
454 //
455 // Remove trailing '.' if one and try to enable the subbranch without
456 // the master branch name. This is to be compatible with older mars
457 // and camera files.
458 //
459 const char *dot = strrchr(name, '.');
460 if (!dot)
461 return;
462
463 if (fChain->GetBranch(dot+1))
464 SetBranchStatus(dot+1, status);
465}
466
467// --------------------------------------------------------------------------
468//
469// Set the status of all branches in the list to status.
470//
471void MReadTree::SetBranchStatus(const TList *list, Bool_t status)
472{
473 //
474 // Loop over all subbranches in this master branch
475 //
476 TIter Next(list);
477
478 TObject *obj;
479 while ((obj=Next()))
480 SetBranchStatus(obj, status);
481}
482
483// --------------------------------------------------------------------------
484//
485// This is the implementation of the Auto Enabling Scheme.
486// For more information see MTask::AddBranchToList.
487// This function loops over all tasks and its filters in the tasklist
488// and enables all branches which are requested by the tasks and its
489// filters.
490//
491// To enable 'unknown' branches which are not in the branchlist of
492// the tasks you can call EnableBranch
493//
494void MReadTree::EnableBranches(MParList *plist)
495{
496 //
497 // check whether branch choosing must be switched on
498 //
499 EnableBranchChoosing();
500
501 //
502 // request the tasklist from the parameter list.
503 // FIXME: Tasklist can have a different name
504 //
505 const MTaskList *tlist = (MTaskList*)plist->FindObject("MTaskList");
506 if (!tlist)
507 {
508 *fLog << warn << GetDescriptor() << "Cannot use auto enabeling scheme for branches. 'MTaskList' not found." << endl;
509 return;
510 }
511
512 //
513 // This loop is not necessary. We could do it like in the commented
514 // loop below. But this loop makes sure, that we don't try to enable
515 // one branch several times. This would not harm, but we would get
516 // an output for each attempt. To have several outputs for one subbranch
517 // may confuse the user, this we don't want.
518 // This loop creates a new list of subbranches and for each branch
519 // which is added we check before whether it already exists or not.
520 //
521 TList list;
522
523 MTask *task;
524 TIter NextTask(tlist->GetList());
525 while ((task=(MTask*)NextTask()))
526 {
527 TObject *obj;
528
529 TIter NextTBranch(task->GetListOfBranches());
530 while ((obj=NextTBranch()))
531 if (!list.FindObject(obj->GetName()))
532 list.Add(obj);
533
534 const MFilter *filter = task->GetFilter();
535
536 if (!filter)
537 continue;
538
539 TIter NextFBranch(filter->GetListOfBranches());
540 while ((obj=NextFBranch()))
541 if (!list.FindObject(obj->GetName()))
542 list.Add(obj);
543 }
544
545 SetBranchStatus(&list, kTRUE);
546/*
547 //
548 // Loop over all tasks iand its filters n the task list.
549 //
550 MTask *task;
551 TIter NextTask(tlist->GetList());
552 while ((task=(MTask*)NextTask()))
553 {
554 SetBranchStatus(task->GetListOfBranches(), kTRUE);
555
556 const MFilter *filter = task->GetFilter();
557 if (!filter)
558 continue;
559
560 SetBranchStatus(filter->GetListOfBranches(), kTRUE);
561
562 }
563*/
564}
565
566// --------------------------------------------------------------------------
567//
568// If the chain has been changed (by calling AddFile or using a file
569// in the constructors argument) the number of entries is newly
570// calculated from the files in the chain - this may take a while.
571// The number of entries is returned.
572//
573UInt_t MReadTree::GetEntries()
574{
575 if (TestBit(kChainWasChanged))
576 {
577 *fLog << inf << "Scanning chain " << fChain->GetName() << "... " << flush;
578 fNumEntries = (UInt_t)fChain->GetEntries();
579 *fLog << fNumEntries << " events found." << endl;
580 ResetBit(kChainWasChanged);
581 }
582 return fNumEntries==TChain::kBigNumber ? 0 : fNumEntries;
583}
584
585// --------------------------------------------------------------------------
586//
587// The disables all subbranches of the given master branch.
588//
589void MReadTree::DisableSubBranches(TBranch *branch)
590{
591 //
592 // This is not necessary, it would work without. But the output
593 // may confuse the user...
594 //
595 if (fAutoEnable || fBranchChoosing)
596 return;
597
598 SetBranchStatus(branch->GetListOfBranches(), kFALSE);
599}
600
601// --------------------------------------------------------------------------
602//
603// The PreProcess loops (till now) over the branches in the given tree.
604// It checks if the corresponding containers (containers with the same
605// name than the branch name) are existing in the Parameter Container List.
606// If not, a container of objec type 'branch-name' is created (everything
607// after the last semicolon in the branch name is stripped). Only
608// branches which don't have a veto (see VetoBranch) are enabled If the
609// object isn't found in the root dictionary (a list of classes known by the
610// root environment) the branch is skipped and an error message is printed
611// out.
612// If a selector is specified it is preprocessed after the
613// MReadTree::PreProcess
614//
615Int_t MReadTree::PreProcess(MParList *pList)
616{
617 fTaskList = (MTaskList*)pList->FindObject("MTaskList");
618 if (!fTaskList)
619 *fLog << warn << "WARNING - Standard tasklist MTaskList not found... ignoring Stream-ID." << endl;
620
621 //
622 // Make sure, that all the following calls doesn't result in
623 // Notifications. This may be dangerous, because the notified
624 // tasks are not preprocessed.
625 //
626 fChain->SetNotify(NULL);
627
628 //
629 // It seems, that TFile and TTree are not completely independant if
630 // many times the same file is openes (MReadReports) and some of
631 // the files in the chains don't have one tree. TChain::fTreeNumber
632 // is already set before LoadTree from GetFile is called and
633 // it crashes. ResetTree makes sure, that the tree number is -1
634 //
635 fChain->ResetTree();
636 // Maybe this would be enough, but the above might be safer...
637 //if (fChain->GetTreeNumber()==0)
638 // fChain->ResetTree();
639
640 //
641 // check for files and for the tree!
642 //
643 if (!fChain->GetFile())
644 {
645 *fLog << err << GetDescriptor() << ": No file or no tree with name " << fChain->GetName() << " in file." << endl;
646 return kFALSE;
647 }
648
649 //
650 // get number of events in this tree
651 //
652 if (!GetEntries())
653 {
654 *fLog << err << GetDescriptor() << ": No entries found in file(s)" << endl;
655 return kFALSE;
656 }
657
658 //
659 // output logging information
660 //
661 *fLog << inf << fNumEntries << " entries found in file(s)." << endl;
662
663 //
664 // Get all branches of this tree and
665 // create the Iterator to loop over all branches
666 //
667 TIter Next(fChain->GetListOfBranches());
668 TBranch *branch=NULL;
669
670 Int_t num=0;
671
672 //
673 // loop over all tasks for processing
674 //
675 while ( (branch=(TBranch*)Next()) )
676 {
677 //
678 // Get Name of Branch and Object
679 //
680 const char *bname = branch->GetName();
681
682 TString oname(bname);
683 if (oname.EndsWith("."))
684 oname.Remove(oname.Length()-1);
685
686 //
687 // Check if enabeling the branch is allowed
688 //
689 if (fVetoList->FindObject(oname))
690 {
691 *fLog << inf << "Master branch " << bname << " has veto... skipped." << endl;
692 DisableSubBranches(branch);
693 continue;
694 }
695
696 //
697 // Create a pointer to the pointer to the object in which the
698 // branch data is stored. The pointers are stored in the TChain
699 // object and we get the pointers from there to delete it.
700 //
701 MParContainer **pcont= new MParContainer*;
702
703#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,06)
704 const char *classname = oname;
705#else
706 const char *classname = branch->GetClassName();
707#endif
708
709 //
710 // check if object is existing in the list
711 //
712 *pcont=pList->FindCreateObj(classname, oname);
713
714 if (!*pcont)
715 {
716 //
717 // if class is not existing in the (root) environment
718 // we cannot proceed reading this branch
719 //
720 *fLog << warn << dbginf << "Warning: Class '" << classname;
721 *fLog << "' for " << oname << " not existing in dictionary. Branch skipped." << endl;
722 DisableSubBranches(branch);
723 continue;
724 }
725
726 //
727 // Check whether a Pointer to a pointer already exists.
728 // If we created one already, delete it.
729 //
730 TChainElement *element = (TChainElement*)fChain->GetStatus()->FindObject(bname);
731 if (element)
732 delete (MParContainer**)element->GetBaddress();
733
734 //
735 // here pcont is a pointer the to container in which the data from
736 // the actual branch should be stored - enable branch.
737 //
738 fChain->SetBranchAddress(bname, pcont);
739
740 *fLog << inf << "Master branch address '" << bname << "' [";
741 *fLog << classname << "] setup for reading." << endl;
742
743 //*fLog << "Branch " << bname << " autodel: " << (int)branch->IsAutoDelete() << endl;
744 //branch->SetAutoDelete();
745
746 num++;
747 }
748
749 *fLog << inf << GetDescriptor() << " setup " << num << " master branches addresses." << endl;
750
751 //
752 // If auto enabling scheme isn't disabled, do auto enabling
753 //
754 if (fAutoEnable)
755 EnableBranches(pList);
756
757 //
758 // Now we can start notifying. Reset tree makes sure, that TChain thinks
759 // that the correct file is not yet initialized and reinitilizes it
760 // as soon as the first event is read. This is necessary to call
761 // the notifiers when the first event is read, but after the
762 // PreProcess-function.
763 //
764 fChain->ResetTree();
765 fChain->SetNotify(this);
766
767 return GetSelector() ? GetSelector()->CallPreProcess(pList) : kTRUE;
768}
769
770// --------------------------------------------------------------------------
771//
772// Set the ready to save flag of all containers which branchaddresses are
773// set for. This is necessary to copy data.
774//
775void MReadTree::SetReadyToSave(Bool_t flag)
776{
777 TIter Next(fChain->GetStatus());
778
779 TChainElement *element = NULL;
780 while ((element=(TChainElement*)Next()))
781 {
782 //
783 // Check whether the branch is enabled
784 //
785 if (!element->GetStatus())
786 continue;
787
788 //
789 // Get the pointer to the pointer of the corresponding container
790 //
791 MParContainer **pcont = (MParContainer**)element->GetBaddress();
792
793 //
794 // Check whether the pointer is not NULL
795 //
796 if (!pcont || !*pcont)
797 continue;
798
799 //
800 // Set the ready to save status of the container.
801 //
802 (*pcont)->SetReadyToSave(flag);
803 }
804
805 //
806 // Set the ready to save status of this task (used?), too
807 //
808 MTask::SetReadyToSave(flag);
809}
810
811// --------------------------------------------------------------------------
812//
813// The Process-function reads one event from the tree (this contains all
814// enabled branches) and increases the position in the file by one event.
815// (Remark: The position can also be set by some member functions
816// If the end of the file is reached the Eventloop is stopped.
817// In case an event selector is given its value is checked before
818// reading the event. If it returns kAFLSE the event is skipped.
819//
820#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,06)
821#include "MRawEvtData.h"
822#endif
823Int_t MReadTree::Process()
824{
825 //
826 // This is necessary due to a bug in TChain::LoadTree in root.
827 // will be fixed in 3.03
828 //
829#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,01)
830 if (fNumEntry >= GetEntries())
831 return kFALSE;
832#endif
833
834#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,06)
835 //
836 // This fixes 99.9% of a memory leak using a root version prior
837 // to 3.02/??
838 //
839 TChainElement *element=NULL;
840 TIter Next(fChain->GetStatus());
841 while ((element=(TChainElement*)Next()))
842 {
843 MParContainer **c = (MParContainer**)element->GetBaddress();
844 if (!c) continue;
845 if ((*c)->InheritsFrom(MRawEvtData::Class()))
846 static_cast<MRawEvtData*>(*c)->DeletePixels(kFALSE);
847
848 }
849#endif
850
851 if (GetSelector())
852 {
853 //
854 // Make sure selector is processed
855 //
856 if (!GetSelector()->CallProcess())
857 {
858 *fLog << err << dbginf << "Processing Selector failed." << endl;
859 return kFALSE;
860 }
861
862 //
863 // Skip Event
864 //
865 if (!GetSelector()->IsConditionTrue())
866 {
867 fNumEntry++;
868 return kCONTINUE;
869 }
870 }
871
872 const Bool_t rc = fChain->GetEntry(fNumEntry++) != 0;
873
874 if (fTaskList)
875 fTaskList->SetStreamId(fChain->GetName());
876
877 if (rc)
878 SetReadyToSave();
879
880 return rc;
881}
882
883// --------------------------------------------------------------------------
884//
885// If a selector is given the selector is post processed
886//
887Int_t MReadTree::PostProcess()
888{
889 return GetSelector() ? GetSelector()->CallPostProcess() : kTRUE;
890}
891
892// --------------------------------------------------------------------------
893//
894// Get the Event with the current EventNumber fNumEntry
895//
896Bool_t MReadTree::GetEvent()
897{
898 Bool_t rc = fChain->GetEntry(fNumEntry) != 0;
899
900 if (rc)
901 SetReadyToSave();
902
903 return rc;
904}
905
906// --------------------------------------------------------------------------
907//
908// Decrease the number of the event which is read by Process() next
909// by one or more
910//
911Bool_t MReadTree::DecEventNum(UInt_t dec)
912{
913 if (fNumEntry-dec >= GetEntries())
914 {
915 *fLog << warn << GetDescriptor() << ": DecEventNum, WARNING - Event " << fNumEntry << "-";
916 *fLog << dec << "=" << (Int_t)fNumEntry-dec << " out of Range (>=";
917 *fLog << GetEntries() << ")." << endl;
918 return kFALSE;
919 }
920
921 fNumEntry -= dec;
922 return kTRUE;
923}
924
925// --------------------------------------------------------------------------
926//
927// Increase the number of the event which is read by Process() next
928// by one or more
929//
930Bool_t MReadTree::IncEventNum(UInt_t inc)
931{
932 if (fNumEntry+inc >= GetEntries())
933 {
934 *fLog << warn << GetDescriptor() << ": IncEventNum, WARNING - Event " << fNumEntry << "+";
935 *fLog << inc << "=" << (Int_t)fNumEntry+inc << " out of Range (>=";
936 *fLog << GetEntries() << ")." << endl;
937 return kFALSE;
938 }
939
940 fNumEntry += inc;
941 return kTRUE;
942}
943
944// --------------------------------------------------------------------------
945//
946// This function makes Process() read event number nr next
947//
948// Remark: You can use this function after instatiating you MReadTree-object
949// to set the event number from which you want to start reading.
950//
951Bool_t MReadTree::SetEventNum(UInt_t nr)
952{
953 if (nr!=0 && nr >= GetEntries())
954 {
955 *fLog << warn << GetDescriptor() << ": SetEventNum, WARNING - " << nr << " out of Range." << endl;
956 return kFALSE;
957 }
958
959 fNumEntry = nr;
960 return kTRUE;
961}
962
963// --------------------------------------------------------------------------
964//
965// For the branch with the given name:
966// 1) no object is automatically created
967// 2) the branch address for this branch is not set
968// (because we lack the object, see 1)
969// 3) The whole branch (exactly: all its subbranches) are disabled
970// this means are not read in memory by TTree:GetEntry
971//
972void MReadTree::VetoBranch(const char *name)
973{
974 fVetoList->Add(new TNamed(name, ""));
975}
976
977// --------------------------------------------------------------------------
978//
979// Return the name of the file we are actually reading from.
980//
981TString MReadTree::GetFileName() const
982{
983 const TFile *file = fChain->GetFile();
984
985 if (!file)
986 return TString("<unknown>");
987
988 TString name(file->GetName());
989 name.Remove(0, name.Last('/')+1);
990 return name;
991}
992
993// --------------------------------------------------------------------------
994//
995// Return the number of the file in the chain, -1 in case of an error
996//
997Int_t MReadTree::GetFileIndex() const
998{
999 return fChain->GetTreeNumber();
1000 /*
1001 const TString filename = fChain->GetFile()->GetName();
1002
1003 int i=0;
1004 TObject *file = NULL;
1005
1006 TIter Next(fChain->GetListOfFiles());
1007 while ((file=Next()))
1008 {
1009 if (filename==gSystem->ExpandPathName(file->GetTitle()))
1010 return i;
1011 i++;
1012 }
1013 return -1;
1014 */
1015}
1016
1017// --------------------------------------------------------------------------
1018//
1019// This schedules a TObject which Notify(9 function is called in case
1020// of MReadTree (TChain) switches from one file in the chain to another
1021// one.
1022//
1023void MReadTree::AddNotify(TObject *obj)
1024{
1025 fNotify->Add(obj);
1026}
1027
1028void MReadTree::Print(Option_t *o) const
1029{
1030 *fLog << all << underline << GetDescriptor() << ":" << endl << dec;
1031 *fLog << " Files [Tree]:" << endl;
1032
1033 int i = 0;
1034 TIter Next(fChain->GetListOfFiles());
1035 TObject *obj = NULL;
1036 while ((obj=Next()))
1037 *fLog << " " << i++ << ") " << obj->GetTitle() << " [" << obj->GetName() << "]" << endl;
1038
1039 *fLog << " Total Number of Entries: " << fNumEntries << endl;
1040 *fLog << " Next Entry to read: " << fNumEntry << endl;
1041}
1042
1043// --------------------------------------------------------------------------
1044//
1045// Implementation of SavePrimitive. Used to write the call to a constructor
1046// to a macro. In the original root implementation it is used to write
1047// gui elements to a macro-file.
1048//
1049void MReadTree::StreamPrimitive(ofstream &out) const
1050{
1051 out << " " << ClassName() << " " << GetUniqueName() << "(\"";
1052 out << fChain->GetName() << "\", \"" << fName << "\", \"" << fTitle << "\");" << endl;
1053
1054 TIter Next(fChain->GetListOfFiles());
1055 TObject *obj = NULL;
1056 while ((obj=Next()))
1057 out << " " << GetUniqueName() << ".AddFile(\"" << obj->GetTitle() << "\");" << endl;
1058
1059 if (!fAutoEnable)
1060 out << " " << GetUniqueName() << ".DisableAutoScheme();" << endl;
1061
1062 if (fNumEntry!=0)
1063 out << " " << GetUniqueName() << ".SetEventNum(" << fNumEntry << ");" << endl;
1064
1065
1066}
Note: See TracBrowser for help on using the repository browser.