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