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