Make the Scan method public
[u/mrichter/AliRoot.git] / MUON / AliMUONTreeManager.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
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 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 //_____________________________________________________________________________
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   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     {
249       return value;
250     }
251   }
252   
253   if ( makeDefault ) return DefaultClassName(tree.GetName(),pattern);
254   
255   return "";
256 }
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   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