1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 //-----------------------------------------------------------------------------
19 /// \class AliMUONTreeManager
21 /// Helper class to handle the relationships TTree<->MUON data containers
23 /// The general way of dealing with I/O for MUON is a two stage process :
25 /// 1) first get a TTree pointer using the AliLoader mechanism (this is AliRoot
28 /// 2) connect that TTree to a MUON (virtual) data container using
29 /// the container's Connect(TTree&) method (this is MUON specific)
31 /// This class helps implementing stage 2 in the relevant store implementations
33 /// \see AliMUONVStore
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.
39 /// \author Laurent Aphecetche, Subatech
40 //-----------------------------------------------------------------------------
42 #include "AliMUONTreeManager.h"
45 #include "AliMUONObjectPair.h"
47 #include <TObjString.h>
50 #include <Riostream.h>
53 ClassImp(AliMUONTreeManager)
56 //_____________________________________________________________________________
57 AliMUONTreeManager::AliMUONTreeManager() : TObject()
62 //_____________________________________________________________________________
63 AliMUONTreeManager::~AliMUONTreeManager()
68 //_____________________________________________________________________________
70 AliMUONTreeManager::GetEvent(TTree& tree, Int_t event) const
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
78 TObjArray* branches = tree.GetListOfBranches();
83 while ( ( branch = static_cast<TBranch*>(next()) ) )
85 TString bname(branch->GetName());
86 if ( branch->GetAddress() == 0 &&
87 tree.GetBranchStatus(bname.Data()) == 1 )
89 AliError(Form("Branch %s has status 1 and no address",bname.Data()));
100 tree.GetEvent(event);
103 //_____________________________________________________________________________
105 AliMUONTreeManager::ShowStatus(TTree& tree) const
107 /// Show main branches status and address
108 TObjArray* branches = tree.GetListOfBranches();
109 TIter next(branches);
112 while ( ( branch = static_cast<TBranch*>(next()) ) )
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;
120 //_____________________________________________________________________________
122 AliMUONTreeManager::AddClassName(TTree& tree, const char* pattern,
123 const char* className) const
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.
129 TString test(GetClassName(tree,pattern,kFALSE));
130 if ( test.Length() == 0 )
133 TList* userInfo = tree.GetUserInfo();
134 userInfo->Add(new AliMUONObjectPair(new TObjString(pattern),
135 new TObjString(className),
140 //_____________________________________________________________________________
142 AliMUONTreeManager::MakeBranch(TTree& tree, const char* storeClassName,
143 const char* branchClassName,
144 const char* branchName,
146 Int_t bufferSize, Int_t splitLevel) const
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 );
154 //_____________________________________________________________________________
156 AliMUONTreeManager::SetAddress(TTree& tree, const char* branchName,
159 /// Set the address for one branch
160 TBranch* branch = tree.GetBranch(branchName);
163 branch->SetAddress(address);
166 AliError(Form("Did not find branch %s in tree %s",branchName,tree.GetName()));
170 //_____________________________________________________________________________
172 AliMUONTreeManager::CreateObject(const TTree& tree, const char* detail) const
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());
180 AliError(Form("Could not get class %s",className.Data()));
183 return reinterpret_cast<TObject*>(classPtr->New());
186 //_____________________________________________________________________________
188 AliMUONTreeManager::UpdateBranchStatuses(TTree& tree, const char* pattern) const
190 /// Loop over tree branches and set their status if their name matches
192 /// - zero if branch address is null and
194 /// This will avoid memory leak, if we set the address to only part
195 /// of the branches before doing a tree.GetEvent(i)
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.
202 TIter next(tree.GetListOfBranches());
205 while ( ( branch = static_cast<TBranch*>(next()) ) )
207 TString bname(branch->GetName());
208 if ( bname.Contains(pattern) )
210 tree.SetBranchStatus(Form("%s*",branch->GetName()),1);
214 if ( !branch->GetAddress() )
216 tree.SetBranchStatus(Form("%s*",branch->GetName()),0);
223 //_____________________________________________________________________________
225 AliMUONTreeManager::GetClassName(const TTree& tree, const char* pattern,
226 Bool_t makeDefault) const
228 /// Find out, using the TTree::UserInfo, the classname corresponding to
230 /// If makeDefault=true and we cannot find the pattern in the UserInfo,
231 /// we return DefaultClassName(pattern)
234 TTree& vtree = const_cast<TTree&>(tree); // not pretty, but the GetUserInfo is not const...
236 TIter next(vtree.GetUserInfo());
240 while ( ( object = next() ) )
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) )
251 if ( makeDefault ) return DefaultClassName(tree.GetName(),pattern);
256 //_____________________________________________________________________________
258 AliMUONTreeManager::DefaultClassName(const char* treeName, const char* pattern) const
260 /// For backward compatibility only. Decides, based on the tree name and a
261 /// pattern, which store class should be used.
263 TString name(treeName);
264 TString spattern(pattern);
267 if ( name == "TreeH" )
269 return "AliMUONHitStoreV1";
272 if ( name == "TreeD" || name == "TreeS" )
274 if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1";
275 if ( spattern.Contains("DIGIT") ) return "AliMUONDigitStoreV1";
278 if ( name == "TreeR" )
280 if ( spattern.Contains("CLUSTER") ) return "AliMUONClusterStoreV1";
281 if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1";
284 if ( name == "TreeT" )
286 if ( spattern.Contains("TRIGGER" ) ) return "AliMUONTriggerTrackStoreV1";
287 if ( spattern.Contains("TRACK") ) return "AliMUONTrackStoreV1";
290 AliError(Form("Do not know how to create default class for tree %s pattern %s",