- Adding check and flagging for HG present
[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 /// \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