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 **************************************************************************/
16 // $Id: AliMergeableCollection.cxx 50593 2011-07-14 17:42:28Z martinez $
19 /// A mergeable object container.
21 /// For each tuple (key1,key2,..,keyN) a (hash)list of mergeable objects is associated.
22 /// Note that key1, key2 (optional), ..., keyN (optional) are strings.
23 /// Those strings should not contain "/" themselves.
25 /// More helper functions might be added in the future (e.g. Project, etc...)
27 #include "AliMergeableCollection.h"
31 ClassImp(AliMergeableCollection)
34 #include "Riostream.h"
40 #include "THashList.h"
41 #include "THnSparse.h"
44 #include "TObjArray.h"
45 #include "TObjString.h"
54 //_____________________________________________________________________________
55 AliMergeableCollection::AliMergeableCollection(const char* name, const char* title)
56 : TFolder(name,title), fMap(0x0), fMustShowEmptyObject(0), fMapVersion(0), fMessages()
61 //_____________________________________________________________________________
62 AliMergeableCollection::~AliMergeableCollection()
64 /// dtor. Note that the map is owner
68 //_____________________________________________________________________________
70 AliMergeableCollection::Adopt(TObject* obj)
72 /// Adopt a given object at top level (i.e. no key)
73 return InternalAdopt("",obj);
76 //_____________________________________________________________________________
78 AliMergeableCollection::Adopt(const char* identifier, TObject* obj)
80 /// Adopt a given object, and associate it with pair key
81 TString sidentifier(identifier);
82 if ( ! sidentifier.IsNull() ){
83 if ( ! sidentifier.EndsWith("/") ) sidentifier.Append("/");
84 if ( ! sidentifier.BeginsWith("/") ) sidentifier.Prepend("/");
86 return InternalAdopt(sidentifier.Data(),obj);
89 //_____________________________________________________________________________
90 Bool_t AliMergeableCollection::Attach(AliMergeableCollection* mc, const char* identifier, Bool_t pruneFirstIfAlreadyExists)
92 /// Attach an already existing mergeable collection to this one.
93 /// It is attached at level identifier/
94 /// We take ownership of mc
95 /// If identifier is already existing we kill it if pruneFirstIfAlreadyExists is kTRUE
96 /// (and attach mc) otherwise we return kFALSE (and do *not* attach mc)
98 THashList* hlist = dynamic_cast<THashList*>(Map()->GetValue(identifier));
102 if (!pruneFirstIfAlreadyExists)
104 AliError(Form("%s already exist. Will not overwrite it.",identifier));
109 Int_t n = Prune(identifier);
112 AliError(Form("Could not prune pre-existing %s",identifier));
118 TIter next(mc->fMap);
121 while ( ( str = static_cast<TObjString*>(next())) )
123 THashList* hl = dynamic_cast<THashList*>(mc->Map()->GetValue(str->String()));
124 TString newid(Form("/%s%s",identifier,str->String().Data()));
125 newid.ReplaceAll("//","/");
126 Map()->Add(new TObjString(newid.Data()),hl);
132 //_____________________________________________________________________________
133 void AliMergeableCollection::Browse(TBrowser* b)
135 /// Create a TFolder structure pointing to our objects, so we
138 if ( !fFolders ) return;
140 TObjArray* ids = SortAllIdentifiers();
141 TIter nextIdentifier(ids);
144 while ( ( str = static_cast<TObjString*>(nextIdentifier()) ) )
146 TObjArray* parts = str->String().Tokenize("/");
148 TIter nextPart(parts);
149 TFolder* base = this;
151 while ( ( s = static_cast<TObjString*>(nextPart())))
153 TFolder* f = static_cast<TFolder*>(base->TFolder::FindObject(s->String()));
156 f = new TFolder(s->String(),"");
163 TList* list = CreateListOfObjectNames(str->String());
167 TIter nextObject(list);
168 while ( ( oname = static_cast<TObjString*>(nextObject())) )
170 TObject* o = GetObject(str->String(),oname->String());
176 AliError("got list=0x0");
181 TList* top = CreateListOfKeys(0);
185 while ( ( stop = static_cast<TObjString*>(nextTop())) )
187 b->Add(TFolder::FindObject(stop->String()));
195 //_____________________________________________________________________________
196 void AliMergeableCollection::ClearMessages()
198 /// clear pending messages
202 //_____________________________________________________________________________
204 AliMergeableCollection::CreateIterator(Bool_t direction) const
206 /// Create an iterator (must be deleted by the client)
207 return fMap ? new AliMergeableCollectionIterator(this,direction) : 0x0;
210 //_____________________________________________________________________________
211 AliMergeableCollection*
212 AliMergeableCollection::Clone(const char* name) const
214 /// Clone this collection.
215 /// We loose the messages.
217 AliMergeableCollection* newone = new AliMergeableCollection(name,GetTitle());
219 newone->fMap = static_cast<TMap*>(fMap->Clone());
220 newone->fMustShowEmptyObject = fMustShowEmptyObject;
221 newone->fMapVersion = fMapVersion;
226 //_____________________________________________________________________________
228 AliMergeableCollection::Delete(Option_t*)
230 /// Delete all the objects
236 //_____________________________________________________________________________
238 AliMergeableCollection::FindObject(const char* fullIdentifier) const
240 /// Find an object by its full identifier.
242 return GetObject(fullIdentifier);
245 //_____________________________________________________________________________
247 AliMergeableCollection::FindObject(const TObject *object) const
250 AliWarning("This method is awfully inefficient. Please improve it or use FindObject(const char*)");
251 TIter next(CreateIterator());
253 while ( ( obj=next() ) )
255 if ( obj->IsEqual(object) ) return obj;
261 //_____________________________________________________________________________
263 AliMergeableCollection::CreateListOfKeys(Int_t index) const
265 /// Create the list of keys at level index
267 TList* list = new TList;
268 list->SetOwner(kTRUE);
270 TObjArray* ids = SortAllIdentifiers();
274 while ( ( str = static_cast<TObjString*>(next()) ) )
276 TString oneid = GetKey(str->String().Data(),index,kFALSE);
277 if (oneid.Length()>0 && !list->Contains(oneid))
279 list->Add(new TObjString(oneid));
287 //_____________________________________________________________________________
289 AliMergeableCollection::CreateListOfObjectNames(const char* identifier) const
291 /// Create list of object names for /key1/key2/key...
292 /// Returned list must be deleted by client
294 TList* listOfNames = new TList;
295 listOfNames->SetOwner(kTRUE);
300 while ( ( str = static_cast<TObjString*>(next()) ) )
302 TString currIdentifier = str->String();
303 if ( currIdentifier.CompareTo(identifier) ) continue;
305 THashList* list = static_cast<THashList*>(Map()->GetValue(identifier));
307 TIter nextObject(list);
310 while ( ( obj = nextObject() ) )
312 listOfNames->Add(new TObjString(obj->GetName()));
320 //_____________________________________________________________________________
322 AliMergeableCollection::GetIdentifier(const char* fullIdentifier) const
324 /// Extract the identifier from the fullIdentifier
328 Int_t n = TString(fullIdentifier).CountChar('/')-1;
330 for (Int_t i=0; i < n; ++i)
333 identifier += InternalDecode(fullIdentifier,i);
339 //_____________________________________________________________________________
341 AliMergeableCollection::GetKey(const char* identifier, Int_t index, Bool_t idContainsObjName) const
343 /// Extract the index element of the key pair from the fullIdentifier
345 if ( ! idContainsObjName )
347 TString sidentifier(identifier);
348 sidentifier.Append("/dummy");
349 return InternalDecode(sidentifier.Data(),index);
352 return InternalDecode(identifier,index);
355 //_____________________________________________________________________________
357 AliMergeableCollection::GetObjectName(const char* fullIdentifier) const
359 /// Extract the object name from an identifier
361 return InternalDecode(fullIdentifier,-1);
364 //_____________________________________________________________________________
366 AliMergeableCollection::Histo(const char* fullIdentifier) const
368 /// Get histogram key1/key2/.../objectName:action
369 /// action is used for 2D histograms :
370 /// might be px for projection along x-axis
371 /// py for projection along y-axis
372 /// pfx for profile along x-axis
373 /// pfy for profile along y-axis
375 TString sfullIdentifier(fullIdentifier);
377 TString fullIdWithoutAction(fullIdentifier);
380 if ( sfullIdentifier.First(':') != kNPOS )
382 TObjArray* arr = sfullIdentifier.Tokenize(":");
384 fullIdWithoutAction = static_cast<TObjString*>(arr->At(0))->String();
386 if ( arr->GetLast() > 0 )
388 action = static_cast<TObjString*>(arr->At(1))->String();
395 Int_t nslashes = sfullIdentifier.CountChar('/');
401 o = GetObject("", fullIdWithoutAction);
405 o = GetObject(GetIdentifier(fullIdWithoutAction).Data(), GetObjectName(fullIdWithoutAction));
408 return HistoWithAction(fullIdWithoutAction.Data(),o,action);
411 //_____________________________________________________________________________
413 AliMergeableCollection::Histo(const char* identifier,
414 const char* objectName) const
416 TObject* o = GetObject(identifier,objectName);
418 TObjArray* arr = TString(objectName).Tokenize(":");
421 if ( arr->GetLast() > 0 )
423 action = static_cast<TObjString*>(arr->At(1))->String();
429 return HistoWithAction(identifier,o,action);
433 //_____________________________________________________________________________
435 AliMergeableCollection::HistoWithAction(const char* identifier, TObject* o, const TString& action) const
437 /// Convert o to an histogram if possible, applying a given action if there
441 if (!o->InheritsFrom("TH1"))
443 AliError(Form("%s is not an histogram",o->GetName()));
447 TH2* h2 = dynamic_cast<TH2*>(o);
451 if ( action == "PX" )
453 return h2->ProjectionX(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
455 if ( action == "PY" )
457 return h2->ProjectionY(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
459 if ( action == "PFX" )
461 return h2->ProfileX(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
463 if ( action == "PFY" )
465 return h2->ProfileY(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
469 return static_cast<TH1*>(o);
473 //_____________________________________________________________________________
475 AliMergeableCollection::GetObject(const char* fullIdentifier) const
477 /// Get object key1/key2/.../objectName
478 /// Note that no action is allowed for generic objects (only for histograms,
479 /// see Histo() methods)
481 TString sfullIdentifier(fullIdentifier);
483 Int_t nslashes = sfullIdentifier.CountChar('/');
487 return GetObject("", sfullIdentifier);
491 return GetObject(GetIdentifier(fullIdentifier).Data(), GetObjectName(fullIdentifier));
496 //_____________________________________________________________________________
498 AliMergeableCollection::GetObject(const char* identifier,
499 const char* objectName) const
501 /// Get object for (identifier,objectName) triplet
503 TString sidentifier(identifier);
504 if ( ! sidentifier.IsNull() ) {
505 if ( ! sidentifier.BeginsWith("/") ) sidentifier.Prepend("/");
506 if ( ! sidentifier.EndsWith("/") ) sidentifier.Append("/");
508 return InternalObject(sidentifier.Data(),objectName);
511 //_____________________________________________________________________________
512 TObject* AliMergeableCollection::GetSum(const char* idPattern) const
515 /// The pattern must be in the form:
516 /// /key1_1,key1_2,.../key2_1,key2_2,.../.../objectName_1,objectName_2...
517 /// The logical or between patterns separated by commas is taken
518 /// Exact match is required for keys and objectNames
520 TObject* sumObject = 0x0;
522 // Build array of lists of pattern
523 TString idPatternString(idPattern);
524 TObjArray* keyList = idPatternString.Tokenize("/");
525 TObjArray keyMatrix(keyList->GetEntries());
526 keyMatrix.SetOwner();
527 for ( Int_t ikey=0; ikey<keyList->GetEntries(); ikey++ ) {
528 TObjArray* subKeyList = ((TObjString*)keyList->At(ikey))->GetString().Tokenize(",");
529 keyMatrix.AddAt(subKeyList, ikey);
533 TString debugMsg = "Adding objects:";
536 // First handle the keys
540 while ( ( str = static_cast<TObjString*>(next()) ) )
542 TString identifier = str->String();
544 Bool_t listMatchPattern = kTRUE;
545 for ( Int_t ikey=0; ikey<keyMatrix.GetEntries()-1; ikey++ ) {
546 TString currKey = GetKey(identifier, ikey, kFALSE);
547 Bool_t matchKey = kFALSE;
548 TObjArray* subKeyList = static_cast<TObjArray*> ( keyMatrix.At(ikey) );
549 for ( Int_t isub=0; isub<subKeyList->GetEntries(); isub++ ) {
550 TString subKeyString = static_cast<TObjString*> (subKeyList->At(isub))->GetString();
551 if ( currKey == subKeyString ) {
555 } // loop on the list of patterns of each key
557 listMatchPattern = kFALSE;
560 } // loop on keys in the idPattern
561 if ( ! listMatchPattern ) continue;
565 // Then handle the object name
567 THashList* list = static_cast<THashList*>(Map()->GetValue(identifier.Data()));
572 while ( ( obj = nextObj()) )
574 TString currKey = obj->GetName();
575 Bool_t matchKey = kFALSE;
576 TObjArray* subKeyList = static_cast<TObjArray*> ( keyMatrix.Last() );
577 for ( Int_t isub=0; isub<subKeyList->GetEntries(); isub++ ) {
578 TString subKeyString = static_cast<TObjString*> (subKeyList->At(isub))->GetString();
579 if ( currKey == subKeyString ) {
584 if ( ! matchKey ) continue;
585 if ( ! sumObject ) sumObject = obj->Clone();
586 else MergeObject(sumObject, obj);
587 debugMsg += Form(" %s%s",identifier.Data(),obj->GetName());
588 } // loop on objects in list
589 } // loop on identifiers in map
591 AliDebug(1,debugMsg.Data());
596 //_____________________________________________________________________________
597 Bool_t AliMergeableCollection::InternalAdopt(const char* identifier, TObject* obj)
603 Error("Adopt","Cannot adopt a null object");
607 if ( ! obj->IsA()->InheritsFrom(TObject::Class()) ||
608 ! obj->IsA()->GetMethodWithPrototype("Merge", "TCollection*") ) {
609 Error("Adopt","Cannot adopt an object which is not mergeable!");
612 THashList* hlist = 0x0;
614 hlist = static_cast<THashList*>(Map()->GetValue(identifier));
618 hlist = new THashList;
619 hlist->SetOwner(kTRUE);
620 Map()->Add(new TObjString(identifier),hlist);
621 hlist->SetName(identifier);
624 TObject* existingObj = hlist->FindObject(obj->GetName());
628 AliError(Form("Cannot adopt an already existing object : %s -> %s",identifier,existingObj->GetName()));
632 if ( obj->IsA()->InheritsFrom(TH1::Class()) ) (static_cast<TH1*> ( obj ))->SetDirectory(0);
636 // invalidate the TFolder structure, if any, so it will
637 // be recomputed next time Browse() is called
645 //_____________________________________________________________________________
647 AliMergeableCollection::InternalDecode(const char* identifier, Int_t index) const
649 /// Extract the index-th element of the identifier (/key1/key2/.../keyN/objectName)
650 /// object is index=-1 (i.e. last)
652 if ( strlen(identifier) > 0 && identifier[0] != '/' )
654 AliError(Form("identifier %s is malformed (should start with /)",identifier));
658 std::vector<Int_t> splitIndex;
661 TString sidentifier(identifier);
663 while (start < sidentifier.Length())
665 Int_t pos = sidentifier.Index('/', start);
666 if (pos == kNPOS) break;
667 splitIndex.push_back(pos);
671 Int_t nkeys = splitIndex.size() - 1;
673 if ( index >= nkeys )
675 AliError(Form("Requiring index %i of identifier %s which only have %i",index, identifier, nkeys));
681 return sidentifier(splitIndex.back()+1,sidentifier.Length()-splitIndex.back()-1);
684 return sidentifier(splitIndex[index]+1,splitIndex[index+1]-splitIndex[index]-1);
687 //_____________________________________________________________________________
689 AliMergeableCollection::InternalObject(const char* identifier,
690 const char* objectName) const
692 /// Get object for (identifier,objectName)
699 THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier));
702 TString msg(Form("Did not find hashlist for identifier=%s dir=%s",identifier,gDirectory ? gDirectory->GetName() : "" ));
703 fMessages[msg.Data()]++;
707 TObject* obj = hlist->FindObject(objectName);
710 TString msg(Form("Did not find objectName=%s in %s",objectName,identifier));
711 fMessages[msg.Data()]++;
717 //_____________________________________________________________________________
718 Bool_t AliMergeableCollection::IsEmptyObject(TObject* obj) const
720 /// Check if object is empty
721 /// (done only for TH1, so far)
723 if ( obj->IsA()->InheritsFrom(TH1::Class()) ) {
724 TH1* histo = static_cast<TH1*> (obj);
725 if ( histo->GetEntries() == 0 ) return kTRUE;
733 //_____________________________________________________________________________
734 TMap* AliMergeableCollection::Map() const
736 /// Wrapper to insure proper key formats (i.e. new vs old)
741 fMap->SetOwnerKeyValue(kTRUE,kTRUE);
746 if ( fMapVersion < 1 )
748 AliInfo("Remapping");
753 while ( ( str = static_cast<TObjString*>(next()) ) )
755 if ( str->String().Contains("./") )
757 TString newkey(str->String());
759 newkey.ReplaceAll("./","");
761 TObject* o = fMap->GetValue(str);
763 TPair* p = fMap->RemoveEntry(str);
766 AliError("oups oups oups");
770 fMap->Add(new TObjString(newkey.Data()),o);
783 //_____________________________________________________________________________
785 AliMergeableCollection::Merge(TCollection* list)
787 // Merge a list of AliMergeableCollection objects with this
788 // Returns the number of merged objects (including this).
792 if (list->IsEmpty()) return 1;
799 while ( ( currObj = next() ) )
801 AliMergeableCollection* mergeCol = dynamic_cast<AliMergeableCollection*>(currObj);
803 AliFatal(Form("object named \"%s\" is a %s instead of an AliMergeableCollection!", currObj->GetName(), currObj->ClassName()));
809 if ( mergeCol->fMap ) mergeCol->Map(); // to insure keys in the new format
811 TIter nextIdentifier(mergeCol->fMap);
812 TObjString* identifier;
814 while ( ( identifier = static_cast<TObjString*>(nextIdentifier()) ) )
816 THashList* otherList = static_cast<THashList*>(mergeCol->fMap->GetValue(identifier->String().Data()));
818 TIter nextObject(otherList);
821 while ( ( obj = nextObject() ) )
823 TString newid(Form("%s%s",identifier->String().Data(),obj->GetName()));
825 TObject* thisObject = GetObject(newid.Data());
829 AliDebug(1,Form("Adopting a new object = %s%s",identifier->String().Data(),obj->GetName()));
831 Bool_t ok = Adopt(identifier->String(), obj->Clone());
835 AliError(Form("Adoption of object %s failed",obj->GetName()));
841 AliDebug(1,Form("Merging object = %s%s",
842 identifier->String().Data(),
845 MergeObject(thisObject, obj);
847 } // loop on objects in map
848 } // loop on identifiers
849 } // loop on collections in list
851 AliDebug(1,Form("count=%d",count));
856 //_____________________________________________________________________________
857 Bool_t AliMergeableCollection::MergeObject(TObject* baseObject, TObject* objToAdd)
859 /// Add objToAdd to baseObject
861 if ( baseObject->IsA()->Class() != objToAdd->IsA()->Class() ) {
862 printf("MergeObject: Cannot add %s to %s", objToAdd->ClassName(), baseObject->ClassName());
865 if ( ! baseObject->IsA()->InheritsFrom(TObject::Class()) ||
866 ! baseObject->IsA()->GetMethodWithPrototype("Merge", "TCollection*") ) {
867 printf("MergeObject: Objects are not mergeable!");
874 TString listArgs = Form("((TCollection*)0x%lx)", (ULong_t)&list);
876 baseObject->Execute("Merge", listArgs.Data(), &error);
880 //_____________________________________________________________________________
881 TString AliMergeableCollection::NormalizeName(const char* identifier,const char* action) const
883 /// Replace / by _ to build a root-compliant histo name
884 TString name(GetName());
890 name.ReplaceAll("/","_");
891 name.ReplaceAll("-","_");
895 //_____________________________________________________________________________
897 AliMergeableCollection::NumberOfObjects() const
899 /// Get the number of objects we hold
900 TIter next(CreateIterator());
902 while ( next() ) ++count;
906 //_____________________________________________________________________________
908 AliMergeableCollection::NumberOfKeys() const
910 /// Get the number of keys we have
911 return fMap ? fMap->GetSize() : 0;
914 //_____________________________________________________________________________
916 AliMergeableCollection::Print(Option_t* option) const
918 /// Print all the objects we hold, in a hopefully visually pleasing
921 /// Option can be used to select given part only, using the schema :
923 /// Where the stars are wilcards for /key1/key2/.../objectName
925 /// if * is used it is assumed to be a wildcard for objectName
927 /// For other selections the full syntax /*/*/*/*/* must be used.
929 /// Use "-" as objectName to disable object's name output
931 /// One might also use /*/*/*/*/:classname syntax to restrict
932 /// output to only those objects matching a given classname pattern
935 cout << Form("AliMergeableCollection(%s,%s) : %d keys and %d objects",
936 GetName(),GetTitle(),
937 NumberOfKeys(), NumberOfObjects()) << endl;
939 if (!strlen(option)) return;
941 TString soption(option);
943 TObjArray* classes = soption.Tokenize(":");
945 TRegexp* classPattern(0x0);
947 if ( classes->GetLast() > 0 )
949 TString pat = static_cast<TObjString*>(classes->At(1))->String();
950 classPattern = new TRegexp(pat,kTRUE);
951 soption = static_cast<TObjString*>(classes->At(0))->String();
956 TObjArray* select = soption.Tokenize("/");
958 TString sreObjectName(select->Last()->GetName());
959 TRegexp reObjectName(sreObjectName.Data(),kTRUE);
961 TObjArray* identifiers = SortAllIdentifiers();
963 printf("identifiers entries %i\n", identifiers->GetEntries());
965 TIter nextIdentifier(identifiers);
967 TObjString* sid(0x0);
969 while ( ( sid = static_cast<TObjString*>(nextIdentifier()) ) )
971 Bool_t identifierPrinted(kFALSE);
973 TString identifier(sid->String());
975 Bool_t matchPattern = kTRUE;
976 for ( Int_t isel=0; isel<select->GetLast(); isel++ ) {
977 if ( ! GetKey(identifier.Data(), isel, kFALSE).Contains(TRegexp(select->At(isel)->GetName(),kTRUE)) ) {
978 matchPattern = kFALSE;
982 if ( ! matchPattern ) continue;
984 if ( sreObjectName == "*" && !classPattern)
986 identifierPrinted = kTRUE;
987 cout << identifier.Data() << endl;
990 THashList * list = static_cast<THashList*>(Map()->GetValue(sid->String().Data()));
993 names.SetOwner(kTRUE);
994 TIter nextUnsortedObj(list);
996 while ( ( obj = nextUnsortedObj() ) )
998 TString cname(obj->ClassName());
999 if ( classPattern && !cname.Contains((*classPattern)) )
1003 names.Add(new TObjString(obj->GetName()));
1006 TIter nextObjName(&names);
1008 while ( ( oname = static_cast<TObjString*>(nextObjName()) ) )
1010 TString objName(oname->String());
1011 if (objName.Contains(reObjectName) )
1013 obj = list->FindObject(objName.Data());
1014 if ( IsEmptyObject(obj) && ! fMustShowEmptyObject ) continue;
1016 if (!identifierPrinted)
1018 cout << identifier.Data() << endl;
1019 identifierPrinted = kTRUE;
1023 TString warning(" ");
1025 if ( obj->IsA()->InheritsFrom(TH1::Class()) )
1028 TH1* histo = static_cast<TH1*> (obj);
1029 extra.Form("%s | Entries=%d Sum=%g",histo->GetTitle(),Int_t(histo->GetEntries()),histo->GetSumOfWeights());
1031 else if ( obj->IsA()->InheritsFrom(TGraph::Class()) )
1033 TGraph* graph = static_cast<TGraph*> (obj);
1034 if ( ! TMath::Finite(graph->GetMean(2) ) )
1038 extra.Form("%s | Npts=%d Mean=%g RMS=%g",graph->GetTitle(),graph->GetN(),
1039 graph->GetMean(2),graph->GetRMS(2));
1043 std::cout << Form(" (%s) %s %s", obj->ClassName(),
1047 if ( extra.Length() )
1049 std::cout << " | " << extra.Data();
1051 std::cout << std::endl;
1054 if (!identifierPrinted && sreObjectName=="-" )
1056 // to handle the case where we used objectName="-" to disable showing the objectNames,
1057 // but we still want to see the matching keys maybe...
1058 cout << identifier.Data() << endl;
1067 //_____________________________________________________________________________
1069 AliMergeableCollection::PrintMessages(const char* prefix) const
1071 /// Print pending messages
1073 std::map<std::string,int>::const_iterator it;
1075 for ( it = fMessages.begin(); it != fMessages.end(); ++it )
1077 cout << Form("%s : message %s appeared %5d times",prefix,it->first.c_str(),it->second) << endl;
1082 //_____________________________________________________________________________
1084 AliMergeableCollection::EstimateSize(Bool_t show) const
1086 /// Estimate the memory (in kilobytes) used by some objects
1089 // sizeof(TH1) + (nbins+2)*(nbytes_per_bin) +name+title_sizes
1090 // if you have errors add (nbins+2)*8
1092 TIter next(CreateIterator());
1097 while ( ( obj = next() ) )
1100 if ( obj->IsA()->InheritsFrom(TH1::Class()) ) {
1101 TH1* histo = static_cast<TH1*> (obj);
1102 Int_t nbins = (histo->GetNbinsX()+2);
1104 if (histo->GetNbinsY()>1)
1106 nbins *= (histo->GetNbinsY()+2);
1109 if (histo->GetNbinsZ()>1)
1111 nbins *= (histo->GetNbinsZ()+2);
1114 Bool_t hasErrors = ( histo->GetSumw2N() > 0 );
1116 TString cname(histo->ClassName());
1118 Int_t nbytesPerBin(0);
1120 if (cname.Contains(TRegexp("C$")) ) nbytesPerBin = sizeof(Char_t);
1121 if (cname.Contains(TRegexp("S$")) ) nbytesPerBin = sizeof(Short_t);
1122 if (cname.Contains(TRegexp("I$")) ) nbytesPerBin = sizeof(Int_t);
1123 if (cname.Contains(TRegexp("F$")) ) nbytesPerBin = sizeof(Float_t);
1124 if (cname.Contains(TRegexp("D$")) ) nbytesPerBin = sizeof(Double_t);
1128 AliError(Form("Could not get the number of bytes per bin for histo %s of class %s. Thus the size estimate will be wrong !",
1129 histo->GetName(),histo->ClassName()));
1133 thissize = sizeof(histo) + nbins*(nbytesPerBin) + strlen(histo->GetName())
1134 + strlen(histo->GetTitle());
1136 if ( hasErrors) thissize += nbins*8;
1138 else if ( obj->IsA()->InheritsFrom(THnSparse::Class()) ) {
1139 THnSparse* sparse = static_cast<THnSparse*> (obj);
1140 thissize = sizeof(Float_t) * (UInt_t)sparse->GetNbins();
1142 // else if ( obj->IsA() == AliCFGridSparse::Class() ) {
1143 // AliCFGridSparse* sparse = static_cast<AliCFGridSparse*> (obj);
1144 // thissize = sizeof(Float_t) * (UInt_t)sparse->GetNFilledBins();
1146 // else if ( obj->IsA() == AliCFContainer::Class() ) {
1147 // AliCFContainer* cont = static_cast<AliCFContainer*> (obj);
1148 // for ( Int_t istep=0; istep<cont->GetNStep(); istep++ ) {
1149 // thissize += sizeof(Float_t) * (UInt_t)cont->GetGrid(istep)->GetNFilledBins();
1153 AliWarning(Form("Cannot estimate size of %s\n", obj->ClassName()));
1161 AliInfo(Form("Size of %30s is %20d bytes",obj->GetName(),thissize));
1163 } // loop on objects
1168 //_____________________________________________________________________________
1169 Int_t AliMergeableCollection::Prune(const char* identifier)
1171 // Delete all objects which match the beginning of the identifier
1172 // returns the number of entries removed from the Map()
1173 // (not to be confused with the number of leaf objects removed)
1180 while ( ( key = static_cast<TObjString*>(next())) )
1182 if (key->String().BeginsWith(identifier))
1184 Bool_t ok = Map()->DeleteEntry(key);
1192 //_____________________________________________________________________________
1193 void AliMergeableCollection::PruneEmptyObjects()
1195 /// Delete the empty objects
1196 /// (Implemented for TH1 only)
1201 toBeRemoved.SetOwner(kTRUE);
1203 while ( ( key = static_cast<TObjString*>(next()) ) )
1205 TString identifier(key->String());
1206 THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier.Data()));
1207 TIter nextObject(hlist);
1209 while ( ( obj = nextObject() ) )
1211 if ( IsEmptyObject(obj) ) toBeRemoved.Add(new TObjString(Form("%s%s",identifier.Data(),obj->GetName())));
1215 TIter nextTBR(&toBeRemoved);
1216 while ( ( key = static_cast<TObjString*>(nextTBR()) ) )
1218 Remove(key->GetString().Data());
1219 AliDebug(2,Form("Removing %s", key->GetString().Data()));
1223 //_____________________________________________________________________________
1224 AliMergeableCollection*
1225 AliMergeableCollection::Project(const char* identifier) const
1227 /// To be implemented : would create a new collection starting at /key1/key2/...
1229 if (!fMap) return 0x0;
1231 AliMergeableCollection* mergCol = new AliMergeableCollection(Form("%s %s",GetName(),identifier),
1237 while ( ( str = static_cast<TObjString*>(next()) ) )
1239 TString currIdentifier = str->String();
1240 if ( ! currIdentifier.Contains(identifier) ) continue;
1242 THashList* list = static_cast<THashList*>(Map()->GetValue(identifier));
1244 TIter nextObj(list);
1247 while ( ( obj = nextObj()) )
1249 TObject* clone = obj->Clone();
1251 TString newkey(currIdentifier.Data());
1252 newkey.ReplaceAll(identifier,"");
1254 if (newkey=="/") newkey="";
1256 mergCol->InternalAdopt(newkey.Data(),clone);
1263 //_____________________________________________________________________________
1265 AliMergeableCollection::Remove(const char* fullIdentifier)
1268 /// Remove a given object (given its fullIdentifier=/key1/key2/.../objectName)
1270 /// Note that we do *not* remove the /key1/key2/... entry even if there's no
1271 /// more object for this triplet.
1273 /// Not very efficient. Could be improved ?
1276 TString identifier = GetIdentifier(fullIdentifier);
1278 THashList* hlist = dynamic_cast<THashList*>(Map()->GetValue(identifier.Data()));
1282 AliWarning(Form("Could not get hlist for key=%s",identifier.Data()));
1286 TObject* obj = GetObject(fullIdentifier);
1289 AliError(Form("Could not find object %s",fullIdentifier));
1293 TObject* rmObj = hlist->Remove(obj);
1296 AliError("Remove failed");
1303 //_____________________________________________________________________________
1304 Int_t AliMergeableCollection::RemoveByType(const char* typeName)
1306 /// Remove all the objects in this collection that are of a given type
1307 TIter nextIdentifier(Map());
1308 TObjString* identifier;
1311 while ( (identifier = static_cast<TObjString*>(nextIdentifier()) ) )
1313 THashList* list = static_cast<THashList*>(Map()->GetValue(identifier->String()));
1317 while ( ( o = next() ) )
1319 if ( strcmp(o->ClassName(),typeName) == 0 )
1330 //_____________________________________________________________________________
1332 AliMergeableCollection::SortAllIdentifiers() const
1334 /// Sort our internal identifiers. Returned array must be deleted.
1335 TObjArray* identifiers = new TObjArray;
1336 identifiers->SetOwner(kFALSE);
1340 while ( ( sid = static_cast<TObjString*>(next()) ) )
1342 if ( !identifiers->FindObject(sid->String().Data()) )
1344 identifiers->Add(sid);
1347 identifiers->Sort();
1352 ///////////////////////////////////////////////////////////////////////////////
1354 // AliMergeableCollectionIterator
1356 ///////////////////////////////////////////////////////////////////////////////
1358 class AliMergeableCollectionIterator;
1360 //_____________________________________________________________________________
1361 AliMergeableCollectionIterator::AliMergeableCollectionIterator(const AliMergeableCollection* mcol, Bool_t dir)
1362 : fkMergeableCollection(mcol), fMapIterator(0x0), fHashListIterator(0x0), fDirection(dir)
1367 //_____________________________________________________________________________
1368 AliMergeableCollectionIterator&
1369 AliMergeableCollectionIterator::operator=(const TIterator&)
1371 /// Overriden operator= (imposed by Root's declaration of TIterator ?)
1372 Fatal("TIterator::operator=","Not implementeable"); // because there's no clone in TIterator :-(
1376 //_____________________________________________________________________________
1377 AliMergeableCollectionIterator::~AliMergeableCollectionIterator()
1383 //_____________________________________________________________________________
1384 TObject* AliMergeableCollectionIterator::Next()
1386 /// Advance to next object in the collection
1388 if (!fHashListIterator)
1390 if ( !fMapIterator )
1392 fMapIterator = fkMergeableCollection->fMap->MakeIterator(fDirection);
1394 TObjString* key = static_cast<TObjString*>(fMapIterator->Next());
1400 THashList* list = static_cast<THashList*>(fkMergeableCollection->Map()->GetValue(key->String().Data()));
1401 if (!list) return 0x0;
1402 fHashListIterator = list->MakeIterator(fDirection);
1405 TObject* obj = fHashListIterator->Next();
1409 delete fHashListIterator;
1410 fHashListIterator = 0x0;
1417 //_____________________________________________________________________________
1418 void AliMergeableCollectionIterator::Reset()
1420 /// Reset the iterator
1421 delete fHashListIterator;
1422 delete fMapIterator;