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>
55 ClassImp(AliMUONTreeManager)
58 //_____________________________________________________________________________
59 AliMUONTreeManager::AliMUONTreeManager() : TObject()
64 //_____________________________________________________________________________
65 AliMUONTreeManager::~AliMUONTreeManager()
70 //_____________________________________________________________________________
72 AliMUONTreeManager::GetEvent(TTree& tree, Int_t event) const
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
80 TObjArray* branches = tree.GetListOfBranches();
85 while ( ( branch = static_cast<TBranch*>(next()) ) )
87 TString bname(branch->GetName());
88 if ( branch->GetAddress() == 0 &&
89 tree.GetBranchStatus(bname.Data()) == 1 )
91 AliError(Form("Branch %s has status 1 and no address",bname.Data()));
102 tree.GetEvent(event);
105 //_____________________________________________________________________________
107 AliMUONTreeManager::ShowStatus(TTree& tree) const
109 /// Show main branches status and address
110 TObjArray* branches = tree.GetListOfBranches();
111 TIter next(branches);
114 while ( ( branch = static_cast<TBranch*>(next()) ) )
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;
122 //_____________________________________________________________________________
124 AliMUONTreeManager::AddClassName(TTree& tree, const char* pattern,
125 const char* className) const
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.
131 TString test(GetClassName(tree,pattern,kFALSE));
132 if ( test.Length() == 0 )
135 TList* userInfo = tree.GetUserInfo();
136 userInfo->Add(new AliMUONObjectPair(new TObjString(pattern),
137 new TObjString(className),
142 //_____________________________________________________________________________
144 AliMUONTreeManager::MakeBranch(TTree& tree, const char* storeClassName,
145 const char* branchClassName,
146 const char* branchName,
148 Int_t bufferSize, Int_t splitLevel) const
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 );
156 //_____________________________________________________________________________
158 AliMUONTreeManager::SetAddress(TTree& tree, const char* branchName,
161 /// Set the address for one branch
162 TBranch* branch = tree.GetBranch(branchName);
165 branch->SetAddress(address);
168 AliError(Form("Did not find branch %s in tree %s",branchName,tree.GetName()));
172 //_____________________________________________________________________________
174 AliMUONTreeManager::CreateObject(const TTree& tree, const char* detail) const
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());
182 AliError(Form("Could not get class %s",className.Data()));
185 return reinterpret_cast<TObject*>(classPtr->New());
188 //_____________________________________________________________________________
190 AliMUONTreeManager::UpdateBranchStatuses(TTree& tree, const char* pattern) const
192 /// Loop over tree branches and set their status if their name matches
194 /// - zero if branch address is null and
196 /// This will avoid memory leak, if we set the address to only part
197 /// of the branches before doing a tree.GetEvent(i)
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.
204 TIter next(tree.GetListOfBranches());
207 while ( ( branch = static_cast<TBranch*>(next()) ) )
209 TString bname(branch->GetName());
210 if ( bname.Contains(pattern) )
212 tree.SetBranchStatus(Form("%s*",branch->GetName()),1);
216 if ( !branch->GetAddress() )
218 tree.SetBranchStatus(Form("%s*",branch->GetName()),0);
225 //_____________________________________________________________________________
227 AliMUONTreeManager::GetClassName(const TTree& tree, const char* pattern,
228 Bool_t makeDefault) const
230 /// Find out, using the TTree::UserInfo, the classname corresponding to
232 /// If makeDefault=true and we cannot find the pattern in the UserInfo,
233 /// we return DefaultClassName(pattern)
236 TTree& vtree = const_cast<TTree&>(tree); // not pretty, but the GetUserInfo is not const...
238 TIter next(vtree.GetUserInfo());
242 while ( ( object = next() ) )
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) )
253 if ( makeDefault ) return DefaultClassName(tree.GetName(),pattern);
258 //_____________________________________________________________________________
260 AliMUONTreeManager::DefaultClassName(const char* treeName, const char* pattern) const
262 /// For backward compatibility only. Decides, based on the tree name and a
263 /// pattern, which store class should be used.
265 TString name(treeName);
266 TString spattern(pattern);
269 if ( name == "TreeH" )
271 return "AliMUONHitStoreV1";
274 if ( name == "TreeD" || name == "TreeS" )
276 if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1";
277 if ( spattern.Contains("DIGIT") ) return "AliMUONDigitStoreV1";
280 if ( name == "TreeR" )
282 if ( spattern.Contains("CLUSTER") ) return "AliMUONClusterStoreV1";
283 if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1";
286 if ( name == "TreeT" )
288 if ( spattern.Contains("TRIGGER" ) ) return "AliMUONTriggerTrackStoreV1";
289 if ( spattern.Contains("TRACK") ) return "AliMUONTrackStoreV1";
292 AliError(Form("Do not know how to create default class for tree %s pattern %s",