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

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