]>
Commit | Line | Data |
---|---|---|
de6dbd08 | 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 | ||
3d1463c8 | 18 | //----------------------------------------------------------------------------- |
de6dbd08 | 19 | /// \class AliMUONTreeManager |
20 | /// | |
21 | /// Helper class to handle the relationships TTree<->MUON data containers | |
22 | /// | |
23 | /// The general way of dealing with I/O for MUON is a two stage process : | |
24 | /// | |
25 | /// 1) first get a TTree pointer using the AliLoader mechanism (this is AliRoot | |
26 | /// general) | |
27 | /// | |
28 | /// 2) connect that TTree to a MUON (virtual) data container using | |
29 | /// the container's Connect(TTree&) method (this is MUON specific) | |
30 | /// | |
31 | /// This class helps implementing stage 2 in the relevant store implementations | |
32 | /// | |
33 | /// \see AliMUONVStore | |
34 | /// | |
35 | /// Basically, the relationship Tree<->Store is possible because | |
36 | /// the TreeManager, when creating branches, uses the UserInfo part of the | |
37 | /// TTree to store the relationship branch -> MUON store classname. | |
38 | /// | |
39 | /// \author Laurent Aphecetche, Subatech | |
3d1463c8 | 40 | //----------------------------------------------------------------------------- |
de6dbd08 | 41 | |
42 | #include "AliMUONTreeManager.h" | |
43 | ||
44 | #include "AliLog.h" | |
45 | #include "AliMUONObjectPair.h" | |
46 | #include <TList.h> | |
47 | #include <TObjString.h> | |
48 | #include <TTree.h> | |
49 | #include <TBranch.h> | |
50 | #include <Riostream.h> | |
51 | ||
b80faac0 | 52 | using std::cout; |
53 | using std::endl; | |
de6dbd08 | 54 | /// \cond CLASSIMP |
55 | ClassImp(AliMUONTreeManager) | |
56 | /// \endcond | |
57 | ||
58 | //_____________________________________________________________________________ | |
59 | AliMUONTreeManager::AliMUONTreeManager() : TObject() | |
60 | { | |
61 | /// Default ctor | |
62 | } | |
63 | ||
64 | //_____________________________________________________________________________ | |
65 | AliMUONTreeManager::~AliMUONTreeManager() | |
66 | { | |
67 | /// Dtor | |
68 | } | |
69 | ||
70 | //_____________________________________________________________________________ | |
71 | void | |
72 | AliMUONTreeManager::GetEvent(TTree& tree, Int_t event) const | |
73 | { | |
74 | /// Equivalent to tree.GetEvent(event) is NDEBUG is not defined, | |
75 | /// otherwise insure that selected branches have a non-zero address | |
76 | /// (the contrary indicating we'll get a memory leak when reading the | |
77 | /// tree). | |
78 | ||
79 | #ifndef NDEBUG | |
80 | TObjArray* branches = tree.GetListOfBranches(); | |
81 | TIter next(branches); | |
82 | TBranch* branch; | |
83 | Bool_t error(kFALSE); | |
84 | ||
85 | while ( ( branch = static_cast<TBranch*>(next()) ) ) | |
86 | { | |
87 | TString bname(branch->GetName()); | |
88 | if ( branch->GetAddress() == 0 && | |
89 | tree.GetBranchStatus(bname.Data()) == 1 ) | |
90 | { | |
91 | AliError(Form("Branch %s has status 1 and no address",bname.Data())); | |
92 | error = kTRUE; | |
93 | } | |
94 | } | |
95 | ||
96 | if ( error ) | |
97 | { | |
98 | ShowStatus(tree); | |
99 | } | |
100 | #endif | |
101 | ||
102 | tree.GetEvent(event); | |
103 | } | |
104 | ||
105 | //_____________________________________________________________________________ | |
106 | void | |
107 | AliMUONTreeManager::ShowStatus(TTree& tree) const | |
108 | { | |
109 | /// Show main branches status and address | |
110 | TObjArray* branches = tree.GetListOfBranches(); | |
111 | TIter next(branches); | |
112 | TBranch* branch; | |
113 | ||
114 | while ( ( branch = static_cast<TBranch*>(next()) ) ) | |
115 | { | |
116 | TString bname(branch->GetName()); | |
117 | Int_t status = tree.GetBranchStatus(bname.Data()); | |
118 | cout << Form("%50s Status %d Address %p",bname.Data(),status,branch->GetAddress()) << endl; | |
119 | } | |
120 | } | |
121 | ||
122 | //_____________________________________________________________________________ | |
123 | void | |
124 | AliMUONTreeManager::AddClassName(TTree& tree, const char* pattern, | |
125 | const char* className) const | |
126 | { | |
127 | /// Adds a association (pattern,className) to the UserInfo() of tree | |
128 | /// It is mandatory to use this method in MakeBranches(), as this is the key | |
129 | /// to get an automatic container creation from a tree. | |
130 | ||
131 | TString test(GetClassName(tree,pattern,kFALSE)); | |
132 | if ( test.Length() == 0 ) | |
133 | { | |
134 | // not already there | |
135 | TList* userInfo = tree.GetUserInfo(); | |
136 | userInfo->Add(new AliMUONObjectPair(new TObjString(pattern), | |
137 | new TObjString(className), | |
138 | kTRUE,kTRUE)); | |
139 | } | |
140 | } | |
141 | ||
142 | //_____________________________________________________________________________ | |
143 | Bool_t | |
144 | AliMUONTreeManager::MakeBranch(TTree& tree, const char* storeClassName, | |
145 | const char* branchClassName, | |
146 | const char* branchName, | |
147 | void* address, | |
148 | Int_t bufferSize, Int_t splitLevel) const | |
149 | { | |
150 | /// Create a branch in the tree | |
151 | AddClassName(tree,branchName,storeClassName); | |
152 | TBranch* branch = tree.Branch(branchName,branchClassName,address,bufferSize,splitLevel); | |
153 | return ( branch != 0x0 ); | |
154 | } | |
155 | ||
156 | //_____________________________________________________________________________ | |
157 | Bool_t | |
158 | AliMUONTreeManager::SetAddress(TTree& tree, const char* branchName, | |
159 | void* address) const | |
160 | { | |
161 | /// Set the address for one branch | |
162 | TBranch* branch = tree.GetBranch(branchName); | |
163 | if (branch) | |
164 | { | |
165 | branch->SetAddress(address); | |
166 | return kTRUE; | |
167 | } | |
168 | AliError(Form("Did not find branch %s in tree %s",branchName,tree.GetName())); | |
169 | return kFALSE; | |
170 | } | |
171 | ||
172 | //_____________________________________________________________________________ | |
173 | TObject* | |
174 | AliMUONTreeManager::CreateObject(const TTree& tree, const char* detail) const | |
175 | { | |
176 | /// Object creation from tree, using | |
177 | /// the (pattern,className) pairs stored in the UserInfo() of TTree. | |
178 | TString className(GetClassName(tree,detail,kTRUE)); | |
179 | TClass* classPtr = TClass::GetClass(className.Data()); | |
180 | if (!classPtr) | |
181 | { | |
182 | AliError(Form("Could not get class %s",className.Data())); | |
183 | return 0x0; | |
184 | } | |
185 | return reinterpret_cast<TObject*>(classPtr->New()); | |
186 | } | |
187 | ||
188 | //_____________________________________________________________________________ | |
189 | void | |
190 | AliMUONTreeManager::UpdateBranchStatuses(TTree& tree, const char* pattern) const | |
191 | { | |
192 | /// Loop over tree branches and set their status if their name matches | |
193 | /// the pattern : | |
194 | /// - zero if branch address is null and | |
195 | /// - one otherwise | |
196 | /// This will avoid memory leak, if we set the address to only part | |
197 | /// of the branches before doing a tree.GetEvent(i) | |
198 | /// | |
199 | /// WARNING : this is a time consuming operation, as we loop over branches | |
200 | /// at least twice (one here, and the TTree::SetBranchStatus is itself | |
201 | /// a loop). So use only when necessary. | |
202 | /// | |
203 | ||
204 | TIter next(tree.GetListOfBranches()); | |
205 | TBranch* branch; | |
206 | ||
207 | while ( ( branch = static_cast<TBranch*>(next()) ) ) | |
208 | { | |
209 | TString bname(branch->GetName()); | |
210 | if ( bname.Contains(pattern) ) | |
211 | { | |
212 | tree.SetBranchStatus(Form("%s*",branch->GetName()),1); | |
213 | } | |
214 | else | |
215 | { | |
216 | if ( !branch->GetAddress() ) | |
217 | { | |
218 | tree.SetBranchStatus(Form("%s*",branch->GetName()),0); | |
219 | } | |
220 | } | |
221 | } | |
222 | ||
223 | } | |
224 | ||
225 | //_____________________________________________________________________________ | |
d725888e | 226 | TString |
de6dbd08 | 227 | AliMUONTreeManager::GetClassName(const TTree& tree, const char* pattern, |
228 | Bool_t makeDefault) const | |
229 | { | |
230 | /// Find out, using the TTree::UserInfo, the classname corresponding to | |
231 | /// pattern. | |
232 | /// If makeDefault=true and we cannot find the pattern in the UserInfo, | |
233 | /// we return DefaultClassName(pattern) | |
234 | /// | |
235 | ||
236 | TTree& vtree = const_cast<TTree&>(tree); // not pretty, but the GetUserInfo is not const... | |
237 | ||
238 | TIter next(vtree.GetUserInfo()); | |
239 | ||
240 | TObject* object; | |
241 | ||
242 | while ( ( object = next() ) ) | |
243 | { | |
244 | AliMUONObjectPair* pair = static_cast<AliMUONObjectPair*>(object); | |
245 | TString key = (static_cast<TObjString*>(pair->First()))->String(); | |
246 | TString value = (static_cast<TObjString*>(pair->Second()))->String(); | |
247 | if ( key.Contains(pattern,TString::kIgnoreCase) ) | |
248 | { | |
d725888e | 249 | return value; |
de6dbd08 | 250 | } |
251 | } | |
252 | ||
253 | if ( makeDefault ) return DefaultClassName(tree.GetName(),pattern); | |
254 | ||
4e08d74e | 255 | return ""; |
de6dbd08 | 256 | } |
257 | ||
258 | //_____________________________________________________________________________ | |
d725888e | 259 | TString |
de6dbd08 | 260 | AliMUONTreeManager::DefaultClassName(const char* treeName, const char* pattern) const |
261 | { | |
262 | /// For backward compatibility only. Decides, based on the tree name and a | |
263 | /// pattern, which store class should be used. | |
264 | ||
265 | TString name(treeName); | |
266 | TString spattern(pattern); | |
267 | spattern.ToUpper(); | |
268 | ||
269 | if ( name == "TreeH" ) | |
270 | { | |
271 | return "AliMUONHitStoreV1"; | |
272 | } | |
273 | ||
274 | if ( name == "TreeD" || name == "TreeS" ) | |
275 | { | |
276 | if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1"; | |
277 | if ( spattern.Contains("DIGIT") ) return "AliMUONDigitStoreV1"; | |
278 | } | |
279 | ||
280 | if ( name == "TreeR" ) | |
281 | { | |
282 | if ( spattern.Contains("CLUSTER") ) return "AliMUONClusterStoreV1"; | |
283 | if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1"; | |
284 | } | |
285 | ||
286 | if ( name == "TreeT" ) | |
287 | { | |
288 | if ( spattern.Contains("TRIGGER" ) ) return "AliMUONTriggerTrackStoreV1"; | |
289 | if ( spattern.Contains("TRACK") ) return "AliMUONTrackStoreV1"; | |
290 | } | |
291 | ||
292 | AliError(Form("Do not know how to create default class for tree %s pattern %s", | |
293 | treeName,pattern)); | |
294 | return ""; | |
295 | } | |
296 | ||
297 | ||
298 | ||
299 | ||
300 | ||
301 | ||
302 |