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"
37 #include "THashList.h"
40 #include "TObjArray.h"
41 #include "TObjString.h"
48 #include "THnSparse.h"
51 //#include "AliCFGridSparse.h"
52 //#include "AliCFContainer.h"
55 //_____________________________________________________________________________
56 AliMergeableCollection::AliMergeableCollection(const char* name, const char* title)
57 : TNamed(name,title), fMap(0x0), fMustShowEmptyObject(0), fMapVersion(0), fMessages()
62 //_____________________________________________________________________________
63 AliMergeableCollection::~AliMergeableCollection()
65 /// dtor. Note that the map is owner
69 //_____________________________________________________________________________
71 AliMergeableCollection::Adopt(TObject* obj)
73 /// Adopt a given object at top level (i.e. no key)
74 return InternalAdopt("",obj);
77 //_____________________________________________________________________________
79 AliMergeableCollection::Adopt(const char* identifier, TObject* obj)
81 /// Adopt a given object, and associate it with pair key
82 TString sidentifier(identifier);
83 if ( ! sidentifier.IsNull() ){
84 if ( ! sidentifier.EndsWith("/") ) sidentifier.Append("/");
85 if ( ! sidentifier.BeginsWith("/") ) sidentifier.Prepend("/");
87 return InternalAdopt(sidentifier.Data(),obj);
90 //_____________________________________________________________________________
91 Bool_t AliMergeableCollection::Attach(AliMergeableCollection* mc, const char* identifier, Bool_t pruneFirstIfAlreadyExists)
93 /// Attach an already existing mergeable collection to this one.
94 /// It is attached at level identifier/
95 /// We take ownership of mc
96 /// If identifier is already existing we kill it if pruneFirstIfAlreadyExists is kTRUE
97 /// (and attach mc) otherwise we return kFALSE (and do *not* attach mc)
99 THashList* hlist = dynamic_cast<THashList*>(Map()->GetValue(identifier));
103 if (!pruneFirstIfAlreadyExists)
105 AliError(Form("%s already exist. Will not overwrite it.",identifier));
110 Int_t n = Prune(identifier);
113 AliError(Form("Could not prune pre-existing %s",identifier));
119 TIter next(mc->fMap);
122 while ( ( str = static_cast<TObjString*>(next())) )
124 THashList* hl = dynamic_cast<THashList*>(mc->Map()->GetValue(str->String()));
125 TString newid(Form("/%s%s",identifier,str->String().Data()));
126 newid.ReplaceAll("//","/");
127 Map()->Add(new TObjString(newid.Data()),hl);
133 //_____________________________________________________________________________
134 void AliMergeableCollection::ClearMessages()
136 /// clear pending messages
140 //_____________________________________________________________________________
142 AliMergeableCollection::CreateIterator(Bool_t direction) const
144 /// Create an iterator (must be deleted by the client)
145 return fMap ? new AliMergeableCollectionIterator(this,direction) : 0x0;
148 //_____________________________________________________________________________
149 AliMergeableCollection*
150 AliMergeableCollection::Clone(const char* name) const
152 /// Clone this collection.
153 /// We loose the messages.
155 AliMergeableCollection* newone = new AliMergeableCollection(name,GetTitle());
157 newone->fMap = static_cast<TMap*>(fMap->Clone());
158 newone->fMustShowEmptyObject = fMustShowEmptyObject;
159 newone->fMapVersion = fMapVersion;
164 //_____________________________________________________________________________
166 AliMergeableCollection::Delete(Option_t*)
168 /// Delete all the objects
174 //_____________________________________________________________________________
176 AliMergeableCollection::FindObject(const char* fullIdentifier) const
178 /// Find an object by its full identifier.
180 return GetObject(fullIdentifier);
183 //_____________________________________________________________________________
185 AliMergeableCollection::FindObject(const TObject *object) const
188 AliWarning("This method is awfully inefficient. Please improve it or use FindObject(const char*)");
189 TIter next(CreateIterator());
191 while ( ( obj=next() ) )
193 if ( obj->IsEqual(object) ) return obj;
199 //_____________________________________________________________________________
201 AliMergeableCollection::CreateListOfKeys(Int_t index) const
203 /// Create the list of keys at level index
205 TList* list = new TList;
206 list->SetOwner(kTRUE);
208 TObjArray* ids = SortAllIdentifiers();
212 while ( ( str = static_cast<TObjString*>(next()) ) )
214 TString oneid = GetKey(str->String().Data(),index,kFALSE);
215 if (oneid.Length()>0 && !list->Contains(oneid))
217 list->Add(new TObjString(oneid));
225 //_____________________________________________________________________________
227 AliMergeableCollection::CreateListOfObjectNames(const char* identifier) const
229 /// Create list of object names for /key1/key2/key...
230 /// Returned list must be deleted by client
232 TList* listOfNames = new TList;
233 listOfNames->SetOwner(kTRUE);
238 while ( ( str = static_cast<TObjString*>(next()) ) )
240 TString currIdentifier = str->String();
241 if ( currIdentifier.CompareTo(identifier) ) continue;
243 THashList* list = static_cast<THashList*>(Map()->GetValue(identifier));
245 TIter nextObject(list);
248 while ( ( obj = nextObject() ) )
250 listOfNames->Add(new TObjString(obj->GetName()));
258 //_____________________________________________________________________________
260 AliMergeableCollection::GetIdentifier(const char* fullIdentifier) const
262 /// Extract the identifier from the fullIdentifier
266 Int_t n = TString(fullIdentifier).CountChar('/')-1;
268 for (Int_t i=0; i < n; ++i)
271 identifier += InternalDecode(fullIdentifier,i);
277 //_____________________________________________________________________________
279 AliMergeableCollection::GetKey(const char* identifier, Int_t index, Bool_t idContainsObjName) const
281 /// Extract the index element of the key pair from the fullIdentifier
283 if ( ! idContainsObjName )
285 TString sidentifier(identifier);
286 sidentifier.Append("/dummy");
287 return InternalDecode(sidentifier.Data(),index);
290 return InternalDecode(identifier,index);
293 //_____________________________________________________________________________
295 AliMergeableCollection::GetObjectName(const char* fullIdentifier) const
297 /// Extract the object name from an identifier
299 return InternalDecode(fullIdentifier,-1);
302 //_____________________________________________________________________________
304 AliMergeableCollection::Histo(const char* fullIdentifier) const
306 /// Get histogram key1/key2/.../objectName:action
307 /// action is used for 2D histograms :
308 /// might be px for projection along x-axis
309 /// py for projection along y-axis
310 /// pfx for profile along x-axis
311 /// pfy for profile along y-axis
313 TString sfullIdentifier(fullIdentifier);
315 TString fullIdWithoutAction(fullIdentifier);
318 if ( sfullIdentifier.First(':') != kNPOS )
320 TObjArray* arr = sfullIdentifier.Tokenize(":");
322 fullIdWithoutAction = static_cast<TObjString*>(arr->At(0))->String();
324 if ( arr->GetLast() > 0 )
326 action = static_cast<TObjString*>(arr->At(1))->String();
333 Int_t nslashes = sfullIdentifier.CountChar('/');
339 o = GetObject("", fullIdWithoutAction);
343 o = GetObject(GetIdentifier(fullIdWithoutAction).Data(), GetObjectName(fullIdWithoutAction));
346 return HistoWithAction(fullIdWithoutAction.Data(),o,action);
349 //_____________________________________________________________________________
351 AliMergeableCollection::Histo(const char* identifier,
352 const char* objectName) const
354 TObject* o = GetObject(identifier,objectName);
356 TObjArray* arr = TString(objectName).Tokenize(":");
359 if ( arr->GetLast() > 0 )
361 action = static_cast<TObjString*>(arr->At(1))->String();
367 return HistoWithAction(identifier,o,action);
371 //_____________________________________________________________________________
373 AliMergeableCollection::HistoWithAction(const char* identifier, TObject* o, const TString& action) const
375 /// Convert o to an histogram if possible, applying a given action if there
379 if (!o->InheritsFrom("TH1"))
381 AliError(Form("%s is not an histogram",o->GetName()));
385 TH2* h2 = dynamic_cast<TH2*>(o);
389 if ( action == "PX" )
391 return h2->ProjectionX(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
393 if ( action == "PY" )
395 return h2->ProjectionY(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
397 if ( action == "PFX" )
399 return h2->ProfileX(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
401 if ( action == "PFY" )
403 return h2->ProfileY(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
407 return static_cast<TH1*>(o);
411 //_____________________________________________________________________________
413 AliMergeableCollection::GetObject(const char* fullIdentifier) const
415 /// Get object key1/key2/.../objectName
416 /// Note that no action is allowed for generic objects (only for histograms,
417 /// see Histo() methods)
419 TString sfullIdentifier(fullIdentifier);
421 Int_t nslashes = sfullIdentifier.CountChar('/');
425 return GetObject("", sfullIdentifier);
429 return GetObject(GetIdentifier(fullIdentifier).Data(), GetObjectName(fullIdentifier));
434 //_____________________________________________________________________________
436 AliMergeableCollection::GetObject(const char* identifier,
437 const char* objectName) const
439 /// Get object for (identifier,objectName) triplet
441 TString sidentifier(identifier);
442 if ( ! sidentifier.IsNull() ) {
443 if ( ! sidentifier.BeginsWith("/") ) sidentifier.Prepend("/");
444 if ( ! sidentifier.EndsWith("/") ) sidentifier.Append("/");
446 return InternalObject(sidentifier.Data(),objectName);
449 //_____________________________________________________________________________
450 TObject* AliMergeableCollection::GetSum(const char* idPattern) const
453 /// The pattern must be in the form:
454 /// /key1_1,key1_2,.../key2_1,key2_2,.../.../objectName_1,objectName_2...
455 /// The logical or between patterns separated by commas is taken
456 /// Exact match is required for keys and objectNames
458 TObject* sumObject = 0x0;
460 // Build array of lists of pattern
461 TString idPatternString(idPattern);
462 TObjArray* keyList = idPatternString.Tokenize("/");
463 TObjArray keyMatrix(keyList->GetEntries());
464 keyMatrix.SetOwner();
465 for ( Int_t ikey=0; ikey<keyList->GetEntries(); ikey++ ) {
466 TObjArray* subKeyList = ((TObjString*)keyList->At(ikey))->GetString().Tokenize(",");
467 keyMatrix.AddAt(subKeyList, ikey);
471 TString debugMsg = "Adding objects:";
474 // First handle the keys
478 while ( ( str = static_cast<TObjString*>(next()) ) )
480 TString identifier = str->String();
482 Bool_t listMatchPattern = kTRUE;
483 for ( Int_t ikey=0; ikey<keyMatrix.GetEntries()-1; ikey++ ) {
484 TString currKey = GetKey(identifier, ikey, kFALSE);
485 Bool_t matchKey = kFALSE;
486 TObjArray* subKeyList = static_cast<TObjArray*> ( keyMatrix.At(ikey) );
487 for ( Int_t isub=0; isub<subKeyList->GetEntries(); isub++ ) {
488 TString subKeyString = static_cast<TObjString*> (subKeyList->At(isub))->GetString();
489 if ( currKey == subKeyString ) {
493 } // loop on the list of patterns of each key
495 listMatchPattern = kFALSE;
498 } // loop on keys in the idPattern
499 if ( ! listMatchPattern ) continue;
503 // Then handle the object name
505 THashList* list = static_cast<THashList*>(Map()->GetValue(identifier.Data()));
510 while ( ( obj = nextObj()) )
512 TString currKey = obj->GetName();
513 Bool_t matchKey = kFALSE;
514 TObjArray* subKeyList = static_cast<TObjArray*> ( keyMatrix.Last() );
515 for ( Int_t isub=0; isub<subKeyList->GetEntries(); isub++ ) {
516 TString subKeyString = static_cast<TObjString*> (subKeyList->At(isub))->GetString();
517 if ( currKey == subKeyString ) {
522 if ( ! matchKey ) continue;
523 if ( ! sumObject ) sumObject = obj->Clone();
524 else MergeObject(sumObject, obj);
525 debugMsg += Form(" %s%s",identifier.Data(),obj->GetName());
526 } // loop on objects in list
527 } // loop on identifiers in map
529 AliDebug(1,debugMsg.Data());
534 //_____________________________________________________________________________
535 Bool_t AliMergeableCollection::InternalAdopt(const char* identifier, TObject* obj)
541 Error("Adopt","Cannot adopt a null object");
545 if ( ! obj->IsA()->InheritsFrom(TObject::Class()) ||
546 ! obj->IsA()->GetMethodWithPrototype("Merge", "TCollection*") ) {
547 Error("Adopt","Cannot adopt an object which is not mergeable!");
550 THashList* hlist = 0x0;
552 hlist = static_cast<THashList*>(Map()->GetValue(identifier));
556 hlist = new THashList;
557 hlist->SetOwner(kTRUE);
558 Map()->Add(new TObjString(identifier),hlist);
559 hlist->SetName(identifier);
562 TObject* existingObj = hlist->FindObject(obj->GetName());
566 AliError(Form("Cannot adopt an already existing object : %s -> %s",identifier,existingObj->GetName()));
570 if ( obj->IsA()->InheritsFrom(TH1::Class()) ) (static_cast<TH1*> ( obj ))->SetDirectory(0);
578 //_____________________________________________________________________________
580 AliMergeableCollection::InternalDecode(const char* identifier, Int_t index) const
582 /// Extract the index-th element of the identifier (/key1/key2/.../keyN/objectName)
583 /// object is index=-1 (i.e. last)
585 if ( strlen(identifier) > 0 && identifier[0] != '/' )
587 AliError(Form("identifier %s is malformed (should start with /)",identifier));
591 std::vector<Int_t> splitIndex;
594 TString sidentifier(identifier);
596 while (start < sidentifier.Length())
598 Int_t pos = sidentifier.Index('/', start);
599 if (pos == kNPOS) break;
600 splitIndex.push_back(pos);
604 Int_t nkeys = splitIndex.size() - 1;
606 if ( index >= nkeys )
608 AliError(Form("Requiring index %i of identifier %s which only have %i",index, identifier, nkeys));
614 return sidentifier(splitIndex.back()+1,sidentifier.Length()-splitIndex.back()-1);
617 return sidentifier(splitIndex[index]+1,splitIndex[index+1]-splitIndex[index]-1);
620 //_____________________________________________________________________________
622 AliMergeableCollection::InternalObject(const char* identifier,
623 const char* objectName) const
625 /// Get object for (identifier,objectName)
632 THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier));
635 TString msg(Form("Did not find hashlist for identifier=%s dir=%s",identifier,gDirectory ? gDirectory->GetName() : "" ));
636 fMessages[msg.Data()]++;
640 TObject* obj = hlist->FindObject(objectName);
643 TString msg(Form("Did not find objectName=%s in %s",objectName,identifier));
644 fMessages[msg.Data()]++;
650 //_____________________________________________________________________________
651 Bool_t AliMergeableCollection::IsEmptyObject(TObject* obj) const
653 /// Check if object is empty
654 /// (done only for TH1, so far)
656 if ( obj->IsA()->InheritsFrom(TH1::Class()) ) {
657 TH1* histo = static_cast<TH1*> (obj);
658 if ( histo->GetEntries() == 0 ) return kTRUE;
666 //_____________________________________________________________________________
667 TMap* AliMergeableCollection::Map() const
669 /// Wrapper to insure proper key formats (i.e. new vs old)
674 fMap->SetOwnerKeyValue(kTRUE,kTRUE);
679 if ( fMapVersion < 1 )
681 AliInfo("Remapping");
686 while ( ( str = static_cast<TObjString*>(next()) ) )
688 if ( str->String().Contains("./") )
690 TString newkey(str->String());
692 newkey.ReplaceAll("./","");
694 TObject* o = fMap->GetValue(str);
696 TPair* p = fMap->RemoveEntry(str);
699 AliError("oups oups oups");
703 fMap->Add(new TObjString(newkey.Data()),o);
716 //_____________________________________________________________________________
718 AliMergeableCollection::Merge(TCollection* list)
720 // Merge a list of AliMergeableCollection objects with this
721 // Returns the number of merged objects (including this).
725 if (list->IsEmpty()) return 1;
732 while ( ( currObj = next() ) )
734 AliMergeableCollection* mergeCol = dynamic_cast<AliMergeableCollection*>(currObj);
736 AliFatal(Form("object named \"%s\" is a %s instead of an AliMergeableCollection!", currObj->GetName(), currObj->ClassName()));
742 if ( mergeCol->fMap ) mergeCol->Map(); // to insure keys in the new format
744 TIter nextIdentifier(mergeCol->fMap);
745 TObjString* identifier;
747 while ( ( identifier = static_cast<TObjString*>(nextIdentifier()) ) )
749 THashList* otherList = static_cast<THashList*>(mergeCol->fMap->GetValue(identifier->String().Data()));
751 TIter nextObject(otherList);
754 while ( ( obj = nextObject() ) )
756 TString newid(Form("%s%s",identifier->String().Data(),obj->GetName()));
758 TObject* thisObject = GetObject(newid.Data());
762 AliDebug(1,Form("Adopting a new object = %s%s",identifier->String().Data(),obj->GetName()));
764 Bool_t ok = Adopt(identifier->String(), obj->Clone());
768 AliError(Form("Adoption of object %s failed",obj->GetName()));
774 AliDebug(1,Form("Merging object = %s%s",
775 identifier->String().Data(),
778 MergeObject(thisObject, obj);
780 } // loop on objects in map
781 } // loop on identifiers
782 } // loop on collections in list
784 AliDebug(1,Form("count=%d",count));
789 //_____________________________________________________________________________
790 Bool_t AliMergeableCollection::MergeObject(TObject* baseObject, TObject* objToAdd)
792 /// Add objToAdd to baseObject
794 if ( baseObject->IsA()->Class() != objToAdd->IsA()->Class() ) {
795 printf("MergeObject: Cannot add %s to %s", objToAdd->ClassName(), baseObject->ClassName());
798 if ( ! baseObject->IsA()->InheritsFrom(TObject::Class()) ||
799 ! baseObject->IsA()->GetMethodWithPrototype("Merge", "TCollection*") ) {
800 printf("MergeObject: Objects are not mergeable!");
807 TString listArgs = Form("((TCollection*)0x%lx)", (ULong_t)&list);
809 baseObject->Execute("Merge", listArgs.Data(), &error);
813 //_____________________________________________________________________________
814 TString AliMergeableCollection::NormalizeName(const char* identifier,const char* action) const
816 /// Replace / by _ to build a root-compliant histo name
817 TString name(GetName());
823 name.ReplaceAll("/","_");
824 name.ReplaceAll("-","_");
828 //_____________________________________________________________________________
830 AliMergeableCollection::NumberOfObjects() const
832 /// Get the number of objects we hold
833 TIter next(CreateIterator());
835 while ( next() ) ++count;
839 //_____________________________________________________________________________
841 AliMergeableCollection::NumberOfKeys() const
843 /// Get the number of keys we have
844 return fMap ? fMap->GetSize() : 0;
847 //_____________________________________________________________________________
849 AliMergeableCollection::Print(Option_t* option) const
851 /// Print all the objects we hold, in a hopefully visually pleasing
854 /// Option can be used to select given part only, using the schema :
856 /// Where the stars are wilcards for /key1/key2/.../objectName
858 /// if * is used it is assumed to be a wildcard for objectName
860 /// For other selections the full syntax /*/*/*/*/* must be used.
862 /// Use "-" as objectName to disable object's name output
864 /// One might also use /*/*/*/*/:classname syntax to restrict
865 /// output to only those objects matching a given classname pattern
868 cout << Form("AliMergeableCollection(%s,%s) : %d keys and %d objects",
869 GetName(),GetTitle(),
870 NumberOfKeys(), NumberOfObjects()) << endl;
872 if (!strlen(option)) return;
874 TString soption(option);
876 TObjArray* classes = soption.Tokenize(":");
878 TRegexp* classPattern(0x0);
880 if ( classes->GetLast() > 0 )
882 TString pat = static_cast<TObjString*>(classes->At(1))->String();
883 classPattern = new TRegexp(pat,kTRUE);
884 soption = static_cast<TObjString*>(classes->At(0))->String();
889 TObjArray* select = soption.Tokenize("/");
891 TString sreObjectName(select->Last()->GetName());
892 TRegexp reObjectName(sreObjectName.Data(),kTRUE);
894 TObjArray* identifiers = SortAllIdentifiers();
896 printf("identifiers entries %i\n", identifiers->GetEntries());
898 TIter nextIdentifier(identifiers);
900 TObjString* sid(0x0);
902 while ( ( sid = static_cast<TObjString*>(nextIdentifier()) ) )
904 Bool_t identifierPrinted(kFALSE);
906 TString identifier(sid->String());
908 Bool_t matchPattern = kTRUE;
909 for ( Int_t isel=0; isel<select->GetLast(); isel++ ) {
910 if ( ! GetKey(identifier.Data(), isel, kFALSE).Contains(TRegexp(select->At(isel)->GetName(),kTRUE)) ) {
911 matchPattern = kFALSE;
915 if ( ! matchPattern ) continue;
917 if ( sreObjectName == "*" && !classPattern)
919 identifierPrinted = kTRUE;
920 cout << identifier.Data() << endl;
923 THashList * list = static_cast<THashList*>(Map()->GetValue(sid->String().Data()));
926 names.SetOwner(kTRUE);
927 TIter nextUnsortedObj(list);
929 while ( ( obj = nextUnsortedObj() ) )
931 TString cname(obj->ClassName());
932 if ( classPattern && !cname.Contains((*classPattern)) )
936 names.Add(new TObjString(obj->GetName()));
939 TIter nextObjName(&names);
941 while ( ( oname = static_cast<TObjString*>(nextObjName()) ) )
943 TString objName(oname->String());
944 if (objName.Contains(reObjectName) )
946 obj = list->FindObject(objName.Data());
947 if ( IsEmptyObject(obj) && ! fMustShowEmptyObject ) continue;
949 if (!identifierPrinted)
951 cout << identifier.Data() << endl;
952 identifierPrinted = kTRUE;
956 TString warning(" ");
958 if ( obj->IsA()->InheritsFrom(TH1::Class()) )
961 TH1* histo = static_cast<TH1*> (obj);
962 extra.Form("%s | Entries=%d Sum=%g",histo->GetTitle(),Int_t(histo->GetEntries()),histo->GetSumOfWeights());
964 else if ( obj->IsA()->InheritsFrom(TGraph::Class()) )
966 TGraph* graph = static_cast<TGraph*> (obj);
967 if ( ! TMath::Finite(graph->GetMean(2) ) )
971 extra.Form("%s | Npts=%d Mean=%g RMS=%g",graph->GetTitle(),graph->GetN(),
972 graph->GetMean(2),graph->GetRMS(2));
976 std::cout << Form(" (%s) %s %s", obj->ClassName(),
980 if ( extra.Length() )
982 std::cout << " | " << extra.Data();
984 std::cout << std::endl;
987 if (!identifierPrinted && sreObjectName=="-" )
989 // to handle the case where we used objectName="-" to disable showing the objectNames,
990 // but we still want to see the matching keys maybe...
991 cout << identifier.Data() << endl;
1000 //_____________________________________________________________________________
1002 AliMergeableCollection::PrintMessages(const char* prefix) const
1004 /// Print pending messages
1006 std::map<std::string,int>::const_iterator it;
1008 for ( it = fMessages.begin(); it != fMessages.end(); ++it )
1010 cout << Form("%s : message %s appeared %5d times",prefix,it->first.c_str(),it->second) << endl;
1015 //_____________________________________________________________________________
1017 AliMergeableCollection::EstimateSize(Bool_t show) const
1019 /// Estimate the memory (in kilobytes) used by some objects
1022 // sizeof(TH1) + (nbins+2)*(nbytes_per_bin) +name+title_sizes
1023 // if you have errors add (nbins+2)*8
1025 TIter next(CreateIterator());
1030 while ( ( obj = next() ) )
1033 if ( obj->IsA()->InheritsFrom(TH1::Class()) ) {
1034 TH1* histo = static_cast<TH1*> (obj);
1035 Int_t nbins = (histo->GetNbinsX()+2);
1037 if (histo->GetNbinsY()>1)
1039 nbins *= (histo->GetNbinsY()+2);
1042 if (histo->GetNbinsZ()>1)
1044 nbins *= (histo->GetNbinsZ()+2);
1047 Bool_t hasErrors = ( histo->GetSumw2N() > 0 );
1049 TString cname(histo->ClassName());
1051 Int_t nbytesPerBin(0);
1053 if (cname.Contains(TRegexp("C$")) ) nbytesPerBin = sizeof(Char_t);
1054 if (cname.Contains(TRegexp("S$")) ) nbytesPerBin = sizeof(Short_t);
1055 if (cname.Contains(TRegexp("I$")) ) nbytesPerBin = sizeof(Int_t);
1056 if (cname.Contains(TRegexp("F$")) ) nbytesPerBin = sizeof(Float_t);
1057 if (cname.Contains(TRegexp("D$")) ) nbytesPerBin = sizeof(Double_t);
1061 AliError(Form("Could not get the number of bytes per bin for histo %s of class %s. Thus the size estimate will be wrong !",
1062 histo->GetName(),histo->ClassName()));
1066 thissize = sizeof(histo) + nbins*(nbytesPerBin) + strlen(histo->GetName())
1067 + strlen(histo->GetTitle());
1069 if ( hasErrors) thissize += nbins*8;
1071 else if ( obj->IsA()->InheritsFrom(THnSparse::Class()) ) {
1072 THnSparse* sparse = static_cast<THnSparse*> (obj);
1073 thissize = sizeof(Float_t) * (UInt_t)sparse->GetNbins();
1075 // else if ( obj->IsA() == AliCFGridSparse::Class() ) {
1076 // AliCFGridSparse* sparse = static_cast<AliCFGridSparse*> (obj);
1077 // thissize = sizeof(Float_t) * (UInt_t)sparse->GetNFilledBins();
1079 // else if ( obj->IsA() == AliCFContainer::Class() ) {
1080 // AliCFContainer* cont = static_cast<AliCFContainer*> (obj);
1081 // for ( Int_t istep=0; istep<cont->GetNStep(); istep++ ) {
1082 // thissize += sizeof(Float_t) * (UInt_t)cont->GetGrid(istep)->GetNFilledBins();
1086 AliWarning(Form("Cannot estimate size of %s\n", obj->ClassName()));
1094 AliInfo(Form("Size of %30s is %20d bytes",obj->GetName(),thissize));
1096 } // loop on objects
1101 //_____________________________________________________________________________
1102 Int_t AliMergeableCollection::Prune(const char* identifier)
1104 // Delete all objects which match the beginning of the identifier
1105 // returns the number of entries removed from the Map()
1106 // (not to be confused with the number of leaf objects removed)
1113 while ( ( key = static_cast<TObjString*>(next())) )
1115 if (key->String().BeginsWith(identifier))
1117 Bool_t ok = Map()->DeleteEntry(key);
1125 //_____________________________________________________________________________
1126 void AliMergeableCollection::PruneEmptyObjects()
1128 /// Delete the empty objects
1129 /// (Implemented for TH1 only)
1134 toBeRemoved.SetOwner(kTRUE);
1136 while ( ( key = static_cast<TObjString*>(next()) ) )
1138 TString identifier(key->String());
1139 THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier.Data()));
1140 TIter nextObject(hlist);
1142 while ( ( obj = nextObject() ) )
1144 if ( IsEmptyObject(obj) ) toBeRemoved.Add(new TObjString(Form("%s%s",identifier.Data(),obj->GetName())));
1148 TIter nextTBR(&toBeRemoved);
1149 while ( ( key = static_cast<TObjString*>(nextTBR()) ) )
1151 Remove(key->GetString().Data());
1152 AliDebug(2,Form("Removing %s", key->GetString().Data()));
1156 //_____________________________________________________________________________
1157 AliMergeableCollection*
1158 AliMergeableCollection::Project(const char* identifier) const
1160 /// To be implemented : would create a new collection starting at /key1/key2/...
1162 if (!fMap) return 0x0;
1164 AliMergeableCollection* mergCol = new AliMergeableCollection(Form("%s %s",GetName(),identifier),
1170 while ( ( str = static_cast<TObjString*>(next()) ) )
1172 TString currIdentifier = str->String();
1173 if ( ! currIdentifier.Contains(identifier) ) continue;
1175 THashList* list = static_cast<THashList*>(Map()->GetValue(identifier));
1177 TIter nextObj(list);
1180 while ( ( obj = nextObj()) )
1182 TObject* clone = obj->Clone();
1184 TString newkey(currIdentifier.Data());
1185 newkey.ReplaceAll(identifier,"");
1187 if (newkey=="/") newkey="";
1189 mergCol->InternalAdopt(newkey.Data(),clone);
1196 //_____________________________________________________________________________
1198 AliMergeableCollection::Remove(const char* fullIdentifier)
1201 /// Remove a given object (given its fullIdentifier=/key1/key2/.../objectName)
1203 /// Note that we do *not* remove the /key1/key2/... entry even if there's no
1204 /// more object for this triplet.
1206 /// Not very efficient. Could be improved ?
1209 TString identifier = GetIdentifier(fullIdentifier);
1211 THashList* hlist = dynamic_cast<THashList*>(Map()->GetValue(identifier.Data()));
1215 AliWarning(Form("Could not get hlist for key=%s",identifier.Data()));
1219 TObject* obj = GetObject(fullIdentifier);
1222 AliError(Form("Could not find object %s",fullIdentifier));
1226 TObject* rmObj = hlist->Remove(obj);
1229 AliError("Remove failed");
1236 //_____________________________________________________________________________
1237 Int_t AliMergeableCollection::RemoveByType(const char* typeName)
1239 /// Remove all the objects in this collection that are of a given type
1240 TIter nextIdentifier(Map());
1241 TObjString* identifier;
1244 while ( (identifier = static_cast<TObjString*>(nextIdentifier()) ) )
1246 THashList* list = static_cast<THashList*>(Map()->GetValue(identifier->String()));
1250 while ( ( o = next() ) )
1252 if ( strcmp(o->ClassName(),typeName) == 0 )
1263 //_____________________________________________________________________________
1265 AliMergeableCollection::SortAllIdentifiers() const
1267 /// Sort our internal identifiers. Returned array must be deleted.
1268 TObjArray* identifiers = new TObjArray;
1269 identifiers->SetOwner(kFALSE);
1273 while ( ( sid = static_cast<TObjString*>(next()) ) )
1275 if ( !identifiers->FindObject(sid->String().Data()) )
1277 identifiers->Add(sid);
1280 identifiers->Sort();
1285 ///////////////////////////////////////////////////////////////////////////////
1287 // AliMergeableCollectionIterator
1289 ///////////////////////////////////////////////////////////////////////////////
1291 class AliMergeableCollectionIterator;
1293 //_____________________________________________________________________________
1294 AliMergeableCollectionIterator::AliMergeableCollectionIterator(const AliMergeableCollection* mcol, Bool_t dir)
1295 : fkMergeableCollection(mcol), fMapIterator(0x0), fHashListIterator(0x0), fDirection(dir)
1300 //_____________________________________________________________________________
1301 AliMergeableCollectionIterator&
1302 AliMergeableCollectionIterator::operator=(const TIterator&)
1304 /// Overriden operator= (imposed by Root's declaration of TIterator ?)
1305 Fatal("TIterator::operator=","Not implementeable"); // because there's no clone in TIterator :-(
1309 //_____________________________________________________________________________
1310 AliMergeableCollectionIterator::~AliMergeableCollectionIterator()
1316 //_____________________________________________________________________________
1317 TObject* AliMergeableCollectionIterator::Next()
1319 /// Advance to next object in the collection
1321 if (!fHashListIterator)
1323 if ( !fMapIterator )
1325 fMapIterator = fkMergeableCollection->fMap->MakeIterator(fDirection);
1327 TObjString* key = static_cast<TObjString*>(fMapIterator->Next());
1333 THashList* list = static_cast<THashList*>(fkMergeableCollection->Map()->GetValue(key->String().Data()));
1334 if (!list) return 0x0;
1335 fHashListIterator = list->MakeIterator(fDirection);
1338 TObject* obj = fHashListIterator->Next();
1342 delete fHashListIterator;
1343 fHashListIterator = 0x0;
1350 //_____________________________________________________________________________
1351 void AliMergeableCollectionIterator::Reset()
1353 /// Reset the iterator
1354 delete fHashListIterator;
1355 delete fMapIterator;