]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG/muon/AliHistogramCollection.cxx
Transition PWG3 --> PWGHF
[u/mrichter/AliRoot.git] / PWG / muon / AliHistogramCollection.cxx
CommitLineData
d899f664 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/// A (fake) "4D" histogram container.
20///
21/// For each tuple (keyA,keyB,keyC,keyD) a (hash)list of histogram is associated.
22/// Note that keyA, keyB (optional), keyC (optional) and keyD (optional) are strings.
23/// Those strings should not contain "/" themselves.
24///
25/// More helper functions might be added in the future (e.g. Project, etc...)
26
27#include "AliHistogramCollection.h"
28
29#include "AliLog.h"
30#include "Riostream.h"
31#include "TError.h"
32#include "TH1.h"
5eabea87 33#include "TH2.h"
d899f664 34#include "THashList.h"
35#include "TKey.h"
36#include "TMap.h"
37#include "TObjArray.h"
38#include "TObjString.h"
39#include "TRegexp.h"
40#include "TROOT.h"
41#include "TSystem.h"
5eabea87 42#include "TProfile.h"
d899f664 43
44ClassImp(AliHistogramCollection)
45
46//_____________________________________________________________________________
47AliHistogramCollection::AliHistogramCollection(const char* name, const char* title)
5eabea87 48: TNamed(name,title), fMap(0x0), fMustShowEmptyHistogram(kFALSE), fMapVersion(0), fMessages()
d899f664 49{
50 /// Ctor
51}
52
53//_____________________________________________________________________________
54AliHistogramCollection::~AliHistogramCollection()
55{
56 /// dtor. Note that the map is owner
57 if ( fMap ) fMap->DeleteAll();
58 delete fMap;
5eabea87 59// PrintMessages("AliHistogramCollection::~AliHistogramCollection");
60}
61
62//_____________________________________________________________________________
63Bool_t
64AliHistogramCollection::Adopt(TH1* histo)
65{
66 /// Adopt a given histogram at top level (i.e. no key)
67 return InternalAdopt("",histo);
d899f664 68}
69
70//_____________________________________________________________________________
71Bool_t
72AliHistogramCollection::Adopt(const char* key, TH1* histo)
73{
74 /// Adopt a given histogram, and associate it with pair (keyA)
5eabea87 75 return InternalAdopt(Form("/%s/",key),histo);
d899f664 76}
77
78//_____________________________________________________________________________
79Bool_t
80AliHistogramCollection::Adopt(const char* keyA, const char* keyB, TH1* histo)
81{
82 /// Adopt a given histogram, and associate it with pair (keyA,keyB)
5eabea87 83 return InternalAdopt(Form("/%s/%s/",keyA,keyB),histo);
d899f664 84}
85
86//_____________________________________________________________________________
87Bool_t
88AliHistogramCollection::Adopt(const char* keyA, const char* keyB, const char* keyC, TH1* histo)
89{
90 /// Adopt a given histogram, and associate it with pair (keyA,keyB,keyC)
5eabea87 91 return InternalAdopt(Form("/%s/%s/%s/",keyA,keyB,keyC),histo);
d899f664 92}
93
94//_____________________________________________________________________________
95Bool_t
96AliHistogramCollection::Adopt(const char* keyA, const char* keyB, const char* keyC, const char* keyD, TH1* histo)
97{
98 /// Adopt a given histogram, and associate it with pair (keyA,keyB,keyC,keyD)
99 return InternalAdopt(Form("/%s/%s/%s/%s/",keyA,keyB,keyC,keyD),histo);
100}
101
5eabea87 102//_____________________________________________________________________________
103void AliHistogramCollection::ClearMessages()
104{
105 /// clear pending messages
106 fMessages.clear();
107}
108
d899f664 109//_____________________________________________________________________________
110TIterator*
111AliHistogramCollection::CreateIterator(Bool_t direction) const
112{
113 /// Create an iterator (must be deleted by the client)
114 return fMap ? new AliHistogramCollectionIterator(this,direction) : 0x0;
115}
116
5eabea87 117//_____________________________________________________________________________
118AliHistogramCollection*
119AliHistogramCollection::Clone(const char* name) const
120{
121 /// Clone this collection.
122 /// We loose the messages.
123
124 AliHistogramCollection* newone = new AliHistogramCollection(name,GetTitle());
125
126 newone->fMap = static_cast<TMap*>(fMap->Clone());
127 newone->fMustShowEmptyHistogram = fMustShowEmptyHistogram;
128 newone->fMapVersion = fMapVersion;
129
130 return newone;
131}
132
d899f664 133//_____________________________________________________________________________
134void
135AliHistogramCollection::Delete(Option_t*)
136{
137 /// Delete all the histograms
138 fMap->DeleteAll();
139 delete fMap;
140 fMap=0x0;
141}
142
143//_____________________________________________________________________________
144TObject*
145AliHistogramCollection::FindObject(const char* identifier) const
146{
147 /// Find an object by its full identifier.
148
149 return Histo(KeyA(identifier),
150 KeyB(identifier),
151 KeyC(identifier),
152 KeyD(identifier),
153 HistoName(identifier));
154}
155
156//_____________________________________________________________________________
157TObject*
158AliHistogramCollection::FindObject(const TObject *key) const
159{
160 /// Find an object
161 AliWarning("This method is awfully inefficient. Please improve it or use FindObject(const char*)");
162 TIter next(CreateIterator());
163 TObject* o;
164 while ( ( o=next() ) )
165 {
166 if ( o->IsEqual(key) ) return o;
167 }
168 return 0x0;
169}
170
171//_____________________________________________________________________________
172TH1*
173AliHistogramCollection::Histo(const char* keyA,
174 const char* histoname) const
175{
176 /// Get histo for (keyA,histoname) triplet
177
5eabea87 178 return InternalHisto(Form("/%s/",keyA),histoname);
d899f664 179}
180
181//_____________________________________________________________________________
182TH1*
183AliHistogramCollection::Histo(const char* keyA, const char* keyB,
184 const char* histoname) const
185{
186 /// Get histo for (keyA,keyB,histoname) triplet
187
5eabea87 188 return InternalHisto(Form("/%s/%s/",keyA,keyB),histoname);
d899f664 189}
190
191//_____________________________________________________________________________
192TH1*
193AliHistogramCollection::Histo(const char* keyA, const char* keyB, const char* keyC,
194 const char* histoname) const
195{
196 /// Get histo for (keyA,keyB,keyC,histoname) quad
197
5eabea87 198 return InternalHisto(Form("/%s/%s/%s/",keyA,keyB,keyC),histoname);
d899f664 199}
200
201//_____________________________________________________________________________
202TH1*
203AliHistogramCollection::Histo(const char* keyA, const char* keyB,
204 const char* keyC, const char* keyD,
205 const char* histoname) const
206{
207 /// Get histo for (keyA,keyB,keyC,histoname) quad
208
209 return InternalHisto(Form("/%s/%s/%s/%s/",keyA,keyB,keyC,keyD),histoname);
210}
211
212//_____________________________________________________________________________
213TString
214AliHistogramCollection::HistoName(const char* identifier) const
215{
216 /// Extract the histogram name from an identifier
217
5eabea87 218 return InternalDecode(identifier,-1);
d899f664 219}
220
221//_____________________________________________________________________________
222Bool_t AliHistogramCollection::InternalAdopt(const char* identifier, TH1* histo)
223{
224 /// Adopt an histogram
225
226 if (!histo)
227 {
228 Error("Adopt","Cannot adopt a null histogram");
229 return kFALSE;
230 }
231
232 THashList* hlist = 0x0;
233
5eabea87 234 hlist = static_cast<THashList*>(Map()->GetValue(identifier));
d899f664 235
236 if (!hlist)
237 {
238 hlist = new THashList;
239 hlist->SetOwner(kTRUE);
5eabea87 240 Map()->Add(new TObjString(identifier),hlist);
d899f664 241 hlist->SetName(identifier);
242 }
243
244 TH1* h = static_cast<TH1*>(hlist->FindObject(histo->GetName()));
245
246 if (h)
247 {
248 AliError(Form("Cannot adopt an already existing histogram : %s -> %s",identifier,h->GetName()));
249 return kFALSE;
250 }
251
252
253 histo->SetDirectory(0);
254
255 hlist->AddLast(histo);
256
257 return kTRUE;
258
259}
260
261//_____________________________________________________________________________
262TH1*
5eabea87 263AliHistogramCollection::Histo(const char* sidentifier) const
d899f664 264{
5eabea87 265 /// Get histogram keyA/keyB/keyC/keyD/histoname:action
266
267 TObjArray* a = TString(sidentifier).Tokenize(":");
268
269 TString identifier(static_cast<TObjString*>(a->At(0))->String());
270 TString action;
271
272 if ( a->GetLast() > 0 )
273 {
274 action = static_cast<TObjString*>(a->At(1))->String();
275 action.ToUpper();
276 }
277
278 Int_t nslashes = identifier.CountChar('/');
279
280 TH1* h(0x0);
281
282 switch (nslashes)
283 {
284 case 0:
285 case 1:
286 // no slash : the identifier is just the histogram name
287 h = InternalHisto("",identifier);
288 break;
289 case 2:
290 h = Histo(InternalDecode(identifier,0),
291 InternalDecode(identifier,-1));
292 break;
293 case 3:
294 h = Histo(InternalDecode(identifier,0),
295 InternalDecode(identifier,1),
296 InternalDecode(identifier,-1));
297 break;
298 case 4:
299 h = Histo(InternalDecode(identifier,0),
300 InternalDecode(identifier,1),
301 InternalDecode(identifier,2),
302 InternalDecode(identifier,-1));
303 break;
304 case 5:
305 h = Histo(InternalDecode(identifier,0),
306 InternalDecode(identifier,1),
307 InternalDecode(identifier,2),
308 InternalDecode(identifier,3),
309 InternalDecode(identifier,-1));
310 break;
311 default:
312 AliError(Form("Invalid identifier %s",identifier.Data()));
313 break;
314 }
315
316 if (h)
317 {
318 TH2* h2(0x0);
319
320 if ( action == "PX" && ( (h2 = dynamic_cast<TH2*>(h)) ) )
321 {
322 return h2->ProjectionX(NormalizeName(identifier.Data(),action.Data()).Data());
323 }
324 else if ( action == "PY" && ( (h2 = dynamic_cast<TH2*>(h)) ) )
325 {
326 return h2->ProjectionY(NormalizeName(identifier.Data(),action.Data()).Data());
327 }
328 else if ( action == "PFX" && ( (h2 = dynamic_cast<TH2*>(h)) ) )
329 {
330 return h2->ProfileX(NormalizeName(identifier.Data(),action.Data()).Data());
331 }
332 else if ( action == "PFY" && ( (h2 = dynamic_cast<TH2*>(h)) ) )
333 {
334 return h2->ProfileY(NormalizeName(identifier.Data(),action.Data()).Data());
335 }
336
337 }
338 else
339 {
340 AliDebug(1,Form("histogram %s not found",sidentifier));
341 }
342 return h;
d899f664 343}
344
345//_____________________________________________________________________________
346TString
347AliHistogramCollection::InternalDecode(const char* identifier, Int_t index) const
348{
349 /// Extract the index-th element of the identifier (/keyA/keyB/keyC/keyD/histoname)
350 /// keyA is index=0
351 /// keyB is index=1
352 /// keyC is index=2
353 /// keyD is index=3
5eabea87 354 /// histo is index=-1 (i.e. last)
d899f664 355
5eabea87 356 if ( strlen(identifier) > 0 && identifier[0] != '/' )
d899f664 357 {
5eabea87 358 AliError(Form("identifier %s is malformed (should start with /)",identifier));
d899f664 359 return "";
360 }
361
362 TObjArray* array = TString(identifier).Tokenize("/");
363
364 if ( array->GetLast()>5 )
365 {
5eabea87 366 AliError(Form("identifier %s is malformed (more than 5 /)",identifier));
d899f664 367 delete array;
368 return "";
369 }
370
371 TString value("");
372
5eabea87 373 if ( index < 0 )
374 {
375 value = static_cast<TObjString*>(array->Last())->String();
376 }
377 else if ( index <= array->GetLast() )
d899f664 378 {
379 value = static_cast<TObjString*>(array->At(index))->String();
380 }
381
382 delete array;
383
384 return value;
d899f664 385}
386
387//_____________________________________________________________________________
388TH1*
389AliHistogramCollection::InternalHisto(const char* identifier,
390 const char* histoname) const
391{
392 /// Get histo for (identifier,histoname)
393
394 if (!fMap)
395 {
396 return 0x0;
397 }
398
5eabea87 399 THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier));
d899f664 400 if (!hlist)
401 {
5eabea87 402 TString msg(Form("Did not find hashlist for identifier=%s dir=%s",identifier,gDirectory ? gDirectory->GetName() : "" ));
403 fMessages[msg.Data()]++;
d899f664 404 return 0x0;
405 }
406
5eabea87 407 TH1* h = static_cast<TH1*>(hlist->FindObject(histoname));
408 if (!h)
409 {
410 TString msg(Form("Did not find histoname=%s in %s",histoname,identifier));
411 fMessages[msg.Data()]++;
412 }
413 return h;
d899f664 414}
415
416
417//_____________________________________________________________________________
418TString
419AliHistogramCollection::KeyA(const char* identifier) const
420{
421 /// Extract the first element of the key pair from an identifier
422
423 return InternalDecode(identifier,0);
424}
425
426//_____________________________________________________________________________
427TString
428AliHistogramCollection::KeyB(const char* identifier) const
429{
430 /// Extract the second element (if present)
431 return InternalDecode(identifier,1);
432}
433
434//_____________________________________________________________________________
435TString
436AliHistogramCollection::KeyC(const char* identifier) const
437{
438 /// Extract the 3rd element (if present)
439 return InternalDecode(identifier,2);
440}
441
442//_____________________________________________________________________________
443TString
444AliHistogramCollection::KeyD(const char* identifier) const
445{
446 /// Extract the 4th element (if present)
447 return InternalDecode(identifier,3);
448}
449
5eabea87 450//_____________________________________________________________________________
451TMap* AliHistogramCollection::Map() const
452{
453 /// Wrapper to insure proper key formats (i.e. new vs old)
454
455 if (!fMap)
456 {
457 fMap = new TMap;
458 fMap->SetOwnerKeyValue(kTRUE,kTRUE);
459 fMapVersion = 1;
460 }
461 else
462 {
463 if ( fMapVersion < 1 )
464 {
465 // change the keys
466 TIter next(fMap);
467 TObjString* str;
468
469 while ( ( str = static_cast<TObjString*>(next()) ) )
470 {
471 if ( str->String().Contains("./") )
472 {
473 TString newkey(str->String());
474
475 newkey.ReplaceAll("./","");
476
477 TObject* o = fMap->GetValue(str);
478
479 TPair* p = fMap->RemoveEntry(str);
480 if (!p)
481 {
482 AliError("oups oups oups");
483 return 0x0;
484 }
485
486 fMap->Add(new TObjString(newkey.Data()),o);
487
488 delete p;
489 }
490 }
491
492 fMapVersion = 1;
493 }
494 }
495
496 return fMap;
497}
498
d899f664 499//_____________________________________________________________________________
500Long64_t
501AliHistogramCollection::Merge(TCollection* list)
502{
503 // Merge a list of AliHistogramCollection objects with this
504 // Returns the number of merged objects (including this).
505
506 if (!list) return 0;
507
508 if (list->IsEmpty()) return 1;
509
510 TIter next(list);
511 TObject* o;
512 TList mapList;
513 Int_t count(0);
514
515 while ( ( o = next() ) )
516 {
517 AliHistogramCollection* hcol = dynamic_cast<AliHistogramCollection*>(o);
e6e96cea 518 if (!hcol) {
519 AliFatal(Form("object named \"%s\" is a %s instead of an AliHistogramCollection!", o->GetName(), o->ClassName()));
520 continue;
521 }
d899f664 522
523 ++count;
524
5eabea87 525 if ( hcol->fMap ) hcol->Map(); // to insure keys in the new format
526
d899f664 527 TIter nextIdentifier(hcol->fMap);
528 TObjString* identifier;
529
530 while ( ( identifier = static_cast<TObjString*>(nextIdentifier()) ) )
531 {
532 THashList* otherList = static_cast<THashList*>(hcol->fMap->GetValue(identifier->String().Data()));
533
534 TIter nextHisto(otherList);
535 TH1* h;
536
537 while ( ( h = static_cast<TH1*>(nextHisto()) ) )
538 {
5eabea87 539 TString newid(Form("%s%s",identifier->String().Data(),h->GetName()));
540
541 TH1* thisHisto = Histo(newid.Data());
d899f664 542
543 if (!thisHisto)
544 {
5eabea87 545 AliDebug(1,Form("Adopting a new histo = %s%s",identifier->String().Data(),h->GetName()));
d899f664 546
547 // this is an histogram we don't have yet. Let's add it
5eabea87 548
549 Int_t nslashes = TString(newid).CountChar('/');
550
551 Bool_t ok(kFALSE);
552
553 switch (nslashes)
554 {
555 case 2:
556 ok = Adopt(KeyA(identifier->String()),
557 static_cast<TH1*>(h->Clone()));
558 break;
559 case 3:
560 ok = Adopt(KeyA(identifier->String()),
561 KeyB(identifier->String()),
562 static_cast<TH1*>(h->Clone()));
563 break;
564 case 4:
565 ok = Adopt(KeyA(identifier->String()),
566 KeyB(identifier->String()),
567 KeyC(identifier->String()),
568 static_cast<TH1*>(h->Clone()));
569 break;
570 case 5:
571 ok = Adopt(KeyA(identifier->String()),
572 KeyB(identifier->String()),
573 KeyC(identifier->String()),
574 KeyD(identifier->String()),
575 static_cast<TH1*>(h->Clone()));
576 break;
577 default:
578 AliError(Form("Invalid identifier %s",identifier->String().Data()));
579 break;
580 }
581
582 if (!ok)
583 {
584 AliError(Form("Adoption of histogram %s failed",h->GetName()));
585 }
d899f664 586 }
587 else
588 {
589 // add it...
5eabea87 590 AliDebug(1,Form("Merging histo = %s%s (%g vs %g)",
d899f664 591 identifier->String().Data(),
592 h->GetName(),
593 h->GetSumOfWeights(),
594 thisHisto->GetSumOfWeights()));
d899f664 595
5eabea87 596 if ( HistoSameAxis(h,thisHisto) )
597 {
598 thisHisto->Add(h);
599 }
600 else
601 {
602 TList l;
603 l.Add(h);
604
605 thisHisto->Merge(&l);
606 }
d899f664 607 }
608 }
609 }
610 }
611
612 AliDebug(1,Form("count=%d",count));
613
614 return count+1;
615}
616
5eabea87 617//_____________________________________________________________________________
618TString AliHistogramCollection::NormalizeName(const char* identifier,const char* action) const
619{
620 // Replace / by _ to build a root-compliant histo name
621 TString name(identifier);
622 name += "_";
623 name += action;
624 name.ReplaceAll("/","_");
625 return name;
626}
627
d899f664 628//_____________________________________________________________________________
629Int_t
630AliHistogramCollection::NumberOfHistograms() const
631{
632 /// Get the number of histograms we hold
633 TIter next(CreateIterator(this));
634 Int_t n(0);
635 while ( next() ) ++n;
636 return n;
637}
638
639//_____________________________________________________________________________
640Int_t
641AliHistogramCollection::NumberOfKeys() const
642{
643 /// Get the number of keys we have
644 return fMap ? fMap->GetSize() : 0;
645}
646
647//_____________________________________________________________________________
648void
649AliHistogramCollection::Print(Option_t* option) const
650{
651 /// Print all the histograms we hold, in a hopefully visually pleasing
652 /// way.
653 ///
654 /// Option can be used to select given part only, using the schema :
655 /// /*/*/*/*/*
656 /// Where the stars are wilcards for /keyA/keyB/keyC/KeyD/histoname
657 ///
658 /// if * is used it is assumed to be a wildcard for histoname
659 ///
660 /// For other selections the full syntax /*/*/*/*/* must be used.
661 ///
662 /// Use "-" as histoname to disable histogram's name output
663
664 cout << Form("AliHistogramCollection : %d keys and %d histos",
665 NumberOfKeys(), NumberOfHistograms()) << endl;
666
667 if (!strlen(option)) return;
668
669 TString sreKeyA("*");
670 TString sreKeyB("*");
671 TString sreKeyC("*");
672 TString sreKeyD("*");
673 TString sreHistoname("*");
674
675 TObjArray* select = TString(option).Tokenize("/");
676 Int_t n = select->GetLast();
677
678 if (n>=0)
679 {
680 sreHistoname = static_cast<TObjString*>(select->At(n))->String();
681 }
682 if (n>=1)
683 {
684 sreKeyD = static_cast<TObjString*>(select->At(n-1))->String();
685 }
686 if (n>=2)
687 {
688 sreKeyC = static_cast<TObjString*>(select->At(n-2))->String();
689 }
690 if (n>=3)
691 {
692 sreKeyB = static_cast<TObjString*>(select->At(n-3))->String();
693 }
694 if (n>=4)
695 {
696 sreKeyA = static_cast<TObjString*>(select->At(n-3))->String();
697 }
698
699 TRegexp reKeyA(sreKeyA,kTRUE);
700 TRegexp reKeyB(sreKeyB,kTRUE);
701 TRegexp reKeyC(sreKeyC,kTRUE);
702 TRegexp reKeyD(sreKeyD,kTRUE);
703 TRegexp reHistoname(sreHistoname,kTRUE);
704
705 delete select;
706
707 TObjArray* identifiers = SortAllIdentifiers();
5eabea87 708
d899f664 709 TIter nextIdentifier(identifiers);
710
711 TObjString* sid(0x0);
712
713 while ( ( sid = static_cast<TObjString*>(nextIdentifier()) ) )
714 {
715 Bool_t identifierPrinted(kFALSE);
716
717 TString identifier(sid->String());
718
5eabea87 719 if ( ( InternalDecode(identifier,0).Contains(reKeyA) &&
720 InternalDecode(identifier,1).Contains(reKeyB) &&
721 InternalDecode(identifier,2).Contains(reKeyC) &&
722 InternalDecode(identifier,3).Contains(reKeyD) )
d899f664 723 )
724 {
725 if ( sreHistoname == "*" )
726 {
727 identifierPrinted = kTRUE;
728 cout << identifier.Data() << endl;
729 }
730
5eabea87 731 THashList * list = static_cast<THashList*>(Map()->GetValue(sid->String().Data()));
d899f664 732 TObjArray names;
733 names.SetOwner(kTRUE);
734 TIter nextUnsortedHisto(list);
735 TH1* h;
736 while ( ( h = static_cast<TH1*>(nextUnsortedHisto()) ) )
737 {
738 names.Add(new TObjString(h->GetName()));
739 }
740 names.Sort();
741 TIter nextHistoName(&names);
742 TObjString* hname;
743 while ( ( hname = static_cast<TObjString*>(nextHistoName()) ) )
744 {
745 TString histoName(hname->String());
746 if (histoName.Contains(reHistoname) )
747 {
748 h = static_cast<TH1*>(list->FindObject(histoName.Data()));
749 if ( h->GetEntries()==0 && !fMustShowEmptyHistogram ) continue;
750 if (!identifierPrinted)
751 {
752 cout << identifier.Data() << endl;
753 identifierPrinted = kTRUE;
754 }
755 cout << Form(" %s %s Entries=%d Sum=%g",h->GetName(),h->GetTitle(),Int_t(h->GetEntries()),h->GetSumOfWeights()) << endl;
756 }
757 }
758 if (!identifierPrinted && sreHistoname=="-" )
759 {
760 // to handle the case where we used histoname="-" to disable showing the histonames,
761 // but we still want to see the matching keys maybe...
762 cout << identifier.Data() << endl;
763 }
764 }
765 }
766
767 delete identifiers;
768}
769
5eabea87 770//_____________________________________________________________________________
771void
772AliHistogramCollection::PrintMessages(const char* prefix) const
773{
774 /// Print pending messages
775
776 std::map<std::string,int>::const_iterator it;
777
778 for ( it = fMessages.begin(); it != fMessages.end(); ++it )
779 {
780 cout << Form("%s : message %s appeared %5d times",prefix,it->first.c_str(),it->second) << endl;
781 }
782}
783
784
d899f664 785//_____________________________________________________________________________
786UInt_t
787AliHistogramCollection::EstimateSize(Bool_t show) const
788{
789 /// Estimate the memory (in kilobytes) used by our histograms
790
791// sizeof(TH1) + (nbins+2)*(nbytes_per_bin) +name+title_sizes
792// if you have errors add (nbins+2)*8
793
794 TIter next(CreateIterator());
795 TH1* h;
796 UInt_t n(0);
797
798 while ( ( h = static_cast<TH1*>(next()) ) )
799 {
800 Int_t nbins = (h->GetNbinsX()+2);
801
802 if (h->GetNbinsY()>1)
803 {
804 nbins *= (h->GetNbinsY()+2);
805 }
806
807 if (h->GetNbinsZ()>1)
808 {
809 nbins *= (h->GetNbinsZ()+2);
810 }
811
812 Bool_t hasErrors = ( h->GetSumw2N() > 0 );
813
814 TString cname(h->ClassName());
815
816 Int_t nbytesPerBin(0);
817
818 if (cname.Contains(TRegexp("C$")) ) nbytesPerBin = sizeof(Char_t);
819 if (cname.Contains(TRegexp("S$")) ) nbytesPerBin = sizeof(Short_t);
820 if (cname.Contains(TRegexp("I$")) ) nbytesPerBin = sizeof(Int_t);
821 if (cname.Contains(TRegexp("F$")) ) nbytesPerBin = sizeof(Float_t);
822 if (cname.Contains(TRegexp("D$")) ) nbytesPerBin = sizeof(Double_t);
823
824 if (!nbytesPerBin)
825 {
826 AliError(Form("Could not get the number of bytes per bin for histo %s of class %s. Thus the size estimate will be wrong !",
827 h->GetName(),h->ClassName()));
828 continue;
829 }
830
831 UInt_t thissize = sizeof(h) + nbins*(nbytesPerBin) + strlen(h->GetName())
832 + strlen(h->GetTitle());
833
834 if ( hasErrors) thissize += nbins*8;
835
836 n += thissize;
837
838 if ( show )
839 {
840 AliInfo(Form("Size of %30s is %20d bytes",h->GetName(),thissize));
841 }
842 }
843
844 return n;
845}
846
847//_____________________________________________________________________________
848void AliHistogramCollection::PruneEmptyHistograms()
849{
850 /// Delete the empty histograms
5eabea87 851 TIter next(Map());
d899f664 852 TObjString* key;
853
854 TList toBeRemoved;
855 toBeRemoved.SetOwner(kTRUE);
856
857 while ( ( key = static_cast<TObjString*>(next()) ) )
858 {
859 TString identifier(key->String());
5eabea87 860 THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier.Data()));
d899f664 861 TIter nextHisto(hlist);
862 TH1* h;
863 while ( ( h = static_cast<TH1*>(nextHisto())))
864 {
865 if ( h->GetEntries()==0)
866 {
867 toBeRemoved.Add(new TObjString(Form("%s%s",identifier.Data(),h->GetName())));
868 }
869 }
870 }
871
872 TIter nextTBR(&toBeRemoved);
873 while ( ( key = static_cast<TObjString*>(nextTBR()) ) )
874 {
875 Remove(key);
876 }
877}
878
879//_____________________________________________________________________________
880AliHistogramCollection*
5eabea87 881AliHistogramCollection::Project(const char* keyA, const char* keyB, const char* keyC, const char* keyD) const
d899f664 882{
5eabea87 883 /// To be implemented : would create a new collection starting at keyA/keyB/keyC/keyD
884
885 if (!fMap) return 0x0;
886
887 AliHistogramCollection* hc = new AliHistogramCollection(Form("%s %s/%s/%s/%s",GetName(),keyA,keyB,keyC,keyD),
888 GetTitle());
889
890 TIter next(Map());
891 TObjString* str;
892
893 while ( ( str = static_cast<TObjString*>(next()) ) )
894 {
895 TString identifier = str->String();
896
897 Bool_t copy= ( KeyA(identifier) == keyA &&
898 ( strlen(keyB)==0 || KeyB(identifier)==keyB ) &&
899 ( strlen(keyC)==0 || KeyC(identifier)==keyC ) &&
900 ( strlen(keyD)==0 || KeyD(identifier)==keyD ));
901
902 if ( !copy ) continue;
903
904 THashList* list = static_cast<THashList*>(Map()->GetValue(identifier.Data()));
905
906 TIter nextHisto(list);
907 TH1* h;
908
909 while ( ( h = static_cast<TH1*>(nextHisto()) ) )
910 {
911 TH1* hclone = static_cast<TH1*>(h->Clone());
912
913 TString newkey(identifier.Data());
914
915 if ( strlen(keyD) > 0 ) newkey.ReplaceAll(Form("/%s",keyD),"");
916 if ( strlen(keyC) > 0 ) newkey.ReplaceAll(Form("/%s",keyC),"");
917 if ( strlen(keyB) > 0 ) newkey.ReplaceAll(Form("/%s",keyB),"");
918 if ( strlen(keyA) > 0 ) newkey.ReplaceAll(Form("/%s",keyA),"");
919
920 if (newkey=="/") newkey="";
921
922 hc->InternalAdopt(newkey.Data(),hclone);
923 }
924 }
925
926 return hc;
d899f664 927}
928
929//_____________________________________________________________________________
930TObject*
931AliHistogramCollection::Remove(TObject* key)
932{
933 ///
934 /// Remove a given histogram (given its key=full identifier=/keyA/keyB/keyC/keyD/histoname)
935 ///
936 /// Note that we do *not* remove the /keyA/keyB/keyC/keyD entry even if there's no
937 /// more histogram for this triplet.
938 ///
939 /// Not very efficient. Could be improved ?
940 ///
941
942 TObjString* str = dynamic_cast<TObjString*>(key);
943
944 if (!str)
945 {
946 AliError(Form("key is not of the expected TObjString type, but of %s",key->ClassName()));
947 return 0x0;
948 }
949
950 TString identifier(str->String());
951
5eabea87 952 Int_t nslashes = TString(identifier).CountChar('/');
953
954 TString skey;
955
956 switch (nslashes )
957 {
958 case 2:
959 skey = Form("/%s/",
960 KeyA(identifier).Data());
961 break;
962 case 3:
963 skey = Form("/%s/%s/",
964 KeyA(identifier).Data(),
965 KeyB(identifier).Data());
966 break;
967 case 4:
968 skey = Form("/%s/%s/%s/",
969 KeyA(identifier).Data(),
970 KeyB(identifier).Data(),
971 KeyC(identifier).Data());
972 break;
973 case 5:
974 skey = Form("/%s/%s/%s/%s/",
975 KeyA(identifier).Data(),
976 KeyB(identifier).Data(),
977 KeyC(identifier).Data(),
978 KeyD(identifier).Data()
979 );
980 break;
981 default:
982 AliError("Oups");
983 break;
984 };
d899f664 985
5eabea87 986 THashList* hlist = dynamic_cast<THashList*>(Map()->GetValue(skey.Data()));
d899f664 987
988 if (!hlist)
989 {
990 AliWarning(Form("Could not get hlist for key=%s",skey.Data()));
991 return 0x0;
992 }
993
994 TH1* h = InternalHisto(skey,HistoName(identifier.Data()));
995 if (!h)
996 {
997 AliError(Form("Could not find histo %s",identifier.Data()));
998 return 0x0;
999 }
1000
1001 TObject* o = hlist->Remove(h);
1002 if (!o)
1003 {
1004 AliError("Remove failed");
1005 return 0x0;
1006 }
1007
1008// if ( hlist->IsEmpty() )
1009// {
1010// // we should remove the key as well
1011// TObject* k = fMap->Remove(key);
1012// if (!k)
1013// {
1014// AliError("Removal of the key failed");
1015// }
1016// }
1017
1018 return o;
1019}
1020
5eabea87 1021//______________________________________________________________________________
1022Bool_t AliHistogramCollection::HistoSameAxis(TH1 *h0, TH1 *h1) const
1023{
1024 // shameless copy from TProofPlayerRemote::HistoSameAxis
1025 //
1026 // Return kTRUE is the histograms 'h0' and 'h1' have the same binning and ranges
1027 // on the axis (i.e. if they can be just Add-ed for merging).
1028
1029 Bool_t rc = kFALSE;
1030 if (!h0 || !h1) return rc;
1031
1032 TAxis *a0 = 0, *a1 = 0;
1033
1034 // Check X
1035 a0 = h0->GetXaxis();
1036 a1 = h1->GetXaxis();
1037 if (a0->GetNbins() == a1->GetNbins())
1038 if (TMath::Abs(a0->GetXmax() - a1->GetXmax()) < 1.e-9)
1039 if (TMath::Abs(a0->GetXmin() - a1->GetXmin()) < 1.e-9) rc = kTRUE;
1040
1041 // Check Y, if needed
1042 if (h0->GetDimension() > 1) {
1043 rc = kFALSE;
1044 a0 = h0->GetYaxis();
1045 a1 = h1->GetYaxis();
1046 if (a0->GetNbins() == a1->GetNbins())
1047 if (TMath::Abs(a0->GetXmax() - a1->GetXmax()) < 1.e-9)
1048 if (TMath::Abs(a0->GetXmin() - a1->GetXmin()) < 1.e-9) rc = kTRUE;
1049 }
1050
1051 // Check Z, if needed
1052 if (h0->GetDimension() > 2) {
1053 rc = kFALSE;
1054 a0 = h0->GetZaxis();
1055 a1 = h1->GetZaxis();
1056 if (a0->GetNbins() == a1->GetNbins())
1057 if (TMath::Abs(a0->GetXmax() - a1->GetXmax()) < 1.e-9)
1058 if (TMath::Abs(a0->GetXmin() - a1->GetXmin()) < 1.e-9) rc = kTRUE;
1059 }
1060
1061 // Done
1062 return rc;
1063}
1064
d899f664 1065//_____________________________________________________________________________
1066TObjArray*
1067AliHistogramCollection::SortAllIdentifiers() const
1068{
1069 /// Sort our internal identifiers. Returned array must be deleted.
1070 TObjArray* identifiers = new TObjArray;
1071 identifiers->SetOwner(kFALSE);
5eabea87 1072 TIter next(Map());
d899f664 1073 TObjString* sid;
1074
1075 while ( ( sid = static_cast<TObjString*>(next()) ) )
1076 {
1077 if ( !identifiers->FindObject(sid->String().Data()) )
1078 {
1079 identifiers->Add(sid);
1080 }
1081 }
1082 identifiers->Sort();
1083 return identifiers;
1084}
1085
1086
1087///////////////////////////////////////////////////////////////////////////////
1088//
1089// AliHistogramCollectionIterator
1090//
1091///////////////////////////////////////////////////////////////////////////////
1092
1093class AliHistogramCollectionIterator;
1094
1095//_____________________________________________________________________________
1096AliHistogramCollectionIterator::AliHistogramCollectionIterator(const AliHistogramCollection* hcol, Bool_t dir)
1097: fkHistogramCollection(hcol), fMapIterator(0x0), fHashListIterator(0x0), fDirection(dir)
1098{
1099 /// Default ctor
1100}
1101
1102//_____________________________________________________________________________
1103AliHistogramCollectionIterator&
1104AliHistogramCollectionIterator::operator=(const TIterator&)
1105{
1106 /// Overriden operator= (imposed by Root's declaration of TIterator ?)
1107 Fatal("TIterator::operator=","Not implementeable"); // because there's no clone in TIterator :-(
1108 return *this;
1109}
1110
1111//_____________________________________________________________________________
1112AliHistogramCollectionIterator::~AliHistogramCollectionIterator()
1113{
1114 /// dtor
1115 Reset();
1116}
1117
1118//_____________________________________________________________________________
1119TObject* AliHistogramCollectionIterator::Next()
1120{
1121 /// Advance to next object in the collection
1122
1123 if (!fHashListIterator)
1124 {
1125 if ( !fMapIterator )
1126 {
1127 fMapIterator = fkHistogramCollection->fMap->MakeIterator(fDirection);
1128 }
1129 TObjString* key = static_cast<TObjString*>(fMapIterator->Next());
1130 if (!key)
1131 {
1132 // we are done
1133 return 0x0;
1134 }
5eabea87 1135 THashList* list = static_cast<THashList*>(fkHistogramCollection->Map()->GetValue(key->String().Data()));
d899f664 1136 if (!list) return 0x0;
1137 fHashListIterator = list->MakeIterator(fDirection);
1138 }
1139
1140 TObject* o = fHashListIterator->Next();
1141
1142 if (!o)
1143 {
1144 delete fHashListIterator;
1145 fHashListIterator = 0x0;
1146 return Next();
1147 }
1148
1149 return o;
1150}
1151
1152//_____________________________________________________________________________
1153void AliHistogramCollectionIterator::Reset()
1154{
1155 /// Reset the iterator
1156 delete fHashListIterator;
1157 delete fMapIterator;
1158}