Added AddTrackParams() method for convenience + some comments
[u/mrichter/AliRoot.git] / ANALYSIS / AliAnalysisDataSlot.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17 // Author: Andrei Gheata, 31/05/2006
18
19 //==============================================================================
20 //   AliAnalysysDataSlot - Class representing a data slot of an analysis task.
21 //      An analysis slot enforces a certain data type required by the Exec()
22 //      method of the analysis task. The slot must be connected to a data 
23 //      container with data of the same type.
24 //
25 // The class should not be directly created by users - it is created by
26 // each AliAnalysisTask when defining its input/output slots using:
27 //
28 //    AliAnalysisTask::SetInput(Int_t index, TClass *type);
29 //    AliAnalysisTask::SetOutput(TClass *type);
30 //
31 // An existing data contaner (AliAnalysisDataContainer) can be connected to the
32 // input/output slots of an analysis task using:
33 //
34 //   AliAnalysisModule::ConnectInput(AliAnalysisTask *task, Int_t islot,
35 //                                   AliAnalysisDataContainer *cont)
36 //   AliAnalysisModule::ConnectOutput(AliAnalysisTask *task,
37 //                                    AliAnalysisDataContainer *cont)
38 // To connect a slot to a data container, the data types declared by both must
39 // match.
40 //==============================================================================
41
42 #include <Riostream.h>
43 #include <TROOT.h>
44 #include <TClass.h>
45 #include <TTree.h>
46 #include <TLeaf.h>
47
48 #include "AliAnalysisDataSlot.h"
49 #include "AliAnalysisTask.h"
50 #include "AliAnalysisDataContainer.h"
51
52 ClassImp(AliAnalysisDataSlot)
53
54 //______________________________________________________________________________
55 AliAnalysisDataSlot::AliAnalysisDataSlot(TClass *type, AliAnalysisTask *task)
56                     :TNamed(), 
57                      fType(type),
58                      fParent(task), 
59                      fContainer(NULL)
60 {
61 // Default constructor.
62    SetTitle(fType->GetName());
63 }
64
65 //______________________________________________________________________________
66 AliAnalysisDataSlot::AliAnalysisDataSlot(const AliAnalysisDataSlot &slot)
67                     :TNamed(slot), 
68                      fType(NULL), 
69                      fParent(slot.fParent), 
70                      fContainer(slot.fContainer)
71 {
72 // Copy ctor.
73    GetType();
74 }                        
75
76 //______________________________________________________________________________
77 AliAnalysisDataSlot& AliAnalysisDataSlot::operator=(const AliAnalysisDataSlot &slot)
78 {
79 // Assignment
80    if (&slot == this) return *this;
81    TNamed::operator=(slot);
82    GetType();
83    fParent = slot.fParent;
84    fContainer = slot.fContainer;   
85    return *this;
86 }
87
88 //______________________________________________________________________________
89 Bool_t AliAnalysisDataSlot::ConnectContainer(AliAnalysisDataContainer *cont)
90 {
91 // Connect the data slot with a given container. The operation will succeed only
92 // if the type defined by the slot inherits from the type enforced by the container.
93 // The error message in case of failure is posted by the caller.
94    if (!cont || !GetType()) return kFALSE;
95    if (!fType->InheritsFrom(cont->GetType())) {
96      cout<<"Data slot of type "<<GetTitle()<<" of task "<<fParent->GetName()<<" cannot be connected to data container "<<cont->GetName()<<" of type "<<cont->GetTitle()<<endl;
97      //AliError(Form("Data slot of type %s of task %s cannot be connected to data container %s of type %s", fType->GetName(), fParent->GetName(), cont->GetName(), cont->GetType()->GetName()));
98       return kFALSE;
99    }   
100    fContainer = cont;
101    return kTRUE;
102 }   
103
104 //______________________________________________________________________________
105 TClass *AliAnalysisDataSlot::GetType() const
106 {
107 // Get class type for this slot.
108    AliAnalysisDataSlot *slot = (AliAnalysisDataSlot*)this;
109    if (!fType) slot->SetType(gROOT->GetClass(fTitle.Data()));
110    if (!fType) printf("AliAnalysisDataSlot: Unknown class: %s\n", GetTitle());
111    return fType;
112 }
113    
114 //______________________________________________________________________________
115 void *AliAnalysisDataSlot::GetBranchAddress(const char *branchname) const
116 {
117 // Retrieve the address for a given branch. One should always test this before
118 // using SetBranchAddress because the address gets set by the first caller.
119 // Call this in MyTask::Init()
120    if (!GetType()) return NULL;
121    if (!fType->InheritsFrom(TTree::Class())) {
122      cout<<"Cannot call GetBranchAddress() for data slot of task "<<fParent->GetName()<<" not pointing to tree-type data"<<endl;
123      //AliFatal(Form("Cannot call GetBranchAddress() for data slot of task %s not pointing to tree-type data", fParent->GetName()));
124       return NULL;
125    }
126    if (!IsDataReady()) {
127      cout<<"Cannot call GetBranchAddress() for data slot of task "<<fParent->GetName()<<" while data is not ready"<<endl;
128      //AliFatal(Form("Cannot call GetBranchAddress() for data slot of task %s while data is not ready", fParent->GetName()));
129       return NULL;
130    }
131    TTree *tree = (TTree*)GetData();
132    TBranch *br = tree->GetBranch(branchname);
133    if (!br) {   
134      cout<<"Branch "<<branchname<<" not found in tree "<<tree->GetName()<<" as input of task "<<fParent->GetName()<<"..."<<endl;
135      //AliFatal(Form("Branch %s not found in tree %s as input of task %s...", branchname, tree->GetName(), fParent->GetName()));
136       return NULL;
137    }
138    return br->GetAddress();
139 }   
140
141 //______________________________________________________________________________
142 Int_t AliAnalysisDataSlot::EnableBranch(const char *bname, TTree *tree)
143 {
144 // Static method to enable recursively a branch in a tree (why this in not in ROOT?)
145    TBranch *branch = tree->GetBranch(bname);
146    Int_t count = 0;
147 //   static Int_t indent = 0;
148    if (!branch) return count;
149 //   TString s;
150 //   for (Int_t i=0; i<indent; i++) s += " ";
151    count++;
152 //   printf("%sbranch %s: kDoNotProcess=%d\n",s.Data(), branch->GetName(), branch->TestBit(kDoNotProcess));
153    branch->SetBit(kDoNotProcess, kFALSE);
154    TIter next(branch->GetListOfBranches());
155    TBranch *branch_sub;
156    // Activate all sub-branches
157 //   indent++;
158    while ((branch_sub=(TBranch*)next())) {
159       count += AliAnalysisDataSlot::EnableBranch(branch_sub->GetName(), tree);
160    }
161 //   indent--;
162    return count;   
163 }   
164
165 //______________________________________________________________________________
166 Bool_t AliAnalysisDataSlot::SetBranchAddress(const char *branchname, void *address)
167 {
168 // Set a branch address for input tree. To be called during MyTask::Init()
169 // only if GetBranchAddress() returns a NULL pointer for a tree-type slot.
170    if (GetBranchAddress(branchname)) {
171       Error("SetBranchAddress","Branch address for %s already set by other task. Call first GetBranchAddress() in %s::ConnectInputData()",branchname, fParent->GetName());
172       return kFALSE;
173    }
174    TTree *tree = (TTree*)GetData();
175    tree->SetBranchAddress(branchname, address);
176    return kTRUE;
177 }   
178       
179 //______________________________________________________________________________
180 TObject *AliAnalysisDataSlot::GetData() const
181 {
182 // Retreives the data from the container if it is ready.
183    if (!fContainer) {
184      cout<<"Data slot of type "<<GetTitle()<<" of task "<<fParent->GetName()<<" has no connected data container"<<endl;
185      //AliError(Form("Data slot of type %s of task %s has no connected data container",fType->GetName(), fParent->GetName()));    
186       return NULL;
187    }
188    if (!fContainer->IsDataReady()) return NULL;
189    return fContainer->GetData();
190 }
191
192 //______________________________________________________________________________
193 Bool_t  AliAnalysisDataSlot::IsDataReady() const
194 {
195 // Check if data for this slot is ready in its container.
196    if (!fContainer) {
197      cout<<"Data slot of type "<<GetTitle()<<" of task "<<fParent->GetName()<<" has no connected data container"<<endl;
198      //AliError(Form("Data slot of type %s of task %s has no connected data container",fType->GetName(), fParent->GetName()));    
199       return kFALSE;
200    }
201    return fContainer->IsDataReady();
202 }
203