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

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