Line data Source code
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 :
18 : //-----------------------------------------------------------------------------
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
40 : //-----------------------------------------------------------------------------
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 : using std::cout;
53 : using std::endl;
54 : /// \cond CLASSIMP
55 18 : ClassImp(AliMUONTreeManager)
56 : /// \endcond
57 :
58 : //_____________________________________________________________________________
59 99 : AliMUONTreeManager::AliMUONTreeManager() : TObject()
60 495 : {
61 : /// Default ctor
62 198 : }
63 :
64 : //_____________________________________________________________________________
65 : AliMUONTreeManager::~AliMUONTreeManager()
66 198 : {
67 : /// Dtor
68 297 : }
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 0 : TObjArray* branches = tree.GetListOfBranches();
81 0 : TIter next(branches);
82 : TBranch* branch;
83 : Bool_t error(kFALSE);
84 :
85 0 : while ( ( branch = static_cast<TBranch*>(next()) ) )
86 : {
87 0 : TString bname(branch->GetName());
88 0 : if ( branch->GetAddress() == 0 &&
89 0 : tree.GetBranchStatus(bname.Data()) == 1 )
90 : {
91 0 : AliError(Form("Branch %s has status 1 and no address",bname.Data()));
92 : error = kTRUE;
93 0 : }
94 0 : }
95 :
96 0 : if ( error )
97 : {
98 0 : ShowStatus(tree);
99 : }
100 : #endif
101 :
102 0 : tree.GetEvent(event);
103 0 : }
104 :
105 : //_____________________________________________________________________________
106 : void
107 : AliMUONTreeManager::ShowStatus(TTree& tree) const
108 : {
109 : /// Show main branches status and address
110 0 : TObjArray* branches = tree.GetListOfBranches();
111 0 : TIter next(branches);
112 : TBranch* branch;
113 :
114 0 : while ( ( branch = static_cast<TBranch*>(next()) ) )
115 : {
116 0 : TString bname(branch->GetName());
117 0 : Int_t status = tree.GetBranchStatus(bname.Data());
118 0 : cout << Form("%50s Status %d Address %p",bname.Data(),status,branch->GetAddress()) << endl;
119 0 : }
120 0 : }
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 112 : TString test(GetClassName(tree,pattern,kFALSE));
132 112 : if ( test.Length() == 0 )
133 : {
134 : // not already there
135 56 : TList* userInfo = tree.GetUserInfo();
136 336 : userInfo->Add(new AliMUONObjectPair(new TObjString(pattern),
137 168 : new TObjString(className),
138 : kTRUE,kTRUE));
139 56 : }
140 56 : }
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 112 : AddClassName(tree,branchName,storeClassName);
152 56 : TBranch* branch = tree.Branch(branchName,branchClassName,address,bufferSize,splitLevel);
153 56 : 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 168 : TBranch* branch = tree.GetBranch(branchName);
163 84 : if (branch)
164 : {
165 84 : branch->SetAddress(address);
166 84 : return kTRUE;
167 : }
168 0 : AliError(Form("Did not find branch %s in tree %s",branchName,tree.GetName()));
169 0 : return kFALSE;
170 84 : }
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 46 : TString className(GetClassName(tree,detail,kTRUE));
179 46 : TClass* classPtr = TClass::GetClass(className.Data());
180 23 : if (!classPtr)
181 : {
182 0 : AliError(Form("Could not get class %s",className.Data()));
183 0 : return 0x0;
184 : }
185 46 : return reinterpret_cast<TObject*>(classPtr->New());
186 23 : }
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 16 : TIter next(tree.GetListOfBranches());
205 : TBranch* branch;
206 :
207 84 : while ( ( branch = static_cast<TBranch*>(next()) ) )
208 : {
209 40 : TString bname(branch->GetName());
210 40 : if ( bname.Contains(pattern) )
211 : {
212 48 : tree.SetBranchStatus(Form("%s*",branch->GetName()),1);
213 : }
214 : else
215 : {
216 8 : if ( !branch->GetAddress() )
217 : {
218 12 : tree.SetBranchStatus(Form("%s*",branch->GetName()),0);
219 : }
220 : }
221 20 : }
222 :
223 8 : }
224 :
225 : //_____________________________________________________________________________
226 : TString
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 79 : TIter next(vtree.GetUserInfo());
239 :
240 : TObject* object;
241 :
242 411 : while ( ( object = next() ) )
243 : {
244 110 : AliMUONObjectPair* pair = static_cast<AliMUONObjectPair*>(object);
245 110 : TString key = (static_cast<TObjString*>(pair->First()))->String();
246 110 : TString value = (static_cast<TObjString*>(pair->Second()))->String();
247 220 : if ( key.Contains(pattern,TString::kIgnoreCase) )
248 : {
249 23 : return value;
250 : }
251 394 : }
252 :
253 56 : if ( makeDefault ) return DefaultClassName(tree.GetName(),pattern);
254 :
255 112 : return "";
256 79 : }
257 :
258 : //_____________________________________________________________________________
259 : TString
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 0 : TString name(treeName);
266 0 : TString spattern(pattern);
267 0 : spattern.ToUpper();
268 :
269 0 : if ( name == "TreeH" )
270 : {
271 0 : return "AliMUONHitStoreV1";
272 : }
273 :
274 0 : if ( name == "TreeD" || name == "TreeS" )
275 : {
276 0 : if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1";
277 0 : if ( spattern.Contains("DIGIT") ) return "AliMUONDigitStoreV1";
278 : }
279 :
280 0 : if ( name == "TreeR" )
281 : {
282 0 : if ( spattern.Contains("CLUSTER") ) return "AliMUONClusterStoreV1";
283 0 : if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1";
284 : }
285 :
286 0 : if ( name == "TreeT" )
287 : {
288 0 : if ( spattern.Contains("TRIGGER" ) ) return "AliMUONTriggerTrackStoreV1";
289 0 : if ( spattern.Contains("TRACK") ) return "AliMUONTrackStoreV1";
290 : }
291 :
292 0 : AliError(Form("Do not know how to create default class for tree %s pattern %s",
293 : treeName,pattern));
294 0 : return "";
295 0 : }
296 :
297 :
298 :
299 :
300 :
301 :
302 :
|