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

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