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