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