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