Add the line to support the output tree; Change the type of the output histogram...
[u/mrichter/AliRoot.git] / PWG3 / base / AliCounterCollection.cxx
CommitLineData
94ef1a28 1/**************************************************************************
2 * Copyright(c) 1998-2007, 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//-----------------------------------------------------------------------------
17/// \class AliCounterCollection
18///
19/// generic class to handle a collection of counters
20///
21/// \author Philippe Pillot
22//-----------------------------------------------------------------------------
23
24#include "AliCounterCollection.h"
25
26#include <AliLog.h>
27
28#include <TString.h>
29#include <TObjString.h>
30#include <TObjArray.h>
31#include <THnSparse.h>
32#include <THashList.h>
33#include <TArrayI.h>
34#include <TH1D.h>
35#include <TH2D.h>
36#include <TCollection.h>
37
38ClassImp(AliCounterCollection)
39
40//-----------------------------------------------------------------------
41AliCounterCollection::AliCounterCollection(const char* name) :
42TNamed(name,name),
43fRubrics(new THashList(10)),
44fRubricsSize(new TArrayI(10)),
45fCounters(0x0)
46{
47 /// Constructor
48 fRubrics->SetOwner();
49}
50
51//-----------------------------------------------------------------------
52AliCounterCollection::~AliCounterCollection()
53{
54 /// Destructor
55 delete fRubrics;
56 delete fRubricsSize;
57 delete fCounters;
58}
59
60//-----------------------------------------------------------------------
61void AliCounterCollection::Clear(Option_t*)
62{
63 /// Clear counters
64 fRubrics->Clear();
65 fRubricsSize->Reset();
66 delete fCounters; fCounters = 0x0;
67}
68
69//-----------------------------------------------------------------------
70void AliCounterCollection::AddRubric(TString name, TString listOfKeyWords)
71{
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.
75
76 name.ToUpper();
77 listOfKeyWords.ToUpper();
78
79 if (fRubrics->Contains(name.Data())) {
80 AliError(Form("rubric named %s already exist",name.Data()));
81 return;
82 }
83
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);
91
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();
95}
96
97//-----------------------------------------------------------------------
98void AliCounterCollection::AddRubric(TString name, Int_t maxNKeyWords)
99{
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.
104
105 name.ToUpper();
106
107 if (fRubrics->Contains(name.Data())) {
108 AliError(Form("rubric named %s already exist",name.Data()));
109 return;
110 }
111
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);
117
118 // save the maximum number of autorized key words
119 if (nRubrics+1 > fRubricsSize->GetSize()) fRubricsSize->Set(2*fRubricsSize->GetSize());
120 (*fRubricsSize)[nRubrics] = maxNKeyWords;
121}
122
123//-----------------------------------------------------------------------
124void AliCounterCollection::Init()
125{
126 /// Initialize the internal counters from the added rubrics.
127
128 // create the counters
129 delete fCounters;
130 fCounters = new THnSparseT<TArrayI>("hCounters", "hCounters", fRubrics->GetSize(), fRubricsSize->GetArray(), 0x0, 0x0);
131
132 // loop over axis
133 TObject* rubric = 0x0;
134 TIter nextRubric(fRubrics);
135 while ((rubric = nextRubric())) {
136 TAxis* axis = fCounters->GetAxis((Int_t)rubric->GetUniqueID());
137
138 // set axis name
139 axis->SetName(rubric->GetName());
140
141 // set labels if already known
142 TObjArray* keyWords = dynamic_cast<TObjArray*>(rubric);
143 if (keyWords) {
144 TObjString* label = 0x0;
145 Int_t bin = 1;
146 TIter nextLabel(keyWords);
147 while ((label = static_cast<TObjString*>(nextLabel()))) axis->SetBinLabel(bin++, label->String().Data());
148 }
149
150 }
151
152}
153
154//-----------------------------------------------------------------------
6f5626c7 155Int_t AliCounterCollection::GetNActiveBins(Int_t dim)
156{
157 /// return the number of labels in that rubric.
158 THashList* labels = fCounters->GetAxis(dim)->GetLabels();
159 return (labels) ? labels->GetSize() : 0;
160}
161
162//-----------------------------------------------------------------------
163Bool_t AliCounterCollection::ContainsAny(Int_t dim)
164{
165 /// return kTRUE if that rubric contains the keyWord "ANY".
166 THashList* labels = fCounters->GetAxis(dim)->GetLabels();
167 return (labels && labels->Contains("ANY"));
168}
169
170//-----------------------------------------------------------------------
94ef1a28 171const Int_t* AliCounterCollection::FindBins(const TString& externalKey, Bool_t allocate, Int_t& nEmptySlots)
172{
173 /// Return the corresponding bins ordered by rubric or 0x0 if externalKey is not valid.
174 /// The externalKey format must be rubric:keyWord/rubric:keyWord/rubric:keyWord/...
175 /// If allocate = kTRUE, new key words are added to the corresponding rubric if possible.
176 /// If a rubric is not filled in, the coresponding slot contain -1 in the array.
177 /// It is the responsability of the user to delete the returned array.
178
179 // produce an empty array of keys
180 Int_t nRubrics = fRubrics->GetSize();
181 Int_t* bins = new Int_t[nRubrics];
6f5626c7 182 for (Int_t i=0; i<nRubrics; i++) bins[i] = -1;
94ef1a28 183 nEmptySlots = nRubrics;
184 Bool_t isValid = kTRUE;
185
186 // get the list of rubric:keyWord pairs
187 TObjArray* rubricKeyPairs = externalKey.Tokenize("/");
188
189 // loop over each rubric:keyWord pair
190 TObjString* pair = 0x0;
191 TIter next(rubricKeyPairs);
192 while ((pair = static_cast<TObjString*>(next()))) {
193
194 // get both rubric and associated key word
195 TObjArray* rubricKeyPair = pair->String().Tokenize(":");
196
197 // check the format of the pair
198 if (rubricKeyPair->GetEntriesFast() != 2) {
199 AliError("invalid key format");
200 isValid = kFALSE;
201 delete rubricKeyPair;
202 break;
203 }
204
205 // get the axis corresponding to that rubric
206 Int_t dim = FindDim(static_cast<TObjString*>(rubricKeyPair->UncheckedAt(0))->String());
207 if (dim < 0) {
208 isValid = kFALSE;
209 delete rubricKeyPair;
210 break;
211 }
212
213 // find the bin corresponding to that key word
214 Int_t bin = FindBin(dim, static_cast<TObjString*>(rubricKeyPair->UncheckedAt(1))->String(), allocate);
215 if (bin < 0) {
216 isValid = kFALSE;
217 delete rubricKeyPair;
218 break;
219 }
220
221 // check if the array of keys already contains something for that rubric
222 if (bins[dim] >= 0) {
223 AliWarning("key already given for that rubric --> ignored");
224 delete rubricKeyPair;
225 continue;
226 }
227
228 // store the corresponding bin for that slot
229 bins[dim] = bin;
230 nEmptySlots--;
231
232 // clean memory
233 delete rubricKeyPair;
234 }
235
236 // delete the array in case of problem
237 if (!isValid) {
238 delete[] bins;
239 bins = 0x0;
240 nEmptySlots = nRubrics;
241 }
242
243 // clean memory
244 delete rubricKeyPairs;
245
246 return bins;
247}
248
249//-----------------------------------------------------------------------
250Int_t AliCounterCollection::FindDim(const TString& rubricName) const
251{
252 /// Return the dimension corresponding to that rubric (or -1 in case of failure).
253 TObject* rubric = fRubrics->FindObject(rubricName.Data());
254 if (!rubric) {
255 AliError(Form("invalid rubric: %s",rubricName.Data()));
256 return -1;
257 }
258 return (Int_t) rubric->GetUniqueID();
259}
260
261//-----------------------------------------------------------------------
262Int_t AliCounterCollection::FindBin(Int_t dim, const TString& keyWord, Bool_t allocate)
263{
264 /// Return the bin number corresponding to that key word (or -1 in case of failure).
265 /// If allocate = kTRUE, try to add the key word if possible.
266
267 TAxis* axis = fCounters->GetAxis(dim);
268
269 // look for the bin corresponding to keyWord
270 THashList* labels = axis->GetLabels();
271 TObjString* label = (labels) ? static_cast<TObjString*>(labels->FindObject(keyWord.Data())) : 0x0;
272 Int_t bin = (label) ? (Int_t)label->GetUniqueID() : -1;
273
274 // in case the keyWord does not exist, try to add it if required
275 if (bin<0 && allocate) {
276 Int_t nLabels = (labels) ? labels->GetSize() : 0;
277 if (nLabels < axis->GetNbins()) {
278 bin = nLabels+1;
279 axis->SetBinLabel(bin, keyWord.Data());
280 }
281 }
282
283 if (bin<0) AliError(Form("invalid key word: %s:%s",axis->GetName(),keyWord.Data()));
284
285 return bin;
286}
287
288//-----------------------------------------------------------------------
6f5626c7 289Short_t** AliCounterCollection::DecodeSelection(const TString& selections, const TObjArray& displayedRubrics)
290{
291 /// Tag the selected keywords in each rubric (-1=subtract; 0=discard; 1=add). Format:
292 /// "rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.." (order does not matter).
293 /// It is the responsability of the user to delete the returned array.
294
295 // produce an empty array of selected keys
296 Int_t nRubrics = fCounters->GetNdimensions();
297 Short_t** selects = new Short_t*[nRubrics];
298 for (Int_t i=0; i<nRubrics; i++) selects[i] = 0x0;
299
300 // get the list of rubric:LisOfKeyWord pairs
301 TObjArray* rubricKeyPairs = selections.Tokenize("/");
302
303 // loop over each rubric:keyWord pair
304 TObjString* pair = 0x0;
305 TIter next(rubricKeyPairs);
306 while ((pair = static_cast<TObjString*>(next()))) {
307
308 // get both rubric and associated list of key words
309 TObjArray* rubricKeyPair = pair->String().Tokenize(":");
310
311 // check the format of the pair
312 if (rubricKeyPair->GetEntriesFast() != 2) {
313 AliError("invalid key format");
314 delete rubricKeyPair;
315 delete rubricKeyPairs;
316 for (Int_t i=0; i<nRubrics; i++) if (selects[i]) delete[] selects[i];
317 delete[] selects;
318 return 0x0;
319 }
320
321 // check wether to select or to discard the keyWords
322 Int_t include = kTRUE;
323 TString ListOfKeyWords(static_cast<TObjString*>(rubricKeyPair->UncheckedAt(1))->String());
324 if (ListOfKeyWords.BeginsWith("ANY-")) {
325 ListOfKeyWords.Remove(0,4);
326 include = kFALSE;
327 }
328
329 // select the key words
330 const TString& rubric = static_cast<TObjString*>(rubricKeyPair->UncheckedAt(0))->String();
331 if (!Select(include, rubric, ListOfKeyWords, displayedRubrics.Contains(rubric.Data()), selects)) {
332 delete rubricKeyPair;
333 delete rubricKeyPairs;
334 for (Int_t i=0; i<nRubrics; i++) if (selects[i]) delete[] selects[i];
335 delete[] selects;
336 return 0x0;
337 }
338
339 // clean memory
340 delete rubricKeyPair;
341 }
342
343 // clean memory
344 delete rubricKeyPairs;
345
346 // complete the selection of other rubrics
347 for (Int_t i=0; i<nRubrics; i++) {
348
349 // skip already processed rubrics
350 if (selects[i]) continue;
351
352 // create the list of bins
353 Int_t nBins = GetNActiveBins(i) + 1;
354 selects[i] = new Short_t[nBins];
355
356 // select all key words or only the key work "ANY"
357 if (ContainsAny(i) && !displayedRubrics.Contains(fCounters->GetAxis(i)->GetName())) {
358 memset(selects[i], 0, sizeof(Short_t) * nBins);
359 selects[i][FindBin(i, "ANY", kFALSE)] = 1;
360 } else for (Int_t j=0; j<nBins; j++) selects[i][j] = 1;
361
362 }
363
364 return selects;
365}
366
367//-----------------------------------------------------------------------
368Bool_t AliCounterCollection::Select(Bool_t include, const TString& rubric, const TString& keywords,
369 Bool_t displayed, Short_t* selectBins[])
370{
371 /// Tag the selected keywords (separated by ',') in that rubric (-1=subtract; 0=discard; 1=add).
372
373 Int_t dim = FindDim(rubric);
374 if (dim < 0) return kFALSE;
375
376 if (selectBins[dim]) {
377 AliWarning(Form("selection already made for rubric %s --> ignored",rubric.Data()));
378 return kTRUE;
379 }
380
381 // get list of key words to select
382 TObjArray* keys = keywords.Tokenize(",");
383 if (keys->GetEntriesFast() == 0) {
384 AliError(Form("no key word specified for rubric %s",rubric.Data()));
385 delete keys;
386 return kFALSE;
387 }
388
389 // create the list of bins
390 Int_t nBins = GetNActiveBins(dim) + 1;
391 selectBins[dim] = new Short_t[nBins];
392
393 // select/unselect all bins
394 Bool_t containsAny = ContainsAny(dim);
395 if (include || (containsAny && !displayed)) {
396 memset(selectBins[dim], 0, sizeof(Short_t) * nBins);
397 if (!include) selectBins[dim][FindBin(dim, "ANY", kFALSE)] = 1;
398 } else for (Int_t j=0; j<nBins; j++) selectBins[dim][j] = 1;
399
400 // select/unselect specific key words
401 TObjString* key = 0x0;
402 TIter nextKey(keys);
403 while ((key = static_cast<TObjString*>(nextKey()))) {
404
405 // special case of key word "ANY"
406 if (key->String() == "ANY") {
407
408 if (containsAny) {
409
410 Int_t binAny = FindBin(dim, "ANY", kFALSE);
411 if (include) selectBins[dim][binAny] = 1;
412 else selectBins[dim][binAny] = 0;
413
414 } else {
415
416 if (include) for (Int_t j=0; j<nBins; j++) selectBins[dim][j] = 1;
417 else memset(selectBins[dim], 0, sizeof(Short_t) * nBins);
418
419 }
420
421 } else { // other cases
422
423 // find the corresponding bin
424 Int_t bin = FindBin(dim, key->String().Data(), kFALSE);
425 if (bin < 0) {
426 delete keys;
427 return kFALSE;
428 }
429
430 // select/unselect it
431 if (include) selectBins[dim][bin] = 1;
432 else if (containsAny && !displayed) selectBins[dim][bin] = -1;
433 else selectBins[dim][bin] = 0;
434
435 }
436
437 }
438
439 // clean memory
440 delete keys;
441
442 return kTRUE;
443}
444
445//-----------------------------------------------------------------------
94ef1a28 446void AliCounterCollection::CleanListOfStrings(TObjArray* list)
447{
448 /// Make sure all strings appear only once in this list
449
450 // remove multiple-occurrence
451 Int_t nEntries = list->GetEntriesFast();
452 for (Int_t i = 0; i < nEntries; i++) {
453 TObjString* entry1 = static_cast<TObjString*>(list->UncheckedAt(i));
454 if (!entry1) continue;
455 for (Int_t j = i+1; j < nEntries; j++) {
456 TObjString* entry2 = static_cast<TObjString*>(list->UncheckedAt(j));
457 if (entry2 && entry2->IsEqual(entry1)) {
458 AliWarning(Form("multiple-occurence of string \"%s\" --> removed",entry2->String().Data()));
459 list->RemoveAt(j);
460 }
461 }
462 }
463
464 // remove empty slots
465 list->Compress();
466}
467
468//-----------------------------------------------------------------------
469void AliCounterCollection::Count(TString externalKey, Int_t value)
470{
471 /// Add "value" to the counter referenced by "externalKey".
472 /// The externalKey format must be rubric:keyWord/rubric:keyWord/rubric:keyWord/...
473
474 if (value < 1) return;
475 if (!fCounters) {
476 AliError("counters are not initialized");
477 return;
478 }
479
480 externalKey.ToUpper();
481
482 // convert external to internal key
483 Int_t nEmptySlots = 0;
484 const Int_t* bins = FindBins(externalKey, kTRUE, nEmptySlots);
485 if (!bins) return;
486
487 // check for empty slots
488 if (nEmptySlots > 0) {
489 AliError("incomplete key");
490 delete[] bins;
491 return;
492 }
493
494 // increment the corresponding counter
495 fCounters->AddBinContent(bins, (Double_t)value);
496
497 // clean memory
498 delete[] bins;
499}
500
501//-----------------------------------------------------------------------
502void AliCounterCollection::Print(const Option_t* opt) const
503{
504 /// Print every individual counters if opt=="", else call "Print(TString rubrics=opt, TString selections="")".
505
506 if (strcmp(opt,"")) {
507 const_cast<AliCounterCollection*>(this)->Print(opt, "");
508 return;
509 }
510
511 if (!fCounters) {
512 AliError("counters are not initialized");
513 return;
514 }
515
516 if (fCounters->GetNbins() == 0) {
517 printf("\nall counters are empty\n\n");
518 return;
519 }
520
521 Int_t nRubrics = fCounters->GetNdimensions();
522 Int_t* bins = new Int_t[nRubrics];
523
524 // loop over every filled counters
525 for (Long64_t i=0; i<fCounters->GetNbins(); ++i) {
526
527 // get the content of the bin
528 Int_t value = (Int_t) fCounters->GetBinContent(i, bins);
529
530 // build the corresponding counter name
531 TString counter;
532 for (Int_t j=0; j<nRubrics; j++) counter += Form("/%s",fCounters->GetAxis(j)->GetBinLabel(bins[j]));
533 counter += "/";
534
535 // print value
536 printf("\n%s %d", counter.Data(), value);
537 }
538 printf("\n\n");
539
540 // clean memory
541 delete[] bins;
542}
543
544//-----------------------------------------------------------------------
d649ab79 545TString AliCounterCollection::GetKeyWords(TString rubric) const
546{
547 /// return the list of key words for the given rubric.
548
549 TString keyWords = "";
550
551 if (!fCounters) {
552 AliError("counters are not initialized");
553 return keyWords;
554 }
555
556 rubric.ToUpper();
557
558 // get the dimension corresponding to that rubric
559 Int_t dim = FindDim(rubric);
560 if (dim < 0) return keyWords;
561
562 // build list of key words
563 TObjString* label = 0x0;
564 TIter nextLabel(fCounters->GetAxis(dim)->GetLabels());
565 while ((label = static_cast<TObjString*>(nextLabel()))) keyWords += Form("%s,",label->String().Data());
566 keyWords.Remove(TString::kTrailing, ',');
567
568 return keyWords;
569}
570
571//-----------------------------------------------------------------------
94ef1a28 572void AliCounterCollection::PrintKeyWords() const
573{
574 /// Print the full list of key words.
575
576 if (!fCounters) {
577 AliError("counters are not initialized");
578 return;
579 }
580
581 // loop over rubrics
582 Int_t nRubrics = fCounters->GetNdimensions();
583 for (Int_t iDim=0; iDim<nRubrics; iDim++) {
584 TAxis* axis = fCounters->GetAxis(iDim);
585
586 // print rubric's name
587 printf("\n%s:", axis->GetName());
588
589 // loop over key words
590 Bool_t first = kTRUE;
591 TObjString* label = 0x0;
592 TIter nextLabel(axis->GetLabels());
593 while ((label = static_cast<TObjString*>(nextLabel()))) {
594
595 //print key word's name
596 if (first) {
597 printf("%s", label->String().Data());
598 first = kFALSE;
599 } else printf(",%s", label->String().Data());
600
601 }
602 }
603 printf("\n\n");
604}
605
606//-----------------------------------------------------------------------
607void AliCounterCollection::PrintValue(TString selections)
608{
609 /// Print value of selected counter.
6f5626c7 610 /// format of "selections" is rubric:keyWord/rubric:keyWord/rubric:keyWord/...
94ef1a28 611
612 if (!fCounters) {
613 AliError("counters are not initialized");
614 return;
615 }
616
617 selections.ToUpper();
618
619 // convert external to internal key
620 Int_t nEmptySlots = 0;
621 const Int_t* selectedBins = FindBins(selections, kFALSE, nEmptySlots);
622 if (!selectedBins) return;
623
624 // check for empty slots
625 if (nEmptySlots > 0) {
626 AliError("incomplete key");
627 delete[] selectedBins;
628 return;
629 }
630
631 // print value
632 printf("\n%d\n\n", (Int_t) fCounters->GetBinContent(selectedBins));
633
634 // clean memory
635 delete[] selectedBins;
636}
637
638//-----------------------------------------------------------------------
639void AliCounterCollection::Print(TString rubrics, TString selections)
640{
641 /// Print desired rubrics for the given selection:
642 /// - format of "rubrics" is rubric1/rubric2/.. (order matters only for output).
6f5626c7 643 /// - format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
94ef1a28 644 /// If "data" contains 1 rubric, the output will be one counter for each element of that rubric.
645 /// If "data" contains 2 rubrics, the output will be an array of counters, rubric1 vs rubric2.
646 /// If "data" contains 3 rubrics, the output will be an array rubric1 vs rubric2 for each element in rubric3.
647 /// ...
648 /// Results are integrated over rubrics not specified neither in "rubrics" nor in "selections".
649
650 if (!fCounters) {
651 AliError("counters are not initialized");
652 return;
653 }
654
655 rubrics.ToUpper();
656 selections.ToUpper();
657
658 // get the rubrics to print
659 TObjArray* rubricsToPrint = rubrics.Tokenize("/");
660 if (rubricsToPrint->GetEntriesFast() == 0) {
661 delete rubricsToPrint;
662 return;
663 }
664
665 // remove rubrics called twice
666 CleanListOfStrings(rubricsToPrint);
667
668 // project counters in the rubrics to print according to the selections
669 TObject* hist = Projection(*rubricsToPrint, selections);
670 if (!hist) {
671 delete rubricsToPrint;
672 return;
673 }
674
675 // print counters
676 Int_t nRubricsToPrint = rubricsToPrint->GetEntriesFast();
6f5626c7 677 if (nRubricsToPrint == 1 && (static_cast<TH1D*>(hist))->GetEntries() > 0)
94ef1a28 678 PrintList(static_cast<TH1D*>(hist));
6f5626c7 679 else if (nRubricsToPrint == 2 && (static_cast<TH2D*>(hist))->GetEntries() > 0)
94ef1a28 680 PrintArray(static_cast<TH2D*>(hist));
6f5626c7 681 else if (nRubricsToPrint > 2 && (static_cast<THnSparse*>(hist))->GetEntries() > 0)
94ef1a28 682 PrintListOfArrays(static_cast<THnSparse*>(hist));
683 else
684 printf("\nselected counters are empty\n\n");
685
686 // clean memory
687 delete rubricsToPrint;
688 delete hist;
689}
690
691//-----------------------------------------------------------------------
6f5626c7 692void AliCounterCollection::PrintSum(TString selections)
94ef1a28 693{
6f5626c7 694 /// Print the overall statistics for the given selection (result is integrated over not specified rubrics):
695 /// - format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
94ef1a28 696
697 if (!fCounters) {
698 AliError("counters are not initialized");
699 return;
700 }
701
94ef1a28 702 selections.ToUpper();
703
6f5626c7 704 // decode the selections
705 Short_t** select = DecodeSelection(selections, TObjArray());
706 if (!select) return;
94ef1a28 707
6f5626c7 708 // loop over every filled counters and compute integral
709 Int_t sum = 0;
710 Int_t nDims = fCounters->GetNdimensions();
711 Int_t* coord = new Int_t[nDims];
712 for (Long64_t i=0; i<fCounters->GetNbins(); ++i) {
713
714 // get the content of the counter
715 Double_t value = fCounters->GetBinContent(i, coord);
716
717 // discard not selected counters and compute the selection factor
718 Int_t selectionFactor = 1;
719 for (Int_t dim = 0; dim < nDims && selectionFactor != 0; dim++) selectionFactor *= select[dim][coord[dim]];
720 if (selectionFactor == 0) continue;
721
722 // compute integral
723 sum += selectionFactor * ((Int_t) value);
94ef1a28 724 }
725
94ef1a28 726 // clean memory
6f5626c7 727 for (Int_t iDim=0; iDim<nDims; iDim++) delete[] select[iDim];
728 delete[] select;
729 delete[] coord;
730
731 // print result
732 printf("\n%d\n\n", sum);
94ef1a28 733}
734
735//-----------------------------------------------------------------------
736void AliCounterCollection::PrintList(const TH1D* hist) const
737{
738 /// Print the content of 1D histogram as a list.
739
740 // set the format to print labels
741 THashList* labels = hist->GetXaxis()->GetLabels();
742 TString format(Form("\n%%%ds %%9d",GetMaxLabelSize(labels)));
743
744 // print value for each label
745 TObjString* label = 0x0;
746 TIter nextLabel(labels);
747 while ((label = static_cast<TObjString*>(nextLabel()))) {
748 Int_t bin = (Int_t) label->GetUniqueID();
749 printf(format.Data(), label->String().Data(), (Int_t) hist->GetBinContent(bin));
750 }
751 printf("\n\n");
752}
753
754//-----------------------------------------------------------------------
755void AliCounterCollection::PrintArray(const TH2D* hist) const
756{
757 /// Print the content of 2D histogram as an array.
758
759 // set the format to print labels in X direction
760 THashList* labelsX = hist->GetXaxis()->GetLabels();
761 TString formatX(Form("\n%%%ds ",GetMaxLabelSize(labelsX)));
762
763 // set the format to print labels in Y direction and values
764 THashList* labelsY = hist->GetYaxis()->GetLabels();
765 Int_t maxLabelSizeY = TMath::Max(9, GetMaxLabelSize(labelsY));
766 TString formatYs(Form("%%%ds ",maxLabelSizeY));
767 TString formatYd(Form("%%%dd ",maxLabelSizeY));
768
769 // print labels in Y axis
770 printf(formatX.Data()," ");
771 TObjString* labelY = 0x0;
772 TIter nextLabelY(labelsY);
773 while ((labelY = static_cast<TObjString*>(nextLabelY())))
774 printf(formatYs.Data(), labelY->String().Data());
775
776 // fill array for each label in X axis
777 TObjString* labelX = 0x0;
778 TIter nextLabelX(labelsX);
779 while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
780 Int_t binX = (Int_t) labelX->GetUniqueID();
781
782 // print label X
783 printf(formatX.Data(), labelX->String().Data());
784
785 // print value for each label in Y axis
786 nextLabelY.Reset();
787 while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
788 Int_t binY = (Int_t) labelY->GetUniqueID();
789 printf(formatYd.Data(), (Int_t) hist->GetBinContent(binX, binY));
790 }
791 }
792 printf("\n\n");
793}
794
795//-----------------------------------------------------------------------
796void AliCounterCollection::PrintListOfArrays(const THnSparse* hist) const
797{
798 /// Print the content of nD histogram as a list of arrays.
799
800 // set the format to print labels in X direction
801 THashList* labelsX = hist->GetAxis(0)->GetLabels();
802 TString formatX(Form("\n%%%ds ",GetMaxLabelSize(labelsX)));
803
804 // set the format to print labels in Y direction and values
805 THashList* labelsY = hist->GetAxis(1)->GetLabels();
806 Int_t maxLabelSizeY = TMath::Max(9, GetMaxLabelSize(labelsY));
807 TString formatYs(Form("%%%ds ",maxLabelSizeY));
808 TString formatYd(Form("%%%dd ",maxLabelSizeY));
809
810 // create a list containing each combination of labels refering the arrays to be printout
811 TList listOfCombis;
812 listOfCombis.SetOwner();
813
814 // add a first empty combination
815 Int_t nDim = hist->GetNdimensions();
816 listOfCombis.AddLast(new TObjArray(nDim-2));
817
818 // loop over the nDim-2 other rubrics
819 for (Int_t i=2; i<nDim; i++) {
820
821 // save the last label of that rubic
822 THashList* labels = hist->GetAxis(i)->GetLabels();
823 TObjString* lastLabel = (labels) ? static_cast<TObjString*>(labels->Last()) : 0x0;
824 if (!lastLabel) return;
825
826 // prepare iteration over the list of labels
827 TIter nextLabel(labels);
828
829 // loop over existing combinations
830 TObjLink* lnk = listOfCombis.FirstLink();
831 while (lnk) {
832
833 // get the current combination
834 TObjArray* currentCombi = static_cast<TObjArray*>(lnk->GetObject());
835
836 // loop over labels in the current rubric
837 nextLabel.Reset();
838 TObjString* label = 0x0;
839 while ((label = static_cast<TObjString*>(nextLabel()))) {
840
841 // stop at the last one
842 if (label == lastLabel) break;
843
844 // copy the current combination, add the current label to it and add it to the list of combinations
845 TObjArray* combi = new TObjArray(*currentCombi);
846 combi->AddLast(label);
847 listOfCombis.AddBefore(lnk, combi);
848 }
849
850 // add the last label to the current combination
851 currentCombi->AddLast(lastLabel);
852
853 lnk = lnk->Next();
854 }
855
856 }
857
858 // create bin coordinates to access individual counters
859 Int_t* bins = new Int_t[nDim];
860
861 // loop over each combination of labels
862 TObjArray* combi = 0x0;
863 TIter nextCombi(&listOfCombis);
864 while ((combi = static_cast<TObjArray*>(nextCombi()))) {
865
866 // make the name of the combination and fill the corresponding bin coordinates
867 TString combiName = "/";
868 for (Int_t i=2; i<nDim; i++) {
869 TObjString* label = static_cast<TObjString*>(combi->UncheckedAt(i-2));
870 combiName += Form("%s/",label->String().Data());
871 bins[i] = (Int_t)label->GetUniqueID();
872 }
873
874 // skip empty array
875 Bool_t empty = kTRUE;
876 TObjString* labelX = 0x0;
877 TObjString* labelY = 0x0;
878 TIter nextLabelX(labelsX);
879 TIter nextLabelY(labelsY);
880 while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
881 bins[0] = (Int_t) labelX->GetUniqueID();
882 nextLabelY.Reset();
883 while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
884 bins[1] = (Int_t) labelY->GetUniqueID();
885 if (((Int_t) hist->GetBinContent(bins)) > 0) {
886 empty = kFALSE;
887 break;
888 }
889 }
890 if (!empty) break;
891 }
892 if (empty) continue;
893
894 // print the name of the combination of labels refering the incoming array
895 printf("\n%s:\n",combiName.Data());
896
897 // print labels in Y axis
898 printf(formatX.Data()," ");
899 nextLabelY.Reset();
900 while ((labelY = static_cast<TObjString*>(nextLabelY())))
901 printf(formatYs.Data(), labelY->String().Data());
902
903 // fill array for each label in X axis
904 nextLabelX.Reset();
905 while ((labelX = static_cast<TObjString*>(nextLabelX()))) {
906 bins[0] = (Int_t) labelX->GetUniqueID();
907
908 // print label X
909 printf(formatX.Data(), labelX->String().Data());
910
911 // print value for each label in Y axis
912 nextLabelY.Reset();
913 while ((labelY = static_cast<TObjString*>(nextLabelY()))) {
914 bins[1] = (Int_t) labelY->GetUniqueID();
915 printf(formatYd.Data(), (Int_t) hist->GetBinContent(bins));
916 }
917 }
918 printf("\n\n");
919 }
920
921 // clean memory
922 delete[] bins;
923}
924
925//-----------------------------------------------------------------------
926Int_t AliCounterCollection::GetMaxLabelSize(THashList* labels) const
927{
928 /// Return the number of characters of the longest label.
929 Int_t maxLabelSize = 0;
930 TObjString* label = 0x0;
931 TIter nextLabel(labels);
932 while ((label = static_cast<TObjString*>(nextLabel())))
933 maxLabelSize = TMath::Max(maxLabelSize, label->String().Length());
934 return maxLabelSize;
935}
936
937//-----------------------------------------------------------------------
938TH1D* AliCounterCollection::Draw(TString rubric, TString selections)
939{
940 /// Draw counters of the rubric "rubric" for the given "selection".
6f5626c7 941 /// Format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
94ef1a28 942 /// Results are integrated over rubrics not specified neither in "rubric1" nor in "selections".
943 /// It is the responsability of the user to delete the returned histogram.
944
945 if (!fCounters) {
946 AliError("counters are not initialized");
947 return 0x0;
948 }
949
950 rubric.ToUpper();
951 selections.ToUpper();
952
953 // fill the rubrics to print
954 TObjArray rubricsToPrint(1);
955 rubricsToPrint.SetOwner();
956 rubricsToPrint.AddLast(new TObjString(rubric.Data()));
957
958 // project counters in the rubrics to print according to the selections
959 TH1D* hist = static_cast<TH1D*>(Projection(rubricsToPrint, selections));
960
961 // draw counters
962 if (hist) {
963
964 // draw histogram
965 hist->Draw("htext");
966 hist->SetStats(kFALSE);
967
94ef1a28 968 // draw X axis
969 TAxis* axis = hist->GetXaxis();
970 THashList* labels = axis->GetLabels();
971 Int_t nLabels = (labels) ? labels->GetSize() : 1;
972 axis->SetRange(1,nLabels);
973 axis->SetNdivisions(1,kFALSE);
974 axis->SetTitle(rubric.Data());
975
976 // draw Y axis
977 hist->GetYaxis()->SetTitle("Counts");
978 }
979
980 return hist;
981}
982
983//-----------------------------------------------------------------------
984TH2D* AliCounterCollection::Draw(TString rubric1, TString rubric2, TString selections)
985{
986 /// Draw counters of the "rubric1" vs "rubric2" for the given "selection".
6f5626c7 987 /// Format of "selections" is rubric:[any-]keyWord,keyWord,../rubric:[any-]keyWord,.. (order does not matter).
94ef1a28 988 /// Results are integrated over rubrics not specified neither in "rubric1", "rubric2" nor in "selections".
989 /// It is the responsability of the user to delete the returned histogram.
990
991 if (!fCounters) {
992 AliError("counters are not initialized");
993 return 0x0;
994 }
995
996 rubric1.ToUpper();
997 rubric2.ToUpper();
998 selections.ToUpper();
999
1000 // fill the rubrics to print
1001 TObjArray rubricsToPrint(2);
1002 rubricsToPrint.SetOwner();
1003 rubricsToPrint.AddLast(new TObjString(rubric2.Data()));
1004 rubricsToPrint.AddLast(new TObjString(rubric1.Data()));
1005
1006 // project counters in the rubrics to print according to the selections
1007 TH2D* hist = static_cast<TH2D*>(Projection(rubricsToPrint, selections));
1008
1009 // draw counters
1010 if (hist) {
1011
1012 // draw histogram
1013 hist->Draw("text");
1014 hist->SetStats(kFALSE);
1015
94ef1a28 1016 // draw X axis
1017 TAxis* axisX = hist->GetXaxis();
1018 THashList* labelsX = axisX->GetLabels();
1019 Int_t nLabelsX = (labelsX) ? labelsX->GetSize() : 1;
1020 axisX->SetRange(1,nLabelsX);
1021 axisX->SetNdivisions(1,kFALSE);
1022 axisX->SetTitle(rubric2.Data());
1023
1024 // draw Y axis
1025 TAxis* axisY = hist->GetYaxis();
1026 THashList* labelsY = axisY->GetLabels();
1027 Int_t nLabelsY = (labelsY) ? labelsY->GetSize() : 1;
1028 axisY->SetRange(1,nLabelsY);
1029 axisY->SetNdivisions(1,kFALSE);
1030 axisY->SetTitle(rubric1.Data());
1031 }
1032
1033 return hist;
1034}
1035
1036//-----------------------------------------------------------------------
1037TObject* AliCounterCollection::Projection(const TObjArray& data, const TString& selections)
1038{
1039 /// Return desired "data" for the given "selection" stored in a new histogram or 0x0 in case of failure.
1040 /// The type of the histogram (TH1D, TH2D or THnSparse) depend on the number of data.
1041 /// It is the responsability of the user to delete the returned histogram.
1042
6f5626c7 1043 // decode the selections
1044 Short_t** select = DecodeSelection(selections, data);
1045 if (!select) return 0x0;
1046
1047 // define name and dimensions of projection histo
1048 TString name(fCounters->GetName());
1049 Int_t nDims = fCounters->GetNdimensions();
1050 Int_t nTargetDims = data.GetEntriesFast();
1051 TArrayI targetDims(nTargetDims);
1052 TArrayI nNewBins(nTargetDims);
1053 TArrayI* OldToNewCoord = new TArrayI[nTargetDims];
1054 for (Int_t i=0; i<nTargetDims; i++) {
1055
1056 // histo name
1057 name += Form("_%s",static_cast<TObjString*>(data.UncheckedAt(i))->String().Data());
1058
1059 // find target dims
94ef1a28 1060 targetDims[i] = FindDim(static_cast<TObjString*>(data.UncheckedAt(i))->String());
6f5626c7 1061
1062 // set number of selected bins in the target dims and make the correspondence between old and new coordinates
1063 nNewBins[i] = 0;
1064 if (targetDims[i] > -1) {
1065 Int_t nBins = GetNActiveBins(targetDims[i]) + 1;
1066 OldToNewCoord[i].Set(nBins);
1067 for (Int_t j=1; j<nBins; j++) if (select[targetDims[i]][j] > 0) OldToNewCoord[i][j] = ++nNewBins[i];
1068 }
1069
1070 // clean memory and return 0x0 in case of problem
1071 if (nNewBins[i] == 0) {
1072 for (Int_t iDim=0; iDim<nDims; iDim++) delete[] select[iDim];
1073 delete[] select;
1074 delete[] OldToNewCoord;
94ef1a28 1075 return 0x0;
1076 }
6f5626c7 1077
94ef1a28 1078 }
1079
6f5626c7 1080 // define title of projection histo
1081 TString title = "Selections: ";
1082 TString selectionString(selections);
1083 selectionString.Remove(TString::kBoth, '/');
1084 if (selectionString.Length() > 0) title += Form("%s/", selectionString.Data());
1085 TObject* rub = 0x0;
1086 TIter nextRubric(fRubrics);
1087 while ((rub = nextRubric())) {
1088 if (selectionString.Contains(Form("%s:",rub->GetName()))) continue;
1089 if (data.Contains(rub->GetName())) continue;
1090 title += Form("%s:ANY/", rub->GetName());
94ef1a28 1091 }
6f5626c7 1092 title.ReplaceAll("/", " ");
94ef1a28 1093
6f5626c7 1094 // Create new histograms
1095 TObject* hist;
1096 if (nTargetDims == 1) hist = new TH1D(name.Data(), title.Data(), nNewBins[0], 0., 1.);
1097 else if (nTargetDims == 2) hist = new TH2D(name.Data(), title.Data(), nNewBins[0], 0., 1., nNewBins[1], 0., 1.);
1098 else hist = new THnSparseT<TArrayI>(name.Data(), title.Data(), nTargetDims, nNewBins.GetArray(), 0x0, 0x0);
94ef1a28 1099
6f5626c7 1100 // Set new axis labels
1101 TObjString* label;
1102 if (nTargetDims < 3) {
94ef1a28 1103
6f5626c7 1104 // X axis
1105 TIter nextLabelX(fCounters->GetAxis(targetDims[0])->GetLabels());
1106 while ((label = static_cast<TObjString*>(nextLabelX()))) {
1107 if (select[targetDims[0]][label->GetUniqueID()] > 0) {
1108 static_cast<TH1*>(hist)->GetXaxis()->SetBinLabel(OldToNewCoord[0][label->GetUniqueID()], label->String().Data());
1109 }
94ef1a28 1110 }
1111
6f5626c7 1112 // Y axis if any
1113 if (nTargetDims == 2) {
1114 TIter nextLabelY(fCounters->GetAxis(targetDims[1])->GetLabels());
1115 while ((label = static_cast<TObjString*>(nextLabelY()))) {
1116 if (select[targetDims[1]][label->GetUniqueID()] > 0) {
1117 static_cast<TH1*>(hist)->GetYaxis()->SetBinLabel(OldToNewCoord[1][label->GetUniqueID()], label->String().Data());
1118 }
1119 }
1120 }
94ef1a28 1121
6f5626c7 1122 } else {
94ef1a28 1123
6f5626c7 1124 // all axes
1125 for (Int_t i=0; i<nTargetDims; i++) {
1126 TIter nextLabel(fCounters->GetAxis(targetDims[i])->GetLabels());
1127 while ((label = static_cast<TObjString*>(nextLabel()))) {
1128 if (select[targetDims[i]][label->GetUniqueID()] > 0) {
1129 static_cast<THnSparse*>(hist)->GetAxis(i)->SetBinLabel(OldToNewCoord[i][label->GetUniqueID()], label->String().Data());
1130 }
1131 }
94ef1a28 1132 }
1133
6f5626c7 1134 }
1135
1136 // loop over every filled counters
1137 Int_t* coord = new Int_t[nDims];
1138 Int_t* newCoord = new Int_t[nTargetDims];
1139 Int_t nEntries = 0;
1140 for (Long64_t i=0; i<fCounters->GetNbins(); ++i) {
94ef1a28 1141
6f5626c7 1142 // get the content of the counter
1143 Double_t value = fCounters->GetBinContent(i, coord);
94ef1a28 1144
6f5626c7 1145 // discard not selected counters and compute the selection factor
1146 Int_t selectionFactor = 1;
1147 for (Int_t dim = 0; dim < nDims && selectionFactor != 0; dim++) selectionFactor *= select[dim][coord[dim]];
1148 if (selectionFactor == 0) continue;
94ef1a28 1149
6f5626c7 1150 // find new coordinates in the projection histo
1151 for (Int_t d = 0; d < nTargetDims; ++d) newCoord[d] = OldToNewCoord[d][coord[targetDims[d]]];
1152
1153 // fill projection histo
1154 if (nTargetDims < 3) {
1155 Int_t linBin = (nTargetDims == 1) ? newCoord[0] : static_cast<TH1*>(hist)->GetBin(newCoord[0], newCoord[1]);
1156 static_cast<TH1*>(hist)->AddBinContent(linBin, selectionFactor*value);
1157 } else static_cast<THnSparse*>(hist)->AddBinContent(newCoord, selectionFactor*value);
94ef1a28 1158
6f5626c7 1159 nEntries++;
94ef1a28 1160 }
1161
6f5626c7 1162 // update the number of entries
1163 if (nTargetDims < 3) static_cast<TH1*>(hist)->SetEntries(nEntries);
1164 else static_cast<THnSparse*>(hist)->SetEntries(nEntries);
1165
94ef1a28 1166 // clean memory
6f5626c7 1167 for (Int_t iDim=0; iDim<nDims; iDim++) delete[] select[iDim];
1168 delete[] select;
1169 delete[] coord;
1170 delete[] newCoord;
1171 delete[] OldToNewCoord;
94ef1a28 1172
1173 return hist;
1174}
1175
1176//-----------------------------------------------------------------------
1177Int_t* AliCounterCollection::CheckConsistency(const AliCounterCollection* c)
1178{
1179 /// Consistency check of the two counter collections. To be consistent, both counters
1180 /// must have the same rubrics with the same list of authorized key words if any.
1181 /// Return the correspondence between the local rubric ordering and the one of the other counter,
1182 /// or 0x0 in case of problem. It is the responsability of the user to delete the returned array.
1183
1184 if (!fCounters || !c->fCounters) {
1185 AliError("counters are not initialized");
1186 return 0x0;
1187 }
1188
1189 // check if the number of rubrics is the same
1190 Int_t nRubrics = fRubrics->GetSize();
1191 if (c->fRubrics->GetSize() != nRubrics) {
1192 AliError("both counters do not contain the same number of rubrics");
1193 return 0x0;
1194 }
1195
1196 Int_t* otherDims = new Int_t[nRubrics];
1197
1198 // loop over local rubrics
1199 TObject* rubric1 = 0x0;
1200 TIter nextRubric(fRubrics);
1201 while ((rubric1 = nextRubric())) {
1202
1203 // find that rubric in the other counter
1204 TObject* rubric2 = c->fRubrics->FindObject(rubric1->GetName());
1205 if (!rubric2) {
1206 AliError(Form("the other counter does not contain the rubric %s", rubric1->GetName()));
1207 delete[] otherDims;
1208 return 0x0;
1209 }
1210
1211 // check the list of authorized key words if any
1212 TObjArray* keyWords1 = dynamic_cast<TObjArray*>(rubric1);
1213 TObjArray* keyWords2 = dynamic_cast<TObjArray*>(rubric2);
1214 if (keyWords1 && keyWords2) {
1215
1216 // check if the number of key words is the same
1217 if (keyWords1->GetEntriesFast() != keyWords2->GetEntriesFast()) {
1218 AliError("that rubric does not contain the same number of authorized key words in both counters");
1219 delete[] otherDims;
1220 return 0x0;
1221 }
1222
1223 // loop over local key words
1224 TObjString* keyWord = 0x0;
1225 TIter nextKeyWord(keyWords1);
1226 while ((keyWord = static_cast<TObjString*>(nextKeyWord()))) {
1227
1228 // find that key word in the corresponding rubric of the other counter
1229 if (!keyWords2->FindObject(keyWord->String().Data())) {
1230 AliError(Form("rubric %s does not contain the key word %s in the other counter", rubric1->GetName(), keyWord->String().Data()));
1231 delete[] otherDims;
1232 return 0x0;
1233 }
1234
1235 }
1236
1237 } else if (keyWords1 || keyWords2) {
1238
1239 // that rubric has not been initialized the same way in both counter
1240 if (keyWords1) {
1241 AliError(Form("rubric %s of the other counter does not contain a list of authorized key words while this does", rubric1->GetName()));
1242 } else {
1243 AliError(Form("rubric %s of this counter does not contain a list of authorized key words while the other does", rubric1->GetName()));
1244 }
1245 delete[] otherDims;
1246 return 0x0;
1247
1248 }
1249
1250 // save the correspondence of rubric IDs in both counters
1251 otherDims[rubric1->GetUniqueID()] = rubric2->GetUniqueID();
1252
1253 }
1254
1255 return otherDims;
1256}
1257
1258//-----------------------------------------------------------------------
1259void AliCounterCollection::Add(const AliCounterCollection* counter)
1260{
1261 /// Add the given AliCounterCollections to this. They must have the
1262 /// same rubrics with the same list of authorized key words if any.
1263
1264 // check the consistency between the other counter and this and get the correspondences between rubric IDs.
1265 Int_t* otherDims = CheckConsistency(counter);
1266 if (!otherDims) return;
1267
1268 Int_t nRubrics = fCounters->GetNdimensions();
1269 Int_t* thisBins = new Int_t[nRubrics];
1270 Int_t* otherBins = new Int_t[nRubrics];
1271
1272 // loop over every filled bins inside the other counter
1273 for (Long64_t i = 0; i < counter->fCounters->GetNbins(); i++) {
1274
1275 // get the content of the bin
1276 Double_t value = counter->fCounters->GetBinContent(i, otherBins);
1277
1278 // convert "other" bin coordinates to "this" bin coordinates
1279 Bool_t ok = kTRUE;
1280 for (Int_t dim = 0; dim < nRubrics; dim++) {
1281 TString label = counter->fCounters->GetAxis(otherDims[dim])->GetBinLabel(otherBins[otherDims[dim]]);
1282 thisBins[dim] = FindBin(dim, label, kTRUE);
1283 if (thisBins[dim] < 0) {
1284 AliError("this counter is full, unable to add that key word");
1285 ok = kFALSE;
1286 break;
1287 }
1288 }
1289 if (!ok) continue;
1290
1291 // increment the corresponding local counter
1292 fCounters->AddBinContent(thisBins, value);
1293 }
1294
1295 // clean memory
1296 delete[] otherDims;
1297 delete[] thisBins;
1298 delete[] otherBins;
1299}
1300
1301//-----------------------------------------------------------------------
1302Long64_t AliCounterCollection::Merge(TCollection* list)
1303{
1304 /// Merge this with a list of AliCounterCollections. All AliCounterCollections provided
1305 /// must have the same rubrics with the same list of authorized key words if any.
1306
1307 if (!list || !fCounters) return 0;
1308 if (list->IsEmpty()) return (Long64_t)fCounters->GetEntries();
1309
1310 TIter next(list);
1311 const TObject* obj = 0x0;
1312 while ((obj = next())) {
1313
1314 // check that "obj" is an object of the class AliCounterCollection
1315 const AliCounterCollection* counter = dynamic_cast<const AliCounterCollection*>(obj);
1316 if (!counter) {
1317 AliError(Form("object named %s is not AliCounterCollection! Skipping it.", counter->GetName()));
1318 continue;
1319 }
1320
1321 // merge counter to this one
1322 Add(counter);
1323
1324 }
1325
1326 return (Long64_t)fCounters->GetEntries();
1327}
1328
1329//-----------------------------------------------------------------------
1330void AliCounterCollection::Sort(Option_t* opt, Bool_t asInt)
1331{
1332 /// Sort rubrics defined without a list of authorized key words or all rubrics if opt=="all".
1333 /// If asInt=kTRUE, key words are ordered as interger instead of alphabetically.
1334
1335 if (!fCounters) {
1336 AliError("counters are not initialized");
1337 return;
1338 }
1339
1340 Bool_t all = (!strcasecmp(opt, "all"));
1341
1342 Bool_t somethingToSort = kFALSE;
1343 Int_t nRubrics = fRubrics->GetSize();
1344 Bool_t* rubricsToSort = new Bool_t[nRubrics];
1345 memset(rubricsToSort, kFALSE, sizeof(Bool_t) * nRubrics);
1346
1347 // choose rubrics to sort
1348 TObject* rubric = 0x0;
1349 TIter nextRubric(fRubrics);
1350 while ((rubric = nextRubric())) {
1351
1352 if (all || dynamic_cast<TObjString*>(rubric)) {
1353
1354 // check if something to sort
1355 THashList* labels = fCounters->GetAxis((Int_t)rubric->GetUniqueID())->GetLabels();
1356 if (!labels || labels->GetSize() < 2) continue;
1357
1358 // select that rubric
1359 rubricsToSort[(Int_t)rubric->GetUniqueID()] = kTRUE;
1360 somethingToSort = kTRUE;
1361
1362 }
1363
1364 }
1365
1366 // sort selected rubrics if any
1367 if (somethingToSort) Sort(rubricsToSort, asInt);
1368
1369 // clean memory
1370 delete[] rubricsToSort;
1371}
1372
1373//-----------------------------------------------------------------------
1374void AliCounterCollection::SortRubric(TString rubric, Bool_t asInt)
1375{
1376 /// Sort only that rubric. If asInt=kTRUE, key words are ordered as interger instead of alphabetically.
1377
1378 if (!fCounters) {
1379 AliError("counters are not initialized");
1380 return;
1381 }
1382
1383 rubric.ToUpper();
1384
1385 // find the rubric to sort
1386 Int_t dim = FindDim(rubric);
1387 if (dim < 0) return;
1388
1389 // check if something to sort
1390 THashList* labels = fCounters->GetAxis(dim)->GetLabels();
1391 if (!labels || labels->GetSize() < 2) return;
1392
1393 // select that rubric
1394 Int_t nRubrics = fRubrics->GetSize();
1395 Bool_t* rubricsToSort = new Bool_t[nRubrics];
1396 memset(rubricsToSort, kFALSE, sizeof(Bool_t) * nRubrics);
1397 rubricsToSort[dim] = kTRUE;
1398
1399 // sort it
1400 Sort(rubricsToSort, asInt);
1401
1402 // clean memory
1403 delete[] rubricsToSort;
1404}
1405
1406//-----------------------------------------------------------------------
1407void AliCounterCollection::Sort(const Bool_t* rubricsToSort, Bool_t asInt)
1408{
1409 /// Sort labels (alphabetically or as integer) in each rubric flagged in "rubricsToSort".
1410
1411 // create a new counter
1412 THnSparse* oldCounters = fCounters;
1413 Int_t nRubrics = fRubrics->GetSize();
1414 fCounters = new THnSparseT<TArrayI>("hCounters", "hCounters", nRubrics, fRubricsSize->GetArray(), 0x0, 0x0);
1415 Int_t** newBins = new Int_t*[nRubrics];
1416
1417 // define the new axes
1418 for (Int_t i=0; i<nRubrics; i++) {
1419 TAxis* oldAxis = oldCounters->GetAxis(i);
1420 TAxis* newAxis = fCounters->GetAxis(i);
1421
1422 // set the name of the new axis
1423 newAxis->SetName(oldAxis->GetName());
1424
1425 // get old labels
1426 THashList* oldLabels = oldAxis->GetLabels();
1427 if (!oldLabels) continue;
1428
1429 // sort them if required
1430 if (rubricsToSort[i]) {
1431 if (asInt) { oldLabels = SortAsInt(oldLabels); }
1432 else { oldLabels->Sort(); }
1433 }
1434
1435 // set labels in the new axis and save the correspondence between new and old bins
1436 newBins[i] = new Int_t[oldLabels->GetSize()+1];
1437 TObjString* label = 0x0;
1438 Int_t bin = 1;
1439 TIter nextLabel(oldLabels);
1440 while ((label = static_cast<TObjString*>(nextLabel()))) {
1441 newAxis->SetBinLabel(bin, label->String().Data());
1442 newBins[i][(Int_t)label->GetUniqueID()] = bin;
1443 bin++;
1444 }
1445
1446 // clean memory
1447 if (rubricsToSort[i] && asInt) delete oldLabels;
1448 }
1449
1450 // fill the new counters
1451 Int_t* oldCoor = new Int_t[nRubrics];
1452 Int_t* newCoor = new Int_t[nRubrics];
1453 for (Long64_t i = 0; i < oldCounters->GetNbins(); i++) {
1454 Double_t value = oldCounters->GetBinContent(i, oldCoor);
1455 for (Int_t dim = 0; dim < nRubrics; dim++) newCoor[dim] = newBins[dim][oldCoor[dim]];
1456 fCounters->AddBinContent(newCoor, value);
1457 }
1458
1459 // clean memory
1460 for (Int_t i=0; i<nRubrics; i++) delete[] newBins[i];
1461 delete[] newBins;
1462 delete[] oldCoor;
1463 delete[] newCoor;
1464 delete oldCounters;
1465}
1466
1467//-----------------------------------------------------------------------
1468THashList* AliCounterCollection::SortAsInt(const THashList* labels)
1469{
1470 /// Return a list (not owner) of labels sorted assuming they are integers.
1471 /// It is the responsability of user to delete the returned list.
1472
1473 THashList* sortedLabels = new THashList(labels->GetSize());
1474 TIter nextSortedLabel(sortedLabels);
1475
1476 // loop over labels
1477 TObjString* label = 0x0;
1478 TIter nextLabel(labels);
1479 while ((label = static_cast<TObjString*>(nextLabel()))) {
1480
1481 // find where to add it
1482 TObjString* sortedLabel = 0x0;
1483 nextSortedLabel.Reset();
1484 while ((sortedLabel = static_cast<TObjString*>(nextSortedLabel())) &&
1485 (sortedLabel->String().Atoi() <= label->String().Atoi())) {}
1486
1487 // add it
1488 if (sortedLabel) sortedLabels->AddBefore(sortedLabel, label);
1489 else sortedLabels->AddLast(label);
1490 }
1491
1492 return sortedLabels;
1493}
1494