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

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