]>
Commit | Line | Data |
---|---|---|
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 | ||
38 | ClassImp(AliCounterCollection) | |
39 | ||
40 | //----------------------------------------------------------------------- | |
41 | AliCounterCollection::AliCounterCollection(const char* name) : | |
42 | TNamed(name,name), | |
43 | fRubrics(new THashList(10)), | |
44 | fRubricsSize(new TArrayI(10)), | |
d810835e | 45 | fCounters(0x0), |
46 | fWeightedCounters(kFALSE) | |
94ef1a28 | 47 | { |
48 | /// Constructor | |
49 | fRubrics->SetOwner(); | |
50 | } | |
51 | ||
52 | //----------------------------------------------------------------------- | |
53 | AliCounterCollection::~AliCounterCollection() | |
54 | { | |
55 | /// Destructor | |
56 | delete fRubrics; | |
57 | delete fRubricsSize; | |
58 | delete fCounters; | |
59 | } | |
60 | ||
61 | //----------------------------------------------------------------------- | |
62 | void 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 | //----------------------------------------------------------------------- | |
72 | void 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 | //----------------------------------------------------------------------- | |
100 | void 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 | 126 | void 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 | //----------------------------------------------------------------------- |
161 | Int_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 | //----------------------------------------------------------------------- | |
169 | Bool_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 | //----------------------------------------------------------------------- |
177 | const 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 | //----------------------------------------------------------------------- | |
256 | Int_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 | //----------------------------------------------------------------------- | |
268 | Int_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 | //----------------------------------------------------------------------- |
295 | Short_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 | //----------------------------------------------------------------------- | |
374 | Bool_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 | //----------------------------------------------------------------------- |
452 | void 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 | //----------------------------------------------------------------------- | |
475 | void 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 | //----------------------------------------------------------------------- | |
484 | void 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 | //----------------------------------------------------------------------- | |
493 | void 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 | //----------------------------------------------------------------------- | |
525 | void 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 | 569 | TString 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 | //----------------------------------------------------------------------- |
596 | Double_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 | 639 | void 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 | //----------------------------------------------------------------------- | |
674 | void 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 | 707 | void 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 | 760 | void 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 | 770 | void 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 | 794 | void 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 | 884 | void 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 | //----------------------------------------------------------------------- | |
1054 | Int_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 | 1066 | TH1D* 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 | 1111 | TH2D* 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 | //----------------------------------------------------------------------- |
1163 | TH1D* 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 | //----------------------------------------------------------------------- | |
1175 | TH2D* 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 | //----------------------------------------------------------------------- |
1187 | TObject* 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 | //----------------------------------------------------------------------- | |
1328 | Int_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 | //----------------------------------------------------------------------- | |
1413 | void 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 | //----------------------------------------------------------------------- | |
1456 | Long64_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 | //----------------------------------------------------------------------- | |
1484 | void 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 | //----------------------------------------------------------------------- | |
1528 | void 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 | //----------------------------------------------------------------------- | |
1561 | void 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 | //----------------------------------------------------------------------- | |
1625 | THashList* 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 |