]>
Commit | Line | Data |
---|---|---|
d899f664 | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, 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 | /// A (fake) "4D" histogram container. | |
20 | /// | |
21 | /// For each tuple (keyA,keyB,keyC,keyD) a (hash)list of histogram is associated. | |
22 | /// Note that keyA, keyB (optional), keyC (optional) and keyD (optional) are strings. | |
23 | /// Those strings should not contain "/" themselves. | |
24 | /// | |
25 | /// More helper functions might be added in the future (e.g. Project, etc...) | |
26 | ||
27 | #include "AliHistogramCollection.h" | |
28 | ||
2f331ac9 | 29 | ClassImp(AliHistogramCollection) |
30 | ||
d899f664 | 31 | #include "AliLog.h" |
d440e2c5 | 32 | #include "AliMergeableCollection.h" |
d899f664 | 33 | #include "Riostream.h" |
34 | #include "TError.h" | |
35 | #include "TH1.h" | |
5eabea87 | 36 | #include "TH2.h" |
d899f664 | 37 | #include "THashList.h" |
38 | #include "TKey.h" | |
39 | #include "TMap.h" | |
40 | #include "TObjArray.h" | |
41 | #include "TObjString.h" | |
d440e2c5 | 42 | #include "TProfile.h" |
d899f664 | 43 | #include "TRegexp.h" |
44 | #include "TROOT.h" | |
45 | #include "TSystem.h" | |
46 | ||
3a7af7bd | 47 | using std::cout; |
48 | using std::endl; | |
d899f664 | 49 | ClassImp(AliHistogramCollection) |
50 | ||
51 | //_____________________________________________________________________________ | |
52 | AliHistogramCollection::AliHistogramCollection(const char* name, const char* title) | |
5eabea87 | 53 | : TNamed(name,title), fMap(0x0), fMustShowEmptyHistogram(kFALSE), fMapVersion(0), fMessages() |
d899f664 | 54 | { |
55 | /// Ctor | |
56 | } | |
57 | ||
58 | //_____________________________________________________________________________ | |
59 | AliHistogramCollection::~AliHistogramCollection() | |
60 | { | |
61 | /// dtor. Note that the map is owner | |
62 | if ( fMap ) fMap->DeleteAll(); | |
63 | delete fMap; | |
5eabea87 | 64 | } |
65 | ||
66 | //_____________________________________________________________________________ | |
67 | Bool_t | |
68 | AliHistogramCollection::Adopt(TH1* histo) | |
69 | { | |
70 | /// Adopt a given histogram at top level (i.e. no key) | |
71 | return InternalAdopt("",histo); | |
d899f664 | 72 | } |
73 | ||
74 | //_____________________________________________________________________________ | |
75 | Bool_t | |
76 | AliHistogramCollection::Adopt(const char* key, TH1* histo) | |
77 | { | |
78 | /// Adopt a given histogram, and associate it with pair (keyA) | |
5eabea87 | 79 | return InternalAdopt(Form("/%s/",key),histo); |
d899f664 | 80 | } |
81 | ||
82 | //_____________________________________________________________________________ | |
83 | Bool_t | |
84 | AliHistogramCollection::Adopt(const char* keyA, const char* keyB, TH1* histo) | |
85 | { | |
86 | /// Adopt a given histogram, and associate it with pair (keyA,keyB) | |
5eabea87 | 87 | return InternalAdopt(Form("/%s/%s/",keyA,keyB),histo); |
d899f664 | 88 | } |
89 | ||
90 | //_____________________________________________________________________________ | |
91 | Bool_t | |
92 | AliHistogramCollection::Adopt(const char* keyA, const char* keyB, const char* keyC, TH1* histo) | |
93 | { | |
94 | /// Adopt a given histogram, and associate it with pair (keyA,keyB,keyC) | |
5eabea87 | 95 | return InternalAdopt(Form("/%s/%s/%s/",keyA,keyB,keyC),histo); |
d899f664 | 96 | } |
97 | ||
98 | //_____________________________________________________________________________ | |
99 | Bool_t | |
100 | AliHistogramCollection::Adopt(const char* keyA, const char* keyB, const char* keyC, const char* keyD, TH1* histo) | |
101 | { | |
102 | /// Adopt a given histogram, and associate it with pair (keyA,keyB,keyC,keyD) | |
103 | return InternalAdopt(Form("/%s/%s/%s/%s/",keyA,keyB,keyC,keyD),histo); | |
104 | } | |
105 | ||
5eabea87 | 106 | //_____________________________________________________________________________ |
107 | void AliHistogramCollection::ClearMessages() | |
108 | { | |
109 | /// clear pending messages | |
110 | fMessages.clear(); | |
111 | } | |
112 | ||
d899f664 | 113 | //_____________________________________________________________________________ |
114 | TIterator* | |
115 | AliHistogramCollection::CreateIterator(Bool_t direction) const | |
116 | { | |
117 | /// Create an iterator (must be deleted by the client) | |
118 | return fMap ? new AliHistogramCollectionIterator(this,direction) : 0x0; | |
119 | } | |
120 | ||
5eabea87 | 121 | //_____________________________________________________________________________ |
122 | AliHistogramCollection* | |
123 | AliHistogramCollection::Clone(const char* name) const | |
124 | { | |
125 | /// Clone this collection. | |
126 | /// We loose the messages. | |
127 | ||
128 | AliHistogramCollection* newone = new AliHistogramCollection(name,GetTitle()); | |
129 | ||
130 | newone->fMap = static_cast<TMap*>(fMap->Clone()); | |
131 | newone->fMustShowEmptyHistogram = fMustShowEmptyHistogram; | |
132 | newone->fMapVersion = fMapVersion; | |
133 | ||
134 | return newone; | |
135 | } | |
136 | ||
d899f664 | 137 | //_____________________________________________________________________________ |
138 | void | |
139 | AliHistogramCollection::Delete(Option_t*) | |
140 | { | |
141 | /// Delete all the histograms | |
142 | fMap->DeleteAll(); | |
143 | delete fMap; | |
144 | fMap=0x0; | |
145 | } | |
146 | ||
147 | //_____________________________________________________________________________ | |
148 | TObject* | |
149 | AliHistogramCollection::FindObject(const char* identifier) const | |
150 | { | |
151 | /// Find an object by its full identifier. | |
152 | ||
153 | return Histo(KeyA(identifier), | |
154 | KeyB(identifier), | |
155 | KeyC(identifier), | |
156 | KeyD(identifier), | |
157 | HistoName(identifier)); | |
158 | } | |
159 | ||
160 | //_____________________________________________________________________________ | |
161 | TObject* | |
162 | AliHistogramCollection::FindObject(const TObject *key) const | |
163 | { | |
164 | /// Find an object | |
165 | AliWarning("This method is awfully inefficient. Please improve it or use FindObject(const char*)"); | |
166 | TIter next(CreateIterator()); | |
167 | TObject* o; | |
168 | while ( ( o=next() ) ) | |
169 | { | |
170 | if ( o->IsEqual(key) ) return o; | |
171 | } | |
172 | return 0x0; | |
173 | } | |
174 | ||
d440e2c5 | 175 | //_____________________________________________________________________________ |
176 | AliMergeableCollection* AliHistogramCollection::Convert() const | |
177 | { | |
178 | /// Convert this into a mergeable collection so it can receive objects | |
179 | /// that are not histograms | |
180 | ||
181 | AliMergeableCollection* mc = new AliMergeableCollection(GetName(),GetTitle()); | |
182 | ||
183 | TObjArray* ids = SortAllIdentifiers(); | |
184 | TIter next(ids); | |
185 | TObjString* key; | |
186 | ||
187 | while ( ( key = static_cast<TObjString*>(next()) ) ) | |
188 | { | |
189 | THashList* list = static_cast<THashList*>(fMap->GetValue(key->String().Data())); | |
190 | TIter nextHisto(list); | |
191 | TH1* histo; | |
192 | ||
193 | while ( ( histo = static_cast<TH1*>(nextHisto()))) | |
194 | { | |
195 | TH1* h = static_cast<TH1*>(histo->Clone()); | |
196 | mc->Adopt(key->String().Data(),h); | |
197 | } | |
198 | } | |
199 | ||
200 | delete ids; | |
201 | ||
202 | return mc; | |
203 | } | |
204 | ||
205 | ||
2f331ac9 | 206 | //_____________________________________________________________________________ |
207 | TList* | |
208 | AliHistogramCollection::CreateListOfKeysA() const | |
209 | { | |
210 | /// Create list of keys at level "A" (/A/B/C/D/histoname) | |
211 | /// Must be delete by client | |
212 | return CreateListOfKeys(0); | |
213 | } | |
214 | ||
215 | //_____________________________________________________________________________ | |
216 | TList* | |
217 | AliHistogramCollection::CreateListOfKeysB() const | |
218 | { | |
219 | /// Create list of keys at level "B" (/A/B/C/D/histoname) | |
220 | /// Must be delete by client | |
221 | return CreateListOfKeys(1); | |
222 | } | |
223 | ||
224 | //_____________________________________________________________________________ | |
225 | TList* | |
226 | AliHistogramCollection::CreateListOfKeysC() const | |
227 | { | |
228 | /// Create list of keys at level "C" (/A/B/C/D/histoname) | |
229 | /// Must be delete by client | |
230 | return CreateListOfKeys(2); | |
231 | } | |
232 | ||
233 | //_____________________________________________________________________________ | |
234 | TList* | |
235 | AliHistogramCollection::CreateListOfKeysD() const | |
236 | { | |
237 | /// Create list of keys at level "D" (/A/B/C/D/histoname) | |
238 | /// Must be delete by client | |
239 | return CreateListOfKeys(3); | |
240 | } | |
241 | ||
242 | //_____________________________________________________________________________ | |
243 | TList* | |
244 | AliHistogramCollection::CreateListOfHistogramNames(const char* keyA, const char* keyB, const char* keyC, const char* keyD) const | |
245 | { | |
246 | /// Create list of histogram names for /keyA/keyB/keyC/KeyD | |
247 | /// Returned list must be deleted by client | |
248 | ||
249 | TList* listOfNames = new TList; | |
250 | listOfNames->SetOwner(kTRUE); | |
251 | ||
252 | TIter next(Map()); | |
253 | TObjString* str; | |
254 | ||
255 | while ( ( str = static_cast<TObjString*>(next()) ) ) | |
256 | { | |
257 | TString identifier = str->String(); | |
258 | ||
259 | Bool_t copy= ( KeyA(identifier) == keyA && | |
260 | ( strlen(keyB)==0 || KeyB(identifier)==keyB ) && | |
261 | ( strlen(keyC)==0 || KeyC(identifier)==keyC ) && | |
262 | ( strlen(keyD)==0 || KeyD(identifier)==keyD )); | |
263 | ||
264 | if ( !copy ) continue; | |
265 | ||
266 | THashList* list = static_cast<THashList*>(Map()->GetValue(identifier.Data())); | |
267 | ||
268 | TIter nextHisto(list); | |
269 | TH1* h; | |
270 | ||
271 | while ( ( h = static_cast<TH1*>(nextHisto()) ) ) | |
272 | { | |
273 | listOfNames->Add(new TObjString(h->GetName())); | |
274 | } | |
275 | } | |
276 | ||
277 | return listOfNames; | |
278 | } | |
279 | ||
280 | //_____________________________________________________________________________ | |
281 | TList* | |
282 | AliHistogramCollection::CreateListOfKeys(Int_t index) const | |
283 | { | |
284 | /// Create the list of keys at level index | |
285 | ||
286 | TList* list = new TList; | |
287 | list->SetOwner(kTRUE); | |
288 | ||
289 | TObjArray* ids = SortAllIdentifiers(); | |
290 | TIter next(ids); | |
291 | TObjString* str; | |
292 | ||
293 | while ( ( str = static_cast<TObjString*>(next()) ) ) | |
294 | { | |
295 | TString oneid = InternalDecode(str->String().Data(),index); | |
296 | if (oneid.Length()>0 && !list->Contains(oneid)) | |
297 | { | |
298 | list->Add(new TObjString(oneid)); | |
299 | } | |
300 | } | |
301 | ||
302 | delete ids; | |
303 | return list; | |
304 | } | |
305 | ||
d899f664 | 306 | //_____________________________________________________________________________ |
307 | TH1* | |
308 | AliHistogramCollection::Histo(const char* keyA, | |
309 | const char* histoname) const | |
310 | { | |
311 | /// Get histo for (keyA,histoname) triplet | |
312 | ||
5eabea87 | 313 | return InternalHisto(Form("/%s/",keyA),histoname); |
d899f664 | 314 | } |
315 | ||
316 | //_____________________________________________________________________________ | |
317 | TH1* | |
318 | AliHistogramCollection::Histo(const char* keyA, const char* keyB, | |
319 | const char* histoname) const | |
320 | { | |
321 | /// Get histo for (keyA,keyB,histoname) triplet | |
322 | ||
5eabea87 | 323 | return InternalHisto(Form("/%s/%s/",keyA,keyB),histoname); |
d899f664 | 324 | } |
325 | ||
326 | //_____________________________________________________________________________ | |
327 | TH1* | |
328 | AliHistogramCollection::Histo(const char* keyA, const char* keyB, const char* keyC, | |
329 | const char* histoname) const | |
330 | { | |
331 | /// Get histo for (keyA,keyB,keyC,histoname) quad | |
332 | ||
5eabea87 | 333 | return InternalHisto(Form("/%s/%s/%s/",keyA,keyB,keyC),histoname); |
d899f664 | 334 | } |
335 | ||
336 | //_____________________________________________________________________________ | |
337 | TH1* | |
338 | AliHistogramCollection::Histo(const char* keyA, const char* keyB, | |
339 | const char* keyC, const char* keyD, | |
340 | const char* histoname) const | |
341 | { | |
342 | /// Get histo for (keyA,keyB,keyC,histoname) quad | |
343 | ||
344 | return InternalHisto(Form("/%s/%s/%s/%s/",keyA,keyB,keyC,keyD),histoname); | |
345 | } | |
346 | ||
347 | //_____________________________________________________________________________ | |
348 | TString | |
349 | AliHistogramCollection::HistoName(const char* identifier) const | |
350 | { | |
351 | /// Extract the histogram name from an identifier | |
352 | ||
5eabea87 | 353 | return InternalDecode(identifier,-1); |
d899f664 | 354 | } |
355 | ||
356 | //_____________________________________________________________________________ | |
357 | Bool_t AliHistogramCollection::InternalAdopt(const char* identifier, TH1* histo) | |
358 | { | |
359 | /// Adopt an histogram | |
360 | ||
361 | if (!histo) | |
362 | { | |
363 | Error("Adopt","Cannot adopt a null histogram"); | |
364 | return kFALSE; | |
365 | } | |
366 | ||
367 | THashList* hlist = 0x0; | |
368 | ||
5eabea87 | 369 | hlist = static_cast<THashList*>(Map()->GetValue(identifier)); |
d899f664 | 370 | |
371 | if (!hlist) | |
372 | { | |
373 | hlist = new THashList; | |
374 | hlist->SetOwner(kTRUE); | |
5eabea87 | 375 | Map()->Add(new TObjString(identifier),hlist); |
d899f664 | 376 | hlist->SetName(identifier); |
377 | } | |
378 | ||
379 | TH1* h = static_cast<TH1*>(hlist->FindObject(histo->GetName())); | |
380 | ||
381 | if (h) | |
382 | { | |
383 | AliError(Form("Cannot adopt an already existing histogram : %s -> %s",identifier,h->GetName())); | |
384 | return kFALSE; | |
385 | } | |
386 | ||
387 | ||
388 | histo->SetDirectory(0); | |
389 | ||
390 | hlist->AddLast(histo); | |
391 | ||
392 | return kTRUE; | |
393 | ||
394 | } | |
395 | ||
396 | //_____________________________________________________________________________ | |
397 | TH1* | |
5eabea87 | 398 | AliHistogramCollection::Histo(const char* sidentifier) const |
d899f664 | 399 | { |
5eabea87 | 400 | /// Get histogram keyA/keyB/keyC/keyD/histoname:action |
401 | ||
402 | TObjArray* a = TString(sidentifier).Tokenize(":"); | |
403 | ||
404 | TString identifier(static_cast<TObjString*>(a->At(0))->String()); | |
405 | TString action; | |
406 | ||
407 | if ( a->GetLast() > 0 ) | |
408 | { | |
409 | action = static_cast<TObjString*>(a->At(1))->String(); | |
410 | action.ToUpper(); | |
411 | } | |
09d5920f | 412 | |
413 | delete a; | |
414 | ||
5eabea87 | 415 | Int_t nslashes = identifier.CountChar('/'); |
416 | ||
417 | TH1* h(0x0); | |
418 | ||
419 | switch (nslashes) | |
420 | { | |
421 | case 0: | |
422 | case 1: | |
423 | // no slash : the identifier is just the histogram name | |
424 | h = InternalHisto("",identifier); | |
425 | break; | |
426 | case 2: | |
427 | h = Histo(InternalDecode(identifier,0), | |
428 | InternalDecode(identifier,-1)); | |
429 | break; | |
430 | case 3: | |
431 | h = Histo(InternalDecode(identifier,0), | |
432 | InternalDecode(identifier,1), | |
433 | InternalDecode(identifier,-1)); | |
434 | break; | |
435 | case 4: | |
436 | h = Histo(InternalDecode(identifier,0), | |
437 | InternalDecode(identifier,1), | |
438 | InternalDecode(identifier,2), | |
439 | InternalDecode(identifier,-1)); | |
440 | break; | |
441 | case 5: | |
442 | h = Histo(InternalDecode(identifier,0), | |
443 | InternalDecode(identifier,1), | |
444 | InternalDecode(identifier,2), | |
445 | InternalDecode(identifier,3), | |
446 | InternalDecode(identifier,-1)); | |
447 | break; | |
448 | default: | |
449 | AliError(Form("Invalid identifier %s",identifier.Data())); | |
450 | break; | |
451 | } | |
452 | ||
453 | if (h) | |
454 | { | |
455 | TH2* h2(0x0); | |
456 | ||
457 | if ( action == "PX" && ( (h2 = dynamic_cast<TH2*>(h)) ) ) | |
458 | { | |
459 | return h2->ProjectionX(NormalizeName(identifier.Data(),action.Data()).Data()); | |
460 | } | |
461 | else if ( action == "PY" && ( (h2 = dynamic_cast<TH2*>(h)) ) ) | |
462 | { | |
463 | return h2->ProjectionY(NormalizeName(identifier.Data(),action.Data()).Data()); | |
464 | } | |
465 | else if ( action == "PFX" && ( (h2 = dynamic_cast<TH2*>(h)) ) ) | |
466 | { | |
467 | return h2->ProfileX(NormalizeName(identifier.Data(),action.Data()).Data()); | |
468 | } | |
469 | else if ( action == "PFY" && ( (h2 = dynamic_cast<TH2*>(h)) ) ) | |
470 | { | |
471 | return h2->ProfileY(NormalizeName(identifier.Data(),action.Data()).Data()); | |
472 | } | |
473 | ||
474 | } | |
475 | else | |
476 | { | |
477 | AliDebug(1,Form("histogram %s not found",sidentifier)); | |
478 | } | |
479 | return h; | |
d899f664 | 480 | } |
481 | ||
482 | //_____________________________________________________________________________ | |
483 | TString | |
484 | AliHistogramCollection::InternalDecode(const char* identifier, Int_t index) const | |
485 | { | |
486 | /// Extract the index-th element of the identifier (/keyA/keyB/keyC/keyD/histoname) | |
487 | /// keyA is index=0 | |
488 | /// keyB is index=1 | |
489 | /// keyC is index=2 | |
490 | /// keyD is index=3 | |
5eabea87 | 491 | /// histo is index=-1 (i.e. last) |
d899f664 | 492 | |
5eabea87 | 493 | if ( strlen(identifier) > 0 && identifier[0] != '/' ) |
d899f664 | 494 | { |
5eabea87 | 495 | AliError(Form("identifier %s is malformed (should start with /)",identifier)); |
d899f664 | 496 | return ""; |
497 | } | |
498 | ||
499 | TObjArray* array = TString(identifier).Tokenize("/"); | |
500 | ||
501 | if ( array->GetLast()>5 ) | |
502 | { | |
5eabea87 | 503 | AliError(Form("identifier %s is malformed (more than 5 /)",identifier)); |
d899f664 | 504 | delete array; |
505 | return ""; | |
506 | } | |
507 | ||
508 | TString value(""); | |
509 | ||
5eabea87 | 510 | if ( index < 0 ) |
511 | { | |
512 | value = static_cast<TObjString*>(array->Last())->String(); | |
513 | } | |
514 | else if ( index <= array->GetLast() ) | |
d899f664 | 515 | { |
516 | value = static_cast<TObjString*>(array->At(index))->String(); | |
517 | } | |
518 | ||
519 | delete array; | |
520 | ||
521 | return value; | |
d899f664 | 522 | } |
523 | ||
524 | //_____________________________________________________________________________ | |
525 | TH1* | |
526 | AliHistogramCollection::InternalHisto(const char* identifier, | |
527 | const char* histoname) const | |
528 | { | |
529 | /// Get histo for (identifier,histoname) | |
530 | ||
531 | if (!fMap) | |
532 | { | |
533 | return 0x0; | |
534 | } | |
535 | ||
5eabea87 | 536 | THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier)); |
d899f664 | 537 | if (!hlist) |
538 | { | |
5eabea87 | 539 | TString msg(Form("Did not find hashlist for identifier=%s dir=%s",identifier,gDirectory ? gDirectory->GetName() : "" )); |
540 | fMessages[msg.Data()]++; | |
d899f664 | 541 | return 0x0; |
542 | } | |
543 | ||
5eabea87 | 544 | TH1* h = static_cast<TH1*>(hlist->FindObject(histoname)); |
545 | if (!h) | |
546 | { | |
547 | TString msg(Form("Did not find histoname=%s in %s",histoname,identifier)); | |
548 | fMessages[msg.Data()]++; | |
549 | } | |
550 | return h; | |
d899f664 | 551 | } |
552 | ||
d899f664 | 553 | //_____________________________________________________________________________ |
554 | TString | |
555 | AliHistogramCollection::KeyA(const char* identifier) const | |
556 | { | |
557 | /// Extract the first element of the key pair from an identifier | |
558 | ||
559 | return InternalDecode(identifier,0); | |
560 | } | |
561 | ||
562 | //_____________________________________________________________________________ | |
563 | TString | |
564 | AliHistogramCollection::KeyB(const char* identifier) const | |
565 | { | |
566 | /// Extract the second element (if present) | |
567 | return InternalDecode(identifier,1); | |
568 | } | |
569 | ||
570 | //_____________________________________________________________________________ | |
571 | TString | |
572 | AliHistogramCollection::KeyC(const char* identifier) const | |
573 | { | |
574 | /// Extract the 3rd element (if present) | |
575 | return InternalDecode(identifier,2); | |
576 | } | |
577 | ||
578 | //_____________________________________________________________________________ | |
579 | TString | |
580 | AliHistogramCollection::KeyD(const char* identifier) const | |
581 | { | |
582 | /// Extract the 4th element (if present) | |
583 | return InternalDecode(identifier,3); | |
584 | } | |
585 | ||
5eabea87 | 586 | //_____________________________________________________________________________ |
587 | TMap* AliHistogramCollection::Map() const | |
588 | { | |
589 | /// Wrapper to insure proper key formats (i.e. new vs old) | |
590 | ||
591 | if (!fMap) | |
592 | { | |
593 | fMap = new TMap; | |
594 | fMap->SetOwnerKeyValue(kTRUE,kTRUE); | |
595 | fMapVersion = 1; | |
596 | } | |
597 | else | |
598 | { | |
599 | if ( fMapVersion < 1 ) | |
600 | { | |
2f331ac9 | 601 | AliInfo("Remapping"); |
5eabea87 | 602 | // change the keys |
603 | TIter next(fMap); | |
604 | TObjString* str; | |
605 | ||
606 | while ( ( str = static_cast<TObjString*>(next()) ) ) | |
607 | { | |
608 | if ( str->String().Contains("./") ) | |
609 | { | |
610 | TString newkey(str->String()); | |
611 | ||
612 | newkey.ReplaceAll("./",""); | |
613 | ||
614 | TObject* o = fMap->GetValue(str); | |
615 | ||
616 | TPair* p = fMap->RemoveEntry(str); | |
617 | if (!p) | |
618 | { | |
619 | AliError("oups oups oups"); | |
620 | return 0x0; | |
621 | } | |
622 | ||
623 | fMap->Add(new TObjString(newkey.Data()),o); | |
624 | ||
625 | delete p; | |
626 | } | |
627 | } | |
628 | ||
629 | fMapVersion = 1; | |
630 | } | |
631 | } | |
632 | ||
633 | return fMap; | |
634 | } | |
635 | ||
d899f664 | 636 | //_____________________________________________________________________________ |
637 | Long64_t | |
638 | AliHistogramCollection::Merge(TCollection* list) | |
639 | { | |
640 | // Merge a list of AliHistogramCollection objects with this | |
641 | // Returns the number of merged objects (including this). | |
642 | ||
643 | if (!list) return 0; | |
644 | ||
645 | if (list->IsEmpty()) return 1; | |
646 | ||
647 | TIter next(list); | |
648 | TObject* o; | |
649 | TList mapList; | |
650 | Int_t count(0); | |
651 | ||
652 | while ( ( o = next() ) ) | |
653 | { | |
654 | AliHistogramCollection* hcol = dynamic_cast<AliHistogramCollection*>(o); | |
e6e96cea | 655 | if (!hcol) { |
656 | AliFatal(Form("object named \"%s\" is a %s instead of an AliHistogramCollection!", o->GetName(), o->ClassName())); | |
657 | continue; | |
658 | } | |
d899f664 | 659 | |
660 | ++count; | |
661 | ||
5eabea87 | 662 | if ( hcol->fMap ) hcol->Map(); // to insure keys in the new format |
663 | ||
d899f664 | 664 | TIter nextIdentifier(hcol->fMap); |
665 | TObjString* identifier; | |
666 | ||
667 | while ( ( identifier = static_cast<TObjString*>(nextIdentifier()) ) ) | |
668 | { | |
669 | THashList* otherList = static_cast<THashList*>(hcol->fMap->GetValue(identifier->String().Data())); | |
670 | ||
671 | TIter nextHisto(otherList); | |
672 | TH1* h; | |
673 | ||
674 | while ( ( h = static_cast<TH1*>(nextHisto()) ) ) | |
675 | { | |
5eabea87 | 676 | TString newid(Form("%s%s",identifier->String().Data(),h->GetName())); |
677 | ||
678 | TH1* thisHisto = Histo(newid.Data()); | |
d899f664 | 679 | |
680 | if (!thisHisto) | |
681 | { | |
d899f664 | 682 | // this is an histogram we don't have yet. Let's add it |
5eabea87 | 683 | |
684 | Int_t nslashes = TString(newid).CountChar('/'); | |
685 | ||
686 | Bool_t ok(kFALSE); | |
687 | ||
688 | switch (nslashes) | |
689 | { | |
2f331ac9 | 690 | case 0: |
691 | ok = Adopt(static_cast<TH1*>(h->Clone())); | |
692 | break; | |
5eabea87 | 693 | case 2: |
694 | ok = Adopt(KeyA(identifier->String()), | |
695 | static_cast<TH1*>(h->Clone())); | |
696 | break; | |
697 | case 3: | |
698 | ok = Adopt(KeyA(identifier->String()), | |
699 | KeyB(identifier->String()), | |
700 | static_cast<TH1*>(h->Clone())); | |
701 | break; | |
702 | case 4: | |
703 | ok = Adopt(KeyA(identifier->String()), | |
704 | KeyB(identifier->String()), | |
705 | KeyC(identifier->String()), | |
706 | static_cast<TH1*>(h->Clone())); | |
707 | break; | |
708 | case 5: | |
709 | ok = Adopt(KeyA(identifier->String()), | |
710 | KeyB(identifier->String()), | |
711 | KeyC(identifier->String()), | |
712 | KeyD(identifier->String()), | |
713 | static_cast<TH1*>(h->Clone())); | |
714 | break; | |
715 | default: | |
2f331ac9 | 716 | AliError(Form("Invalid identifier : %s",identifier->String().Data())); |
5eabea87 | 717 | break; |
718 | } | |
719 | ||
720 | if (!ok) | |
721 | { | |
722 | AliError(Form("Adoption of histogram %s failed",h->GetName())); | |
723 | } | |
d899f664 | 724 | } |
725 | else | |
726 | { | |
727 | // add it... | |
5eabea87 | 728 | if ( HistoSameAxis(h,thisHisto) ) |
729 | { | |
730 | thisHisto->Add(h); | |
731 | } | |
732 | else | |
733 | { | |
734 | TList l; | |
735 | l.Add(h); | |
736 | ||
737 | thisHisto->Merge(&l); | |
738 | } | |
d899f664 | 739 | } |
740 | } | |
741 | } | |
742 | } | |
d899f664 | 743 | |
744 | return count+1; | |
745 | } | |
746 | ||
5eabea87 | 747 | //_____________________________________________________________________________ |
748 | TString AliHistogramCollection::NormalizeName(const char* identifier,const char* action) const | |
749 | { | |
750 | // Replace / by _ to build a root-compliant histo name | |
2f331ac9 | 751 | TString name(GetName()); |
752 | ||
753 | name += "_"; | |
754 | name += identifier; | |
5eabea87 | 755 | name += "_"; |
756 | name += action; | |
757 | name.ReplaceAll("/","_"); | |
2f331ac9 | 758 | name.ReplaceAll("-","_"); |
5eabea87 | 759 | return name; |
760 | } | |
761 | ||
d899f664 | 762 | //_____________________________________________________________________________ |
763 | Int_t | |
764 | AliHistogramCollection::NumberOfHistograms() const | |
765 | { | |
766 | /// Get the number of histograms we hold | |
767 | TIter next(CreateIterator(this)); | |
768 | Int_t n(0); | |
769 | while ( next() ) ++n; | |
770 | return n; | |
771 | } | |
772 | ||
773 | //_____________________________________________________________________________ | |
774 | Int_t | |
775 | AliHistogramCollection::NumberOfKeys() const | |
776 | { | |
777 | /// Get the number of keys we have | |
778 | return fMap ? fMap->GetSize() : 0; | |
779 | } | |
780 | ||
781 | //_____________________________________________________________________________ | |
782 | void | |
783 | AliHistogramCollection::Print(Option_t* option) const | |
784 | { | |
785 | /// Print all the histograms we hold, in a hopefully visually pleasing | |
786 | /// way. | |
787 | /// | |
788 | /// Option can be used to select given part only, using the schema : | |
789 | /// /*/*/*/*/* | |
790 | /// Where the stars are wilcards for /keyA/keyB/keyC/KeyD/histoname | |
791 | /// | |
792 | /// if * is used it is assumed to be a wildcard for histoname | |
793 | /// | |
794 | /// For other selections the full syntax /*/*/*/*/* must be used. | |
795 | /// | |
796 | /// Use "-" as histoname to disable histogram's name output | |
797 | ||
2f331ac9 | 798 | cout << Form("AliHistogramCollection(%s,%s) : %d keys and %d histos", |
799 | GetName(),GetTitle(), | |
d899f664 | 800 | NumberOfKeys(), NumberOfHistograms()) << endl; |
801 | ||
802 | if (!strlen(option)) return; | |
803 | ||
804 | TString sreKeyA("*"); | |
805 | TString sreKeyB("*"); | |
806 | TString sreKeyC("*"); | |
807 | TString sreKeyD("*"); | |
808 | TString sreHistoname("*"); | |
809 | ||
810 | TObjArray* select = TString(option).Tokenize("/"); | |
811 | Int_t n = select->GetLast(); | |
812 | ||
813 | if (n>=0) | |
814 | { | |
815 | sreHistoname = static_cast<TObjString*>(select->At(n))->String(); | |
816 | } | |
817 | if (n>=1) | |
818 | { | |
819 | sreKeyD = static_cast<TObjString*>(select->At(n-1))->String(); | |
820 | } | |
821 | if (n>=2) | |
822 | { | |
823 | sreKeyC = static_cast<TObjString*>(select->At(n-2))->String(); | |
824 | } | |
825 | if (n>=3) | |
826 | { | |
827 | sreKeyB = static_cast<TObjString*>(select->At(n-3))->String(); | |
828 | } | |
829 | if (n>=4) | |
830 | { | |
831 | sreKeyA = static_cast<TObjString*>(select->At(n-3))->String(); | |
832 | } | |
833 | ||
834 | TRegexp reKeyA(sreKeyA,kTRUE); | |
835 | TRegexp reKeyB(sreKeyB,kTRUE); | |
836 | TRegexp reKeyC(sreKeyC,kTRUE); | |
837 | TRegexp reKeyD(sreKeyD,kTRUE); | |
838 | TRegexp reHistoname(sreHistoname,kTRUE); | |
839 | ||
840 | delete select; | |
841 | ||
842 | TObjArray* identifiers = SortAllIdentifiers(); | |
5eabea87 | 843 | |
d899f664 | 844 | TIter nextIdentifier(identifiers); |
845 | ||
846 | TObjString* sid(0x0); | |
847 | ||
848 | while ( ( sid = static_cast<TObjString*>(nextIdentifier()) ) ) | |
849 | { | |
850 | Bool_t identifierPrinted(kFALSE); | |
851 | ||
852 | TString identifier(sid->String()); | |
853 | ||
5eabea87 | 854 | if ( ( InternalDecode(identifier,0).Contains(reKeyA) && |
855 | InternalDecode(identifier,1).Contains(reKeyB) && | |
856 | InternalDecode(identifier,2).Contains(reKeyC) && | |
857 | InternalDecode(identifier,3).Contains(reKeyD) ) | |
d899f664 | 858 | ) |
859 | { | |
860 | if ( sreHistoname == "*" ) | |
861 | { | |
862 | identifierPrinted = kTRUE; | |
863 | cout << identifier.Data() << endl; | |
864 | } | |
865 | ||
5eabea87 | 866 | THashList * list = static_cast<THashList*>(Map()->GetValue(sid->String().Data())); |
d899f664 | 867 | TObjArray names; |
868 | names.SetOwner(kTRUE); | |
869 | TIter nextUnsortedHisto(list); | |
870 | TH1* h; | |
871 | while ( ( h = static_cast<TH1*>(nextUnsortedHisto()) ) ) | |
872 | { | |
873 | names.Add(new TObjString(h->GetName())); | |
874 | } | |
875 | names.Sort(); | |
876 | TIter nextHistoName(&names); | |
877 | TObjString* hname; | |
878 | while ( ( hname = static_cast<TObjString*>(nextHistoName()) ) ) | |
879 | { | |
880 | TString histoName(hname->String()); | |
881 | if (histoName.Contains(reHistoname) ) | |
882 | { | |
883 | h = static_cast<TH1*>(list->FindObject(histoName.Data())); | |
884 | if ( h->GetEntries()==0 && !fMustShowEmptyHistogram ) continue; | |
885 | if (!identifierPrinted) | |
886 | { | |
887 | cout << identifier.Data() << endl; | |
888 | identifierPrinted = kTRUE; | |
889 | } | |
890 | cout << Form(" %s %s Entries=%d Sum=%g",h->GetName(),h->GetTitle(),Int_t(h->GetEntries()),h->GetSumOfWeights()) << endl; | |
891 | } | |
892 | } | |
893 | if (!identifierPrinted && sreHistoname=="-" ) | |
894 | { | |
895 | // to handle the case where we used histoname="-" to disable showing the histonames, | |
896 | // but we still want to see the matching keys maybe... | |
897 | cout << identifier.Data() << endl; | |
898 | } | |
899 | } | |
900 | } | |
901 | ||
902 | delete identifiers; | |
903 | } | |
904 | ||
5eabea87 | 905 | //_____________________________________________________________________________ |
906 | void | |
907 | AliHistogramCollection::PrintMessages(const char* prefix) const | |
908 | { | |
909 | /// Print pending messages | |
910 | ||
911 | std::map<std::string,int>::const_iterator it; | |
912 | ||
913 | for ( it = fMessages.begin(); it != fMessages.end(); ++it ) | |
914 | { | |
915 | cout << Form("%s : message %s appeared %5d times",prefix,it->first.c_str(),it->second) << endl; | |
916 | } | |
917 | } | |
918 | ||
919 | ||
d899f664 | 920 | //_____________________________________________________________________________ |
921 | UInt_t | |
922 | AliHistogramCollection::EstimateSize(Bool_t show) const | |
923 | { | |
2f331ac9 | 924 | /// Estimate the memory (in bytes) used by our histograms |
d899f664 | 925 | |
926 | // sizeof(TH1) + (nbins+2)*(nbytes_per_bin) +name+title_sizes | |
927 | // if you have errors add (nbins+2)*8 | |
d440e2c5 | 928 | |
929 | TMap sizeMap; | |
930 | sizeMap.SetOwnerKeyValue(kTRUE,kTRUE); | |
931 | ||
d899f664 | 932 | TIter next(CreateIterator()); |
933 | TH1* h; | |
934 | UInt_t n(0); | |
935 | ||
936 | while ( ( h = static_cast<TH1*>(next()) ) ) | |
937 | { | |
938 | Int_t nbins = (h->GetNbinsX()+2); | |
939 | ||
940 | if (h->GetNbinsY()>1) | |
941 | { | |
942 | nbins *= (h->GetNbinsY()+2); | |
943 | } | |
944 | ||
945 | if (h->GetNbinsZ()>1) | |
946 | { | |
947 | nbins *= (h->GetNbinsZ()+2); | |
948 | } | |
949 | ||
950 | Bool_t hasErrors = ( h->GetSumw2N() > 0 ); | |
951 | ||
952 | TString cname(h->ClassName()); | |
953 | ||
954 | Int_t nbytesPerBin(0); | |
955 | ||
956 | if (cname.Contains(TRegexp("C$")) ) nbytesPerBin = sizeof(Char_t); | |
957 | if (cname.Contains(TRegexp("S$")) ) nbytesPerBin = sizeof(Short_t); | |
958 | if (cname.Contains(TRegexp("I$")) ) nbytesPerBin = sizeof(Int_t); | |
959 | if (cname.Contains(TRegexp("F$")) ) nbytesPerBin = sizeof(Float_t); | |
960 | if (cname.Contains(TRegexp("D$")) ) nbytesPerBin = sizeof(Double_t); | |
961 | ||
962 | if (!nbytesPerBin) | |
963 | { | |
964 | AliError(Form("Could not get the number of bytes per bin for histo %s of class %s. Thus the size estimate will be wrong !", | |
965 | h->GetName(),h->ClassName())); | |
966 | continue; | |
967 | } | |
968 | ||
969 | UInt_t thissize = sizeof(h) + nbins*(nbytesPerBin) + strlen(h->GetName()) | |
970 | + strlen(h->GetTitle()); | |
971 | ||
d440e2c5 | 972 | TObjString* m = static_cast<TObjString*>(sizeMap.GetValue(h->GetName())); |
973 | ||
974 | if (!m) | |
975 | { | |
976 | m = new TObjString(Form("%u %u",thissize,1)); | |
977 | sizeMap.Add(new TObjString(h->GetName()),m); | |
978 | } | |
979 | else | |
980 | { | |
981 | UInt_t s; | |
982 | UInt_t d; | |
983 | ||
984 | sscanf(m->String().Data(),"%u %u",&s,&d); | |
985 | ||
986 | s += thissize; | |
987 | ++d; | |
988 | ||
989 | m->String().Form("%u %u",s,d); | |
990 | } | |
991 | ||
d899f664 | 992 | if ( hasErrors) thissize += nbins*8; |
993 | ||
994 | n += thissize; | |
995 | ||
d440e2c5 | 996 | } |
997 | ||
998 | if ( show ) | |
999 | { | |
1000 | std::multimap<UInt_t,std::string> sorted; | |
1001 | ||
1002 | TIter nextMapSize(&sizeMap); | |
1003 | TObjString* m; | |
1004 | ||
1005 | UInt_t s; | |
1006 | UInt_t d; | |
1007 | ||
1008 | while ( ( m = static_cast<TObjString*>(nextMapSize()) ) ) | |
1009 | { | |
1010 | ||
1011 | TObjString* sizeMsg = static_cast<TObjString*>(sizeMap.GetValue(m->String())); | |
1012 | ||
1013 | sscanf(sizeMsg->String().Data(),"%u %u",&s,&d); | |
1014 | ||
1015 | sorted.insert(std::pair<UInt_t,std::string>(s,m->String().Data())); | |
1016 | } | |
1017 | ||
1018 | std::multimap<UInt_t,std::string>::const_iterator it; | |
1019 | ||
1020 | for ( it = sorted.begin(); it != sorted.end(); ++it ) | |
d899f664 | 1021 | { |
d440e2c5 | 1022 | TObjString* sizeMsg = static_cast<TObjString*>(sizeMap.GetValue(it->second.c_str())); |
1023 | ||
1024 | sscanf(sizeMsg->String().Data(),"%u %u",&s,&d); | |
1025 | ||
1026 | AliInfo(Form("%40s : size %10u (%7u per object, %6d objects)", | |
1027 | it->second.c_str(),s,s/d,d)); | |
1028 | ||
d899f664 | 1029 | } |
1030 | } | |
1031 | ||
1032 | return n; | |
1033 | } | |
1034 | ||
1035 | //_____________________________________________________________________________ | |
1036 | void AliHistogramCollection::PruneEmptyHistograms() | |
1037 | { | |
1038 | /// Delete the empty histograms | |
5eabea87 | 1039 | TIter next(Map()); |
d899f664 | 1040 | TObjString* key; |
1041 | ||
1042 | TList toBeRemoved; | |
1043 | toBeRemoved.SetOwner(kTRUE); | |
1044 | ||
1045 | while ( ( key = static_cast<TObjString*>(next()) ) ) | |
1046 | { | |
1047 | TString identifier(key->String()); | |
5eabea87 | 1048 | THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier.Data())); |
d899f664 | 1049 | TIter nextHisto(hlist); |
1050 | TH1* h; | |
1051 | while ( ( h = static_cast<TH1*>(nextHisto()))) | |
1052 | { | |
1053 | if ( h->GetEntries()==0) | |
1054 | { | |
1055 | toBeRemoved.Add(new TObjString(Form("%s%s",identifier.Data(),h->GetName()))); | |
1056 | } | |
1057 | } | |
1058 | } | |
1059 | ||
1060 | TIter nextTBR(&toBeRemoved); | |
1061 | while ( ( key = static_cast<TObjString*>(nextTBR()) ) ) | |
1062 | { | |
1063 | Remove(key); | |
1064 | } | |
1065 | } | |
1066 | ||
1067 | //_____________________________________________________________________________ | |
1068 | AliHistogramCollection* | |
5eabea87 | 1069 | AliHistogramCollection::Project(const char* keyA, const char* keyB, const char* keyC, const char* keyD) const |
d899f664 | 1070 | { |
2f331ac9 | 1071 | /// Create a new collection starting at keyA/keyB/keyC/keyD |
1072 | /// Histograms are *copied* | |
5eabea87 | 1073 | |
1074 | if (!fMap) return 0x0; | |
1075 | ||
1076 | AliHistogramCollection* hc = new AliHistogramCollection(Form("%s %s/%s/%s/%s",GetName(),keyA,keyB,keyC,keyD), | |
1077 | GetTitle()); | |
1078 | ||
1079 | TIter next(Map()); | |
1080 | TObjString* str; | |
1081 | ||
1082 | while ( ( str = static_cast<TObjString*>(next()) ) ) | |
1083 | { | |
1084 | TString identifier = str->String(); | |
1085 | ||
1086 | Bool_t copy= ( KeyA(identifier) == keyA && | |
1087 | ( strlen(keyB)==0 || KeyB(identifier)==keyB ) && | |
1088 | ( strlen(keyC)==0 || KeyC(identifier)==keyC ) && | |
1089 | ( strlen(keyD)==0 || KeyD(identifier)==keyD )); | |
1090 | ||
1091 | if ( !copy ) continue; | |
1092 | ||
1093 | THashList* list = static_cast<THashList*>(Map()->GetValue(identifier.Data())); | |
1094 | ||
1095 | TIter nextHisto(list); | |
1096 | TH1* h; | |
1097 | ||
1098 | while ( ( h = static_cast<TH1*>(nextHisto()) ) ) | |
1099 | { | |
1100 | TH1* hclone = static_cast<TH1*>(h->Clone()); | |
1101 | ||
1102 | TString newkey(identifier.Data()); | |
1103 | ||
1104 | if ( strlen(keyD) > 0 ) newkey.ReplaceAll(Form("/%s",keyD),""); | |
1105 | if ( strlen(keyC) > 0 ) newkey.ReplaceAll(Form("/%s",keyC),""); | |
1106 | if ( strlen(keyB) > 0 ) newkey.ReplaceAll(Form("/%s",keyB),""); | |
1107 | if ( strlen(keyA) > 0 ) newkey.ReplaceAll(Form("/%s",keyA),""); | |
1108 | ||
1109 | if (newkey=="/") newkey=""; | |
1110 | ||
1111 | hc->InternalAdopt(newkey.Data(),hclone); | |
1112 | } | |
1113 | } | |
1114 | ||
1115 | return hc; | |
d899f664 | 1116 | } |
1117 | ||
1118 | //_____________________________________________________________________________ | |
1119 | TObject* | |
1120 | AliHistogramCollection::Remove(TObject* key) | |
1121 | { | |
1122 | /// | |
1123 | /// Remove a given histogram (given its key=full identifier=/keyA/keyB/keyC/keyD/histoname) | |
1124 | /// | |
1125 | /// Note that we do *not* remove the /keyA/keyB/keyC/keyD entry even if there's no | |
1126 | /// more histogram for this triplet. | |
1127 | /// | |
1128 | /// Not very efficient. Could be improved ? | |
1129 | /// | |
1130 | ||
1131 | TObjString* str = dynamic_cast<TObjString*>(key); | |
1132 | ||
1133 | if (!str) | |
1134 | { | |
1135 | AliError(Form("key is not of the expected TObjString type, but of %s",key->ClassName())); | |
1136 | return 0x0; | |
1137 | } | |
1138 | ||
1139 | TString identifier(str->String()); | |
1140 | ||
5eabea87 | 1141 | Int_t nslashes = TString(identifier).CountChar('/'); |
1142 | ||
1143 | TString skey; | |
1144 | ||
1145 | switch (nslashes ) | |
1146 | { | |
1147 | case 2: | |
1148 | skey = Form("/%s/", | |
1149 | KeyA(identifier).Data()); | |
1150 | break; | |
1151 | case 3: | |
1152 | skey = Form("/%s/%s/", | |
1153 | KeyA(identifier).Data(), | |
1154 | KeyB(identifier).Data()); | |
1155 | break; | |
1156 | case 4: | |
1157 | skey = Form("/%s/%s/%s/", | |
1158 | KeyA(identifier).Data(), | |
1159 | KeyB(identifier).Data(), | |
1160 | KeyC(identifier).Data()); | |
1161 | break; | |
1162 | case 5: | |
1163 | skey = Form("/%s/%s/%s/%s/", | |
1164 | KeyA(identifier).Data(), | |
1165 | KeyB(identifier).Data(), | |
1166 | KeyC(identifier).Data(), | |
1167 | KeyD(identifier).Data() | |
1168 | ); | |
1169 | break; | |
1170 | default: | |
1171 | AliError("Oups"); | |
1172 | break; | |
1173 | }; | |
d899f664 | 1174 | |
5eabea87 | 1175 | THashList* hlist = dynamic_cast<THashList*>(Map()->GetValue(skey.Data())); |
d899f664 | 1176 | |
1177 | if (!hlist) | |
1178 | { | |
1179 | AliWarning(Form("Could not get hlist for key=%s",skey.Data())); | |
1180 | return 0x0; | |
1181 | } | |
1182 | ||
1183 | TH1* h = InternalHisto(skey,HistoName(identifier.Data())); | |
1184 | if (!h) | |
1185 | { | |
1186 | AliError(Form("Could not find histo %s",identifier.Data())); | |
1187 | return 0x0; | |
1188 | } | |
1189 | ||
1190 | TObject* o = hlist->Remove(h); | |
1191 | if (!o) | |
1192 | { | |
1193 | AliError("Remove failed"); | |
1194 | return 0x0; | |
1195 | } | |
d899f664 | 1196 | |
1197 | return o; | |
1198 | } | |
1199 | ||
5eabea87 | 1200 | //______________________________________________________________________________ |
1201 | Bool_t AliHistogramCollection::HistoSameAxis(TH1 *h0, TH1 *h1) const | |
1202 | { | |
1203 | // shameless copy from TProofPlayerRemote::HistoSameAxis | |
1204 | // | |
1205 | // Return kTRUE is the histograms 'h0' and 'h1' have the same binning and ranges | |
1206 | // on the axis (i.e. if they can be just Add-ed for merging). | |
1207 | ||
1208 | Bool_t rc = kFALSE; | |
1209 | if (!h0 || !h1) return rc; | |
1210 | ||
1211 | TAxis *a0 = 0, *a1 = 0; | |
1212 | ||
1213 | // Check X | |
1214 | a0 = h0->GetXaxis(); | |
1215 | a1 = h1->GetXaxis(); | |
1216 | if (a0->GetNbins() == a1->GetNbins()) | |
1217 | if (TMath::Abs(a0->GetXmax() - a1->GetXmax()) < 1.e-9) | |
1218 | if (TMath::Abs(a0->GetXmin() - a1->GetXmin()) < 1.e-9) rc = kTRUE; | |
1219 | ||
1220 | // Check Y, if needed | |
1221 | if (h0->GetDimension() > 1) { | |
1222 | rc = kFALSE; | |
1223 | a0 = h0->GetYaxis(); | |
1224 | a1 = h1->GetYaxis(); | |
1225 | if (a0->GetNbins() == a1->GetNbins()) | |
1226 | if (TMath::Abs(a0->GetXmax() - a1->GetXmax()) < 1.e-9) | |
1227 | if (TMath::Abs(a0->GetXmin() - a1->GetXmin()) < 1.e-9) rc = kTRUE; | |
1228 | } | |
1229 | ||
1230 | // Check Z, if needed | |
1231 | if (h0->GetDimension() > 2) { | |
1232 | rc = kFALSE; | |
1233 | a0 = h0->GetZaxis(); | |
1234 | a1 = h1->GetZaxis(); | |
1235 | if (a0->GetNbins() == a1->GetNbins()) | |
1236 | if (TMath::Abs(a0->GetXmax() - a1->GetXmax()) < 1.e-9) | |
1237 | if (TMath::Abs(a0->GetXmin() - a1->GetXmin()) < 1.e-9) rc = kTRUE; | |
1238 | } | |
1239 | ||
1240 | // Done | |
1241 | return rc; | |
1242 | } | |
1243 | ||
d899f664 | 1244 | //_____________________________________________________________________________ |
1245 | TObjArray* | |
1246 | AliHistogramCollection::SortAllIdentifiers() const | |
1247 | { | |
1248 | /// Sort our internal identifiers. Returned array must be deleted. | |
1249 | TObjArray* identifiers = new TObjArray; | |
1250 | identifiers->SetOwner(kFALSE); | |
5eabea87 | 1251 | TIter next(Map()); |
d899f664 | 1252 | TObjString* sid; |
1253 | ||
1254 | while ( ( sid = static_cast<TObjString*>(next()) ) ) | |
1255 | { | |
1256 | if ( !identifiers->FindObject(sid->String().Data()) ) | |
1257 | { | |
1258 | identifiers->Add(sid); | |
1259 | } | |
1260 | } | |
1261 | identifiers->Sort(); | |
1262 | return identifiers; | |
1263 | } | |
1264 | ||
1265 | ||
1266 | /////////////////////////////////////////////////////////////////////////////// | |
1267 | // | |
1268 | // AliHistogramCollectionIterator | |
1269 | // | |
1270 | /////////////////////////////////////////////////////////////////////////////// | |
1271 | ||
1272 | class AliHistogramCollectionIterator; | |
1273 | ||
1274 | //_____________________________________________________________________________ | |
1275 | AliHistogramCollectionIterator::AliHistogramCollectionIterator(const AliHistogramCollection* hcol, Bool_t dir) | |
1276 | : fkHistogramCollection(hcol), fMapIterator(0x0), fHashListIterator(0x0), fDirection(dir) | |
1277 | { | |
1278 | /// Default ctor | |
1279 | } | |
1280 | ||
1281 | //_____________________________________________________________________________ | |
1282 | AliHistogramCollectionIterator& | |
1283 | AliHistogramCollectionIterator::operator=(const TIterator&) | |
1284 | { | |
1285 | /// Overriden operator= (imposed by Root's declaration of TIterator ?) | |
1286 | Fatal("TIterator::operator=","Not implementeable"); // because there's no clone in TIterator :-( | |
1287 | return *this; | |
1288 | } | |
1289 | ||
1290 | //_____________________________________________________________________________ | |
1291 | AliHistogramCollectionIterator::~AliHistogramCollectionIterator() | |
1292 | { | |
1293 | /// dtor | |
1294 | Reset(); | |
1295 | } | |
1296 | ||
1297 | //_____________________________________________________________________________ | |
1298 | TObject* AliHistogramCollectionIterator::Next() | |
1299 | { | |
1300 | /// Advance to next object in the collection | |
1301 | ||
1302 | if (!fHashListIterator) | |
1303 | { | |
1304 | if ( !fMapIterator ) | |
1305 | { | |
2f331ac9 | 1306 | fMapIterator = fkHistogramCollection->Map()->MakeIterator(fDirection); |
d899f664 | 1307 | } |
1308 | TObjString* key = static_cast<TObjString*>(fMapIterator->Next()); | |
1309 | if (!key) | |
1310 | { | |
1311 | // we are done | |
1312 | return 0x0; | |
1313 | } | |
5eabea87 | 1314 | THashList* list = static_cast<THashList*>(fkHistogramCollection->Map()->GetValue(key->String().Data())); |
d899f664 | 1315 | if (!list) return 0x0; |
1316 | fHashListIterator = list->MakeIterator(fDirection); | |
1317 | } | |
1318 | ||
1319 | TObject* o = fHashListIterator->Next(); | |
1320 | ||
1321 | if (!o) | |
1322 | { | |
1323 | delete fHashListIterator; | |
1324 | fHashListIterator = 0x0; | |
1325 | return Next(); | |
1326 | } | |
1327 | ||
1328 | return o; | |
1329 | } | |
1330 | ||
1331 | //_____________________________________________________________________________ | |
1332 | void AliHistogramCollectionIterator::Reset() | |
1333 | { | |
1334 | /// Reset the iterator | |
1335 | delete fHashListIterator; | |
1336 | delete fMapIterator; | |
1337 | } |