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

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