1 /**************************************************************************
2 * Copyright(c) 1998-2007, 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 //-----------------------------------------------------------------------------
17 /// \class AliCounterCollection
19 /// generic class to handle a collection of counters
21 /// \author Philippe Pillot
22 //-----------------------------------------------------------------------------
24 #include "AliCounterCollection.h"
29 #include <TObjString.h>
30 #include <TObjArray.h>
31 #include <THnSparse.h>
32 #include <THashList.h>
36 #include <TCollection.h>
38 ClassImp(AliCounterCollection)
40 //-----------------------------------------------------------------------
41 AliCounterCollection::AliCounterCollection(const char* name) :
43 fRubrics(new THashList(10)),
44 fRubricsSize(new TArrayI(10)),
51 //-----------------------------------------------------------------------
52 AliCounterCollection::~AliCounterCollection()
60 //-----------------------------------------------------------------------
61 void AliCounterCollection::Clear(Option_t*)
65 fRubricsSize->Reset();
66 delete fCounters; fCounters = 0x0;
69 //-----------------------------------------------------------------------
70 void AliCounterCollection::AddRubric(TString name, TString listOfKeyWords)
72 /// Add a new rubric with the complete list of related key words separated by "/".
73 /// If the key word "any" is not defined, the overall statistics is
74 /// assumed to be the sum of the statistics under each key word.
77 listOfKeyWords.ToUpper();
79 if (fRubrics->Contains(name.Data())) {
80 AliError(Form("rubric named %s already exist",name.Data()));
84 // add the list of autorized key words
85 TObjArray* rubric = listOfKeyWords.Tokenize("/");
86 CleanListOfStrings(rubric);
87 rubric->SetName(name.Data());
88 Int_t nRubrics = fRubrics->GetSize();
89 rubric->SetUniqueID(nRubrics);
90 fRubrics->AddLast(rubric);
92 // save the number of autorized key words (expand the array if needed)
93 if (nRubrics+1 > fRubricsSize->GetSize()) fRubricsSize->Set(2*fRubricsSize->GetSize());
94 (*fRubricsSize)[nRubrics] = rubric->GetEntriesFast();
97 //-----------------------------------------------------------------------
98 void AliCounterCollection::AddRubric(TString name, Int_t maxNKeyWords)
100 /// Add a new rubric containing at maximum maxNKeyWords key words.
101 /// Key words will be added as the counters get filled until the maximum is reached.
102 /// If the key word "any" is never defined, the overall statistics is
103 /// assumed to be the sum of the statistics under each key word.
107 if (fRubrics->Contains(name.Data())) {
108 AliError(Form("rubric named %s already exist",name.Data()));
112 // create the empty rubric
113 TObjString* rubric = new TObjString(name.Data());
114 Int_t nRubrics = fRubrics->GetSize();
115 rubric->SetUniqueID(nRubrics);
116 fRubrics->AddLast(rubric);
118 // save the maximum number of autorized key words
119 if (nRubrics+1 > fRubricsSize->GetSize()) fRubricsSize->Set(2*fRubricsSize->GetSize());
120 (*fRubricsSize)[nRubrics] = maxNKeyWords;
123 //-----------------------------------------------------------------------
124 void AliCounterCollection::Init()
126 /// Initialize the internal counters from the added rubrics.
128 // create the counters
130 fCounters = new THnSparseT<TArrayI>("hCounters", "hCounters", fRubrics->GetSize(), fRubricsSize->GetArray(), 0x0, 0x0);
133 TObject* rubric = 0x0;
134 TIter nextRubric(fRubrics);
135 while ((rubric = nextRubric())) {
136 TAxis* axis = fCounters->GetAxis((Int_t)rubric->GetUniqueID());
139 axis->SetName(rubric->GetName());
141 // set labels if already known
142 TObjArray* keyWords = dynamic_cast<TObjArray*>(rubric);
144 TObjString* label = 0x0;
146 TIter nextLabel(keyWords);
147 while ((label = static_cast<TObjString*>(nextLabel()))) axis->SetBinLabel(bin++, label->String().Data());
154 //-----------------------------------------------------------------------
155 const Int_t* AliCounterCollection::FindBins(const TString& externalKey, Bool_t allocate, Int_t& nEmptySlots)
157 /// Return the corresponding bins ordered by rubric or 0x0 if externalKey is not valid.
158 /// The externalKey format must be rubric:keyWord/rubric:keyWord/rubric:keyWord/...
159 /// If allocate = kTRUE, new key words are added to the corresponding rubric if possible.
160 /// If a rubric is not filled in, the coresponding slot contain -1 in the array.
161 /// It is the responsability of the user to delete the returned array.
163 // produce an empty array of keys
164 Int_t nRubrics = fRubrics->GetSize();
165 Int_t* bins = new Int_t[nRubrics];
166 memset(bins, -1, sizeof(Int_t) * nRubrics);
167 nEmptySlots = nRubrics;
168 Bool_t isValid = kTRUE;
170 // get the list of rubric:keyWord pairs
171 TObjArray* rubricKeyPairs = externalKey.Tokenize("/");
173 // loop over each rubric:keyWord pair
174 TObjString* pair = 0x0;
175 TIter next(rubricKeyPairs);
176 while ((pair = static_cast<TObjString*>(next()))) {
178 // get both rubric and associated key word
179 TObjArray* rubricKeyPair = pair->String().Tokenize(":");
181 // check the format of the pair
182 if (rubricKeyPair->GetEntriesFast() != 2) {
183 AliError("invalid key format");
185 delete rubricKeyPair;
189 // get the axis corresponding to that rubric
190 Int_t dim = FindDim(static_cast<TObjString*>(rubricKeyPair->UncheckedAt(0))->String());
193 delete rubricKeyPair;
197 // find the bin corresponding to that key word
198 Int_t bin = FindBin(dim, static_cast<TObjString*>(rubricKeyPair->UncheckedAt(1))->String(), allocate);
201 delete rubricKeyPair;
205 // check if the array of keys already contains something for that rubric
206 if (bins[dim] >= 0) {
207 AliWarning("key already given for that rubric --> ignored");
208 delete rubricKeyPair;
212 // store the corresponding bin for that slot
217 delete rubricKeyPair;
220 // delete the array in case of problem
224 nEmptySlots = nRubrics;
228 delete rubricKeyPairs;
233 //-----------------------------------------------------------------------
234 Int_t AliCounterCollection::FindDim(const TString& rubricName) const
236 /// Return the dimension corresponding to that rubric (or -1 in case of failure).
237 TObject* rubric = fRubrics->FindObject(rubricName.Data());
239 AliError(Form("invalid rubric: %s",rubricName.Data()));
242 return (Int_t) rubric->GetUniqueID();
245 //-----------------------------------------------------------------------
246 Int_t AliCounterCollection::FindBin(Int_t dim, const TString& keyWord, Bool_t allocate)
248 /// Return the bin number corresponding to that key word (or -1 in case of failure).
249 /// If allocate = kTRUE, try to add the key word if possible.
251 TAxis* axis = fCounters->GetAxis(dim);
253 // look for the bin corresponding to keyWord
254 THashList* labels = axis->GetLabels();
255 TObjString* label = (labels) ? static_cast<TObjString*>(labels->FindObject(keyWord.Data())) : 0x0;
256 Int_t bin = (label) ? (Int_t)label->GetUniqueID() : -1;
258 // in case the keyWord does not exist, try to add it if required
259 if (bin<0 && allocate) {
260 Int_t nLabels = (labels) ? labels->GetSize() : 0;
261 if (nLabels < axis->GetNbins()) {
263 axis->SetBinLabel(bin, keyWord.Data());
267 if (bin<0) AliError(Form("invalid key word: %s:%s",axis->GetName(),keyWord.Data()));
272 //-----------------------------------------------------------------------
273 void AliCounterCollection::CleanListOfStrings(TObjArray* list)
275 /// Make sure all strings appear only once in this list
277 // remove multiple-occurrence
278 Int_t nEntries = list->GetEntriesFast();
279 for (Int_t i = 0; i < nEntries; i++) {
280 TObjString* entry1 = static_cast<TObjString*>(list->UncheckedAt(i));
281 if (!entry1) continue;
282 for (Int_t j = i+1; j < nEntries; j++) {
283 TObjString* entry2 = static_cast<TObjString*>(list->UncheckedAt(j));
284 if (entry2 && entry2->IsEqual(entry1)) {
285 AliWarning(Form("multiple-occurence of string \"%s\" --> removed",entry2->String().Data()));
291 // remove empty slots
295 //-----------------------------------------------------------------------
296 void AliCounterCollection::Count(TString externalKey, Int_t value)
298 /// Add "value" to the counter referenced by "externalKey".
299 /// The externalKey format must be rubric:keyWord/rubric:keyWord/rubric:keyWord/...
301 if (value < 1) return;
303 AliError("counters are not initialized");
307 externalKey.ToUpper();
309 // convert external to internal key
310 Int_t nEmptySlots = 0;
311 const Int_t* bins = FindBins(externalKey, kTRUE, nEmptySlots);
314 // check for empty slots
315 if (nEmptySlots > 0) {
316 AliError("incomplete key");
321 // increment the corresponding counter
322 fCounters->AddBinContent(bins, (Double_t)value);
328 //-----------------------------------------------------------------------
329 void AliCounterCollection::Print(const Option_t* opt) const
331 /// Print every individual counters if opt=="", else call "Print(TString rubrics=opt, TString selections="")".
333 if (strcmp(opt,"")) {
334 const_cast<AliCounterCollection*>(this)->Print(opt, "");
339 AliError("counters are not initialized");
343 if (fCounters->GetNbins() == 0) {
344 printf("\nall counters are empty\n\n");
348 Int_t nRubrics = fCounters->GetNdimensions();
349 Int_t* bins = new Int_t[nRubrics];
351 // loop over every filled counters
352 for (Long64_t i=0; i<fCounters->GetNbins(); ++i) {
354 // get the content of the bin
355 Int_t value = (Int_t) fCounters->GetBinContent(i, bins);
357 // build the corresponding counter name
359 for (Int_t j=0; j<nRubrics; j++) counter += Form("/%s",fCounters->GetAxis(j)->GetBinLabel(bins[j]));
363 printf("\n%s %d", counter.Data(), value);
371 //-----------------------------------------------------------------------
372 void AliCounterCollection::PrintKeyWords() const
374 /// Print the full list of key words.
377 AliError("counters are not initialized");
382 Int_t nRubrics = fCounters->GetNdimensions();
383 for (Int_t iDim=0; iDim<nRubrics; iDim++) {
384 TAxis* axis = fCounters->GetAxis(iDim);
386 // print rubric's name
387 printf("\n%s:", axis->GetName());
389 // loop over key words
390 Bool_t first = kTRUE;
391 TObjString* label = 0x0;
392 TIter nextLabel(axis->GetLabels());
393 while ((label = static_cast<TObjString*>(nextLabel()))) {
395 //print key word's name
397 printf("%s", label->String().Data());
399 } else printf(",%s", label->String().Data());
406 //-----------------------------------------------------------------------
407 void AliCounterCollection::PrintValue(TString selections)
409 /// Print value of selected counter.
412 AliError("counters are not initialized");
416 selections.ToUpper();
418 // convert external to internal key
419 Int_t nEmptySlots = 0;
420 const Int_t* selectedBins = FindBins(selections, kFALSE, nEmptySlots);
421 if (!selectedBins) return;
423 // check for empty slots
424 if (nEmptySlots > 0) {
425 AliError("incomplete key");
426 delete[] selectedBins;
431 printf("\n%d\n\n", (Int_t) fCounters->GetBinContent(selectedBins));
434 delete[] selectedBins;
437 //-----------------------------------------------------------------------
438 void AliCounterCollection::Print(TString rubrics, TString selections)
440 /// Print desired rubrics for the given selection:
441 /// - format of "rubrics" is rubric1/rubric2/.. (order matters only for output).
442 /// - format of "selections" is rubric:keyWord/rubric:keyWord/.. (order does not matter).
443 /// If "data" contains 1 rubric, the output will be one counter for each element of that rubric.
444 /// If "data" contains 2 rubrics, the output will be an array of counters, rubric1 vs rubric2.
445 /// If "data" contains 3 rubrics, the output will be an array rubric1 vs rubric2 for each element in rubric3.
447 /// Results are integrated over rubrics not specified neither in "rubrics" nor in "selections".
450 AliError("counters are not initialized");
455 selections.ToUpper();
457 // get the rubrics to print
458 TObjArray* rubricsToPrint = rubrics.Tokenize("/");
459 if (rubricsToPrint->GetEntriesFast() == 0) {
460 delete rubricsToPrint;
464 // remove rubrics called twice
465 CleanListOfStrings(rubricsToPrint);
467 // project counters in the rubrics to print according to the selections
468 TObject* hist = Projection(*rubricsToPrint, selections);
470 delete rubricsToPrint;
475 Int_t nRubricsToPrint = rubricsToPrint->GetEntriesFast();
476 if (nRubricsToPrint == 1 && (static_cast<TH1D*>(hist))->Integral() > 0.)
477 PrintList(static_cast<TH1D*>(hist));
478 else if (nRubricsToPrint == 2 && (static_cast<TH2D*>(hist))->Integral() > 0.)
479 PrintArray(static_cast<TH2D*>(hist));
480 else if (nRubricsToPrint > 2 && (static_cast<THnSparse*>(hist))->GetNbins() > 0)
481 PrintListOfArrays(static_cast<THnSparse*>(hist));
483 printf("\nselected counters are empty\n\n");
486 delete rubricsToPrint;
490 //-----------------------------------------------------------------------
491 void AliCounterCollection::PrintSum(TString rubric, TString selections)
493 /// Print the overall statistics under the given rubric for the given selection:
494 /// - format of "selections" is rubric:keyWord/rubric:keyWord/.. (order does not matter).
495 /// Result is integrated over rubrics not specified neither in "rubric" nor in "selections".
498 AliError("counters are not initialized");
503 selections.ToUpper();
505 // fill the rubric to sum
506 TObjArray rubricsToSum(1);
507 rubricsToSum.SetOwner();
508 rubricsToSum.AddLast(new TObjString(rubric.Data()));
510 // project counters in the rubric to sum according to the selections
511 TH1D* hist = static_cast<TH1D*>(Projection(rubricsToSum, selections));
514 // check for empty rubric
515 THashList* labels = hist->GetXaxis()->GetLabels();
521 // print the sum of counters under that rubric
522 TObjString* any = static_cast<TObjString*>(labels->FindObject("ANY"));
523 if (any) printf("\n%d\n\n", (Int_t) hist->GetBinContent((Int_t)any->GetUniqueID()));
524 else printf("\n%d\n\n", (Int_t) hist->Integral());
530 //-----------------------------------------------------------------------
531 void AliCounterCollection::PrintList(const TH1D* hist) const
533 /// Print the content of 1D histogram as a list.
535 // set the format to print labels
536 THashList* labels = hist->GetXaxis()->GetLabels();
537 TString format(Form("\n%%%ds %%9d",GetMaxLabelSize(labels)));
539 // print value for each label
540 TObjString* label = 0x0;
541 TIter nextLabel(labels);
542 while ((label = static_cast<TObjString*>(nextLabel()))) {
543 Int_t bin = (Int_t) label->GetUniqueID();
544 printf(format.Data(), label->String().Data(), (Int_t) hist->GetBinContent(bin));
549 //-----------------------------------------------------------------------
550 void AliCounterCollection::PrintArray(const TH2D* hist) const
552 /// Print the content of 2D histogram as an array.
554 // set the format to print labels in X direction
555 THashList* labelsX = hist->GetXaxis()->GetLabels();
556 TString formatX(Form("\n%%%ds ",GetMaxLabelSize(labelsX)));
558 // set the format to print labels in Y direction and values
559 THashList* labelsY = hist->GetYaxis()->GetLabels();
560 Int_t maxLabelSizeY = TMath::Max(9, GetMaxLabelSize(labelsY));
561 TString formatYs(Form("%%%ds ",maxLabelSizeY));
562 TString formatYd(Form("%%%dd ",maxLabelSizeY));
564 // print labels in Y axis
565 printf(formatX.Data()," ");
566 TObjString* labelY = 0x0;
567 TIter nextLabelY(labelsY);
568 while ((labelY = static_cast<TObjString*>(nextLabelY())))
569 printf(formatYs.Data(), labelY->String().Data());
571 // fill array for each label in X axis
572 TObjString* labelX = 0x0;
573 TIter nextLabelX(labelsX);
574 while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
575 Int_t binX = (Int_t) labelX->GetUniqueID();
578 printf(formatX.Data(), labelX->String().Data());
580 // print value for each label in Y axis
582 while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
583 Int_t binY = (Int_t) labelY->GetUniqueID();
584 printf(formatYd.Data(), (Int_t) hist->GetBinContent(binX, binY));
590 //-----------------------------------------------------------------------
591 void AliCounterCollection::PrintListOfArrays(const THnSparse* hist) const
593 /// Print the content of nD histogram as a list of arrays.
595 // set the format to print labels in X direction
596 THashList* labelsX = hist->GetAxis(0)->GetLabels();
597 TString formatX(Form("\n%%%ds ",GetMaxLabelSize(labelsX)));
599 // set the format to print labels in Y direction and values
600 THashList* labelsY = hist->GetAxis(1)->GetLabels();
601 Int_t maxLabelSizeY = TMath::Max(9, GetMaxLabelSize(labelsY));
602 TString formatYs(Form("%%%ds ",maxLabelSizeY));
603 TString formatYd(Form("%%%dd ",maxLabelSizeY));
605 // create a list containing each combination of labels refering the arrays to be printout
607 listOfCombis.SetOwner();
609 // add a first empty combination
610 Int_t nDim = hist->GetNdimensions();
611 listOfCombis.AddLast(new TObjArray(nDim-2));
613 // loop over the nDim-2 other rubrics
614 for (Int_t i=2; i<nDim; i++) {
616 // save the last label of that rubic
617 THashList* labels = hist->GetAxis(i)->GetLabels();
618 TObjString* lastLabel = (labels) ? static_cast<TObjString*>(labels->Last()) : 0x0;
619 if (!lastLabel) return;
621 // prepare iteration over the list of labels
622 TIter nextLabel(labels);
624 // loop over existing combinations
625 TObjLink* lnk = listOfCombis.FirstLink();
628 // get the current combination
629 TObjArray* currentCombi = static_cast<TObjArray*>(lnk->GetObject());
631 // loop over labels in the current rubric
633 TObjString* label = 0x0;
634 while ((label = static_cast<TObjString*>(nextLabel()))) {
636 // stop at the last one
637 if (label == lastLabel) break;
639 // copy the current combination, add the current label to it and add it to the list of combinations
640 TObjArray* combi = new TObjArray(*currentCombi);
641 combi->AddLast(label);
642 listOfCombis.AddBefore(lnk, combi);
645 // add the last label to the current combination
646 currentCombi->AddLast(lastLabel);
653 // create bin coordinates to access individual counters
654 Int_t* bins = new Int_t[nDim];
656 // loop over each combination of labels
657 TObjArray* combi = 0x0;
658 TIter nextCombi(&listOfCombis);
659 while ((combi = static_cast<TObjArray*>(nextCombi()))) {
661 // make the name of the combination and fill the corresponding bin coordinates
662 TString combiName = "/";
663 for (Int_t i=2; i<nDim; i++) {
664 TObjString* label = static_cast<TObjString*>(combi->UncheckedAt(i-2));
665 combiName += Form("%s/",label->String().Data());
666 bins[i] = (Int_t)label->GetUniqueID();
670 Bool_t empty = kTRUE;
671 TObjString* labelX = 0x0;
672 TObjString* labelY = 0x0;
673 TIter nextLabelX(labelsX);
674 TIter nextLabelY(labelsY);
675 while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
676 bins[0] = (Int_t) labelX->GetUniqueID();
678 while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
679 bins[1] = (Int_t) labelY->GetUniqueID();
680 if (((Int_t) hist->GetBinContent(bins)) > 0) {
689 // print the name of the combination of labels refering the incoming array
690 printf("\n%s:\n",combiName.Data());
692 // print labels in Y axis
693 printf(formatX.Data()," ");
695 while ((labelY = static_cast<TObjString*>(nextLabelY())))
696 printf(formatYs.Data(), labelY->String().Data());
698 // fill array for each label in X axis
700 while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
701 bins[0] = (Int_t) labelX->GetUniqueID();
704 printf(formatX.Data(), labelX->String().Data());
706 // print value for each label in Y axis
708 while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
709 bins[1] = (Int_t) labelY->GetUniqueID();
710 printf(formatYd.Data(), (Int_t) hist->GetBinContent(bins));
720 //-----------------------------------------------------------------------
721 Int_t AliCounterCollection::GetMaxLabelSize(THashList* labels) const
723 /// Return the number of characters of the longest label.
724 Int_t maxLabelSize = 0;
725 TObjString* label = 0x0;
726 TIter nextLabel(labels);
727 while ((label = static_cast<TObjString*>(nextLabel())))
728 maxLabelSize = TMath::Max(maxLabelSize, label->String().Length());
732 //-----------------------------------------------------------------------
733 TH1D* AliCounterCollection::Draw(TString rubric, TString selections)
735 /// Draw counters of the rubric "rubric" for the given "selection".
736 /// Format of "selections" is rubric:keyWord/rubric:keyWord/.. (order does not matter).
737 /// Results are integrated over rubrics not specified neither in "rubric1" nor in "selections".
738 /// It is the responsability of the user to delete the returned histogram.
741 AliError("counters are not initialized");
746 selections.ToUpper();
748 // fill the rubrics to print
749 TObjArray rubricsToPrint(1);
750 rubricsToPrint.SetOwner();
751 rubricsToPrint.AddLast(new TObjString(rubric.Data()));
753 // project counters in the rubrics to print according to the selections
754 TH1D* hist = static_cast<TH1D*>(Projection(rubricsToPrint, selections));
761 hist->SetStats(kFALSE);
764 TString title = "Selections: ";
765 selections.Remove(TString::kBoth, '/');
766 if (selections.Length() > 0) title += Form("%s/", selections.Data());
768 TIter nextRubric(fRubrics);
769 while ((rub = nextRubric())) {
770 if (selections.Contains(Form("%s:",rub->GetName()))) continue;
771 if (rubricsToPrint.Contains(rub->GetName())) continue;
772 title += Form("%s:ANY/", rub->GetName());
774 title.ReplaceAll("/", " ");
775 hist->SetTitle(title.Data());
778 TAxis* axis = hist->GetXaxis();
779 THashList* labels = axis->GetLabels();
780 Int_t nLabels = (labels) ? labels->GetSize() : 1;
781 axis->SetRange(1,nLabels);
782 axis->SetNdivisions(1,kFALSE);
783 axis->SetTitle(rubric.Data());
786 hist->GetYaxis()->SetTitle("Counts");
792 //-----------------------------------------------------------------------
793 TH2D* AliCounterCollection::Draw(TString rubric1, TString rubric2, TString selections)
795 /// Draw counters of the "rubric1" vs "rubric2" for the given "selection".
796 /// Format of "selections" is rubric:keyWord/rubric:keyWord/.. (order does not matter).
797 /// Results are integrated over rubrics not specified neither in "rubric1", "rubric2" nor in "selections".
798 /// It is the responsability of the user to delete the returned histogram.
801 AliError("counters are not initialized");
807 selections.ToUpper();
809 // fill the rubrics to print
810 TObjArray rubricsToPrint(2);
811 rubricsToPrint.SetOwner();
812 rubricsToPrint.AddLast(new TObjString(rubric2.Data()));
813 rubricsToPrint.AddLast(new TObjString(rubric1.Data()));
815 // project counters in the rubrics to print according to the selections
816 TH2D* hist = static_cast<TH2D*>(Projection(rubricsToPrint, selections));
823 hist->SetStats(kFALSE);
826 TString title = "Selections: ";
827 selections.Remove(TString::kBoth, '/');
828 if (selections.Length() > 0) title += Form("%s/", selections.Data());
830 TIter nextRubric(fRubrics);
831 while ((rub = nextRubric())) {
832 if (selections.Contains(Form("%s:",rub->GetName()))) continue;
833 if (rubricsToPrint.Contains(rub->GetName())) continue;
834 title += Form("%s:ANY/", rub->GetName());
836 title.ReplaceAll("/", " ");
837 hist->SetTitle(title.Data());
840 TAxis* axisX = hist->GetXaxis();
841 THashList* labelsX = axisX->GetLabels();
842 Int_t nLabelsX = (labelsX) ? labelsX->GetSize() : 1;
843 axisX->SetRange(1,nLabelsX);
844 axisX->SetNdivisions(1,kFALSE);
845 axisX->SetTitle(rubric2.Data());
848 TAxis* axisY = hist->GetYaxis();
849 THashList* labelsY = axisY->GetLabels();
850 Int_t nLabelsY = (labelsY) ? labelsY->GetSize() : 1;
851 axisY->SetRange(1,nLabelsY);
852 axisY->SetNdivisions(1,kFALSE);
853 axisY->SetTitle(rubric1.Data());
859 //-----------------------------------------------------------------------
860 TObject* AliCounterCollection::Projection(const TObjArray& data, const TString& selections)
862 /// Return desired "data" for the given "selection" stored in a new histogram or 0x0 in case of failure.
863 /// The type of the histogram (TH1D, TH2D or THnSparse) depend on the number of data.
864 /// It is the responsability of the user to delete the returned histogram.
866 // get the corresponding dimensions
867 Int_t nTargetDim = data.GetEntriesFast();
868 Int_t* targetDims = new Int_t[nTargetDim];
869 for (Int_t i=0; i<nTargetDim; i++) {
870 targetDims[i] = FindDim(static_cast<TObjString*>(data.UncheckedAt(i))->String());
871 if (targetDims[i] < 0) {
877 // find bins to select
878 Int_t nEmptySlots = 0;
879 const Int_t* selectedBins = FindBins(selections, kFALSE, nEmptySlots);
885 // apply selection for each rubric
886 Int_t nRubrics = fCounters->GetNdimensions();
887 for (Int_t iDim=0; iDim<nRubrics; iDim++) {
888 TAxis* axis = fCounters->GetAxis(iDim);
890 // select the desired key word
891 if (selectedBins[iDim] >= 0) axis->SetRange(selectedBins[iDim], selectedBins[iDim]);
893 // or select all key words
894 else if (data.Contains(axis->GetName())) axis->SetRange();
896 // or integrate over all cases
898 THashList* labels = axis->GetLabels();
899 TObjString* label = (labels) ? static_cast<TObjString*>(labels->FindObject("ANY")) : 0x0;
900 Int_t binAny = (label) ? (Int_t)label->GetUniqueID() : -1;
901 if (binAny >= 0) axis->SetRange(binAny, binAny);
902 else axis->SetRange();
908 if (nTargetDim == 1) {
910 // project counters to TH1D
911 hist = fCounters->Projection(targetDims[0]);
913 // reset bin labels lost when producing TH1D
914 if (selectedBins[targetDims[0]] >= 0)
915 static_cast<TH1D*>(hist)->GetXaxis()->SetBinLabel(1, fCounters->GetAxis(targetDims[0])->GetBinLabel(selectedBins[targetDims[0]]));
918 TIter nextLabel(fCounters->GetAxis(targetDims[0])->GetLabels());
919 while ((label = static_cast<TObjString*>(nextLabel())))
920 static_cast<TH1D*>(hist)->GetXaxis()->SetBinLabel((Int_t)label->GetUniqueID(), label->String().Data());
923 } else if (nTargetDim == 2) {
925 // project counters to TH2D (warning X and Y inverted in THnSparse::Projection(X,Y))
926 hist = fCounters->Projection(targetDims[1], targetDims[0]);
928 // reset bin labels in X axis lost when producing TH2D
929 if (selectedBins[targetDims[0]] >= 0)
930 static_cast<TH2D*>(hist)->GetXaxis()->SetBinLabel(1, fCounters->GetAxis(targetDims[0])->GetBinLabel(selectedBins[targetDims[0]]));
933 TIter nextLabel(fCounters->GetAxis(targetDims[0])->GetLabels());
934 while ((label = static_cast<TObjString*>(nextLabel())))
935 static_cast<TH2D*>(hist)->GetXaxis()->SetBinLabel((Int_t)label->GetUniqueID(), label->String().Data());
938 // reset bin labels in Y axis lost when producing TH2D
939 if (selectedBins[targetDims[1]] >= 0)
940 static_cast<TH2D*>(hist)->GetYaxis()->SetBinLabel(1, fCounters->GetAxis(targetDims[1])->GetBinLabel(selectedBins[targetDims[1]]));
943 TIter nextLabel(fCounters->GetAxis(targetDims[1])->GetLabels());
944 while ((label = static_cast<TObjString*>(nextLabel())))
945 static_cast<TH2D*>(hist)->GetYaxis()->SetBinLabel((Int_t)label->GetUniqueID(), label->String().Data());
950 // project counters to THnSparse (labels are not lost in that case)
951 hist = fCounters->Projection(nTargetDim, targetDims);
953 // reset bin labels in case only one bin has been selected
954 for (Int_t i=0; i<nTargetDim; i++) {
955 if (selectedBins[targetDims[i]] >= 0) {
956 TAxis* axis = static_cast<THnSparse*>(hist)->GetAxis(i);
957 axis->GetLabels()->Clear();
958 axis->SetBinLabel(1, fCounters->GetAxis(targetDims[i])->GetBinLabel(selectedBins[targetDims[i]]));
966 delete[] selectedBins;
971 //-----------------------------------------------------------------------
972 Int_t* AliCounterCollection::CheckConsistency(const AliCounterCollection* c)
974 /// Consistency check of the two counter collections. To be consistent, both counters
975 /// must have the same rubrics with the same list of authorized key words if any.
976 /// Return the correspondence between the local rubric ordering and the one of the other counter,
977 /// or 0x0 in case of problem. It is the responsability of the user to delete the returned array.
979 if (!fCounters || !c->fCounters) {
980 AliError("counters are not initialized");
984 // check if the number of rubrics is the same
985 Int_t nRubrics = fRubrics->GetSize();
986 if (c->fRubrics->GetSize() != nRubrics) {
987 AliError("both counters do not contain the same number of rubrics");
991 Int_t* otherDims = new Int_t[nRubrics];
993 // loop over local rubrics
994 TObject* rubric1 = 0x0;
995 TIter nextRubric(fRubrics);
996 while ((rubric1 = nextRubric())) {
998 // find that rubric in the other counter
999 TObject* rubric2 = c->fRubrics->FindObject(rubric1->GetName());
1001 AliError(Form("the other counter does not contain the rubric %s", rubric1->GetName()));
1006 // check the list of authorized key words if any
1007 TObjArray* keyWords1 = dynamic_cast<TObjArray*>(rubric1);
1008 TObjArray* keyWords2 = dynamic_cast<TObjArray*>(rubric2);
1009 if (keyWords1 && keyWords2) {
1011 // check if the number of key words is the same
1012 if (keyWords1->GetEntriesFast() != keyWords2->GetEntriesFast()) {
1013 AliError("that rubric does not contain the same number of authorized key words in both counters");
1018 // loop over local key words
1019 TObjString* keyWord = 0x0;
1020 TIter nextKeyWord(keyWords1);
1021 while ((keyWord = static_cast<TObjString*>(nextKeyWord()))) {
1023 // find that key word in the corresponding rubric of the other counter
1024 if (!keyWords2->FindObject(keyWord->String().Data())) {
1025 AliError(Form("rubric %s does not contain the key word %s in the other counter", rubric1->GetName(), keyWord->String().Data()));
1032 } else if (keyWords1 || keyWords2) {
1034 // that rubric has not been initialized the same way in both counter
1036 AliError(Form("rubric %s of the other counter does not contain a list of authorized key words while this does", rubric1->GetName()));
1038 AliError(Form("rubric %s of this counter does not contain a list of authorized key words while the other does", rubric1->GetName()));
1045 // save the correspondence of rubric IDs in both counters
1046 otherDims[rubric1->GetUniqueID()] = rubric2->GetUniqueID();
1053 //-----------------------------------------------------------------------
1054 void AliCounterCollection::Add(const AliCounterCollection* counter)
1056 /// Add the given AliCounterCollections to this. They must have the
1057 /// same rubrics with the same list of authorized key words if any.
1059 // check the consistency between the other counter and this and get the correspondences between rubric IDs.
1060 Int_t* otherDims = CheckConsistency(counter);
1061 if (!otherDims) return;
1063 Int_t nRubrics = fCounters->GetNdimensions();
1064 Int_t* thisBins = new Int_t[nRubrics];
1065 Int_t* otherBins = new Int_t[nRubrics];
1067 // loop over every filled bins inside the other counter
1068 for (Long64_t i = 0; i < counter->fCounters->GetNbins(); i++) {
1070 // get the content of the bin
1071 Double_t value = counter->fCounters->GetBinContent(i, otherBins);
1073 // convert "other" bin coordinates to "this" bin coordinates
1075 for (Int_t dim = 0; dim < nRubrics; dim++) {
1076 TString label = counter->fCounters->GetAxis(otherDims[dim])->GetBinLabel(otherBins[otherDims[dim]]);
1077 thisBins[dim] = FindBin(dim, label, kTRUE);
1078 if (thisBins[dim] < 0) {
1079 AliError("this counter is full, unable to add that key word");
1086 // increment the corresponding local counter
1087 fCounters->AddBinContent(thisBins, value);
1096 //-----------------------------------------------------------------------
1097 Long64_t AliCounterCollection::Merge(TCollection* list)
1099 /// Merge this with a list of AliCounterCollections. All AliCounterCollections provided
1100 /// must have the same rubrics with the same list of authorized key words if any.
1102 if (!list || !fCounters) return 0;
1103 if (list->IsEmpty()) return (Long64_t)fCounters->GetEntries();
1106 const TObject* obj = 0x0;
1107 while ((obj = next())) {
1109 // check that "obj" is an object of the class AliCounterCollection
1110 const AliCounterCollection* counter = dynamic_cast<const AliCounterCollection*>(obj);
1112 AliError(Form("object named %s is not AliCounterCollection! Skipping it.", counter->GetName()));
1116 // merge counter to this one
1121 return (Long64_t)fCounters->GetEntries();
1124 //-----------------------------------------------------------------------
1125 void AliCounterCollection::Sort(Option_t* opt, Bool_t asInt)
1127 /// Sort rubrics defined without a list of authorized key words or all rubrics if opt=="all".
1128 /// If asInt=kTRUE, key words are ordered as interger instead of alphabetically.
1131 AliError("counters are not initialized");
1135 Bool_t all = (!strcasecmp(opt, "all"));
1137 Bool_t somethingToSort = kFALSE;
1138 Int_t nRubrics = fRubrics->GetSize();
1139 Bool_t* rubricsToSort = new Bool_t[nRubrics];
1140 memset(rubricsToSort, kFALSE, sizeof(Bool_t) * nRubrics);
1142 // choose rubrics to sort
1143 TObject* rubric = 0x0;
1144 TIter nextRubric(fRubrics);
1145 while ((rubric = nextRubric())) {
1147 if (all || dynamic_cast<TObjString*>(rubric)) {
1149 // check if something to sort
1150 THashList* labels = fCounters->GetAxis((Int_t)rubric->GetUniqueID())->GetLabels();
1151 if (!labels || labels->GetSize() < 2) continue;
1153 // select that rubric
1154 rubricsToSort[(Int_t)rubric->GetUniqueID()] = kTRUE;
1155 somethingToSort = kTRUE;
1161 // sort selected rubrics if any
1162 if (somethingToSort) Sort(rubricsToSort, asInt);
1165 delete[] rubricsToSort;
1168 //-----------------------------------------------------------------------
1169 void AliCounterCollection::SortRubric(TString rubric, Bool_t asInt)
1171 /// Sort only that rubric. If asInt=kTRUE, key words are ordered as interger instead of alphabetically.
1174 AliError("counters are not initialized");
1180 // find the rubric to sort
1181 Int_t dim = FindDim(rubric);
1182 if (dim < 0) return;
1184 // check if something to sort
1185 THashList* labels = fCounters->GetAxis(dim)->GetLabels();
1186 if (!labels || labels->GetSize() < 2) return;
1188 // select that rubric
1189 Int_t nRubrics = fRubrics->GetSize();
1190 Bool_t* rubricsToSort = new Bool_t[nRubrics];
1191 memset(rubricsToSort, kFALSE, sizeof(Bool_t) * nRubrics);
1192 rubricsToSort[dim] = kTRUE;
1195 Sort(rubricsToSort, asInt);
1198 delete[] rubricsToSort;
1201 //-----------------------------------------------------------------------
1202 void AliCounterCollection::Sort(const Bool_t* rubricsToSort, Bool_t asInt)
1204 /// Sort labels (alphabetically or as integer) in each rubric flagged in "rubricsToSort".
1206 // create a new counter
1207 THnSparse* oldCounters = fCounters;
1208 Int_t nRubrics = fRubrics->GetSize();
1209 fCounters = new THnSparseT<TArrayI>("hCounters", "hCounters", nRubrics, fRubricsSize->GetArray(), 0x0, 0x0);
1210 Int_t** newBins = new Int_t*[nRubrics];
1212 // define the new axes
1213 for (Int_t i=0; i<nRubrics; i++) {
1214 TAxis* oldAxis = oldCounters->GetAxis(i);
1215 TAxis* newAxis = fCounters->GetAxis(i);
1217 // set the name of the new axis
1218 newAxis->SetName(oldAxis->GetName());
1221 THashList* oldLabels = oldAxis->GetLabels();
1222 if (!oldLabels) continue;
1224 // sort them if required
1225 if (rubricsToSort[i]) {
1226 if (asInt) { oldLabels = SortAsInt(oldLabels); }
1227 else { oldLabels->Sort(); }
1230 // set labels in the new axis and save the correspondence between new and old bins
1231 newBins[i] = new Int_t[oldLabels->GetSize()+1];
1232 TObjString* label = 0x0;
1234 TIter nextLabel(oldLabels);
1235 while ((label = static_cast<TObjString*>(nextLabel()))) {
1236 newAxis->SetBinLabel(bin, label->String().Data());
1237 newBins[i][(Int_t)label->GetUniqueID()] = bin;
1242 if (rubricsToSort[i] && asInt) delete oldLabels;
1245 // fill the new counters
1246 Int_t* oldCoor = new Int_t[nRubrics];
1247 Int_t* newCoor = new Int_t[nRubrics];
1248 for (Long64_t i = 0; i < oldCounters->GetNbins(); i++) {
1249 Double_t value = oldCounters->GetBinContent(i, oldCoor);
1250 for (Int_t dim = 0; dim < nRubrics; dim++) newCoor[dim] = newBins[dim][oldCoor[dim]];
1251 fCounters->AddBinContent(newCoor, value);
1255 for (Int_t i=0; i<nRubrics; i++) delete[] newBins[i];
1262 //-----------------------------------------------------------------------
1263 THashList* AliCounterCollection::SortAsInt(const THashList* labels)
1265 /// Return a list (not owner) of labels sorted assuming they are integers.
1266 /// It is the responsability of user to delete the returned list.
1268 THashList* sortedLabels = new THashList(labels->GetSize());
1269 TIter nextSortedLabel(sortedLabels);
1272 TObjString* label = 0x0;
1273 TIter nextLabel(labels);
1274 while ((label = static_cast<TObjString*>(nextLabel()))) {
1276 // find where to add it
1277 TObjString* sortedLabel = 0x0;
1278 nextSortedLabel.Reset();
1279 while ((sortedLabel = static_cast<TObjString*>(nextSortedLabel())) &&
1280 (sortedLabel->String().Atoi() <= label->String().Atoi())) {}
1283 if (sortedLabel) sortedLabels->AddBefore(sortedLabel, label);
1284 else sortedLabels->AddLast(label);
1287 return sortedLabels;