Line data Source code
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: AliMergeableCollection.cxx 50593 2011-07-14 17:42:28Z martinez $
17 :
18 : ///
19 : /// A mergeable object container.
20 : ///
21 : /// For each tuple (key1,key2,..,keyN) a (hash)list of mergeable objects is associated.
22 : /// Note that key1, key2 (optional), ..., keyN (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 "AliMergeableCollection.h"
28 : #include <iostream>
29 :
30 : using std::cout;
31 : using std::endl;
32 176 : ClassImp(AliMergeableCollection)
33 :
34 : #include "AliLog.h"
35 : #include "Riostream.h"
36 : #include "TError.h"
37 : #include "TFolder.h"
38 : #include "TGraph.h"
39 : #include "TH1.h"
40 : #include "TH2.h"
41 : #include "THashList.h"
42 : #include "THnSparse.h"
43 : #include "TKey.h"
44 : #include "TMap.h"
45 : #include "TObjArray.h"
46 : #include "TObjString.h"
47 : #include "TProfile.h"
48 : #include "TRegexp.h"
49 : #include "TROOT.h"
50 : #include "TSystem.h"
51 : #include <cassert>
52 : #include <vector>
53 : #include "TBrowser.h"
54 :
55 : //_____________________________________________________________________________
56 : AliMergeableCollection::AliMergeableCollection(const char* name, const char* title)
57 0 : : TFolder(name,title), fMap(0x0), fMustShowEmptyObject(0), fMapVersion(0), fMessages()
58 0 : {
59 : /// Ctor
60 0 : }
61 :
62 : //_____________________________________________________________________________
63 : AliMergeableCollection::~AliMergeableCollection()
64 0 : {
65 : /// dtor. Note that the map is owner
66 0 : delete fMap;
67 0 : }
68 :
69 : //_____________________________________________________________________________
70 : Bool_t
71 : AliMergeableCollection::Adopt(TObject* obj)
72 : {
73 : /// Adopt a given object at top level (i.e. no key)
74 0 : return InternalAdopt("",obj);
75 : }
76 :
77 : //_____________________________________________________________________________
78 : void
79 : AliMergeableCollection::CorrectIdentifier(TString& sidentifier)
80 : {
81 : /// Insure identifier has the right number of slashes...
82 :
83 0 : if ( ! sidentifier.IsNull() )
84 : {
85 0 : if ( ! sidentifier.EndsWith("/") ) sidentifier.Append("/");
86 0 : if ( ! sidentifier.BeginsWith("/") ) sidentifier.Prepend("/");
87 0 : sidentifier.ReplaceAll("//","/");
88 0 : }
89 0 : }
90 :
91 : //_____________________________________________________________________________
92 : Bool_t
93 : AliMergeableCollection::Adopt(const char* identifier, TObject* obj)
94 : {
95 : /// Adopt a given object, and associate it with pair key
96 0 : TString sidentifier(identifier);
97 :
98 0 : CorrectIdentifier(sidentifier);
99 :
100 0 : return InternalAdopt(sidentifier.Data(),obj);
101 0 : }
102 :
103 : //_____________________________________________________________________________
104 : Bool_t AliMergeableCollection::Attach(AliMergeableCollection* mc, const char* identifier, Bool_t pruneFirstIfAlreadyExists)
105 : {
106 : /// Attach an already existing mergeable collection to this one.
107 : /// It is attached at level identifier/
108 : /// We take ownership of mc
109 : /// If identifier is already existing we kill it if pruneFirstIfAlreadyExists is kTRUE
110 : /// (and attach mc) otherwise we return kFALSE (and do *not* attach mc)
111 :
112 0 : THashList* hlist = dynamic_cast<THashList*>(Map()->GetValue(identifier));
113 :
114 0 : if (hlist)
115 : {
116 0 : if (!pruneFirstIfAlreadyExists)
117 : {
118 0 : AliError(Form("%s already exist. Will not overwrite it.",identifier));
119 0 : return kFALSE;
120 : }
121 : else
122 : {
123 0 : Int_t n = Prune(identifier);
124 0 : if (!n)
125 : {
126 0 : AliError(Form("Could not prune pre-existing %s",identifier));
127 0 : return kFALSE;
128 : }
129 0 : }
130 : }
131 :
132 0 : TIter next(mc->fMap);
133 : TObjString* str;
134 :
135 0 : while ( ( str = static_cast<TObjString*>(next())) )
136 : {
137 0 : THashList* hl = dynamic_cast<THashList*>(mc->Map()->GetValue(str->String()));
138 0 : TString newid(Form("/%s%s",identifier,str->String().Data()));
139 0 : newid.ReplaceAll("//","/");
140 0 : Map()->Add(new TObjString(newid.Data()),hl);
141 0 : }
142 :
143 : return kTRUE;
144 0 : }
145 :
146 : //_____________________________________________________________________________
147 : void AliMergeableCollection::Browse(TBrowser* b)
148 : {
149 : /// Create a TFolder structure pointing to our objects, so we
150 : /// can be "browsed"
151 :
152 0 : if ( !fFolders ) return;
153 :
154 0 : TObjArray* ids = SortAllIdentifiers();
155 0 : TIter nextIdentifier(ids);
156 : TObjString* str;
157 :
158 0 : while ( ( str = static_cast<TObjString*>(nextIdentifier()) ) )
159 : {
160 0 : TObjArray* parts = str->String().Tokenize("/");
161 : TObjString* s;
162 0 : TIter nextPart(parts);
163 : TFolder* base = this;
164 :
165 0 : while ( ( s = static_cast<TObjString*>(nextPart())))
166 : {
167 0 : TFolder* f = static_cast<TFolder*>(base->TFolder::FindObject(s->String()));
168 0 : if (!f)
169 : {
170 0 : f = new TFolder(s->String(),"");
171 0 : base->Add(f);
172 : }
173 : base = f;
174 : }
175 0 : delete parts;
176 :
177 0 : TList* list = CreateListOfObjectNames(str->String());
178 0 : if (list)
179 : {
180 : TObjString* oname;
181 0 : TIter nextObject(list);
182 0 : while ( ( oname = static_cast<TObjString*>(nextObject())) )
183 : {
184 0 : TObject* o = GetObject(str->String(),oname->String());
185 0 : base->Add(o);
186 : }
187 0 : }
188 : else
189 : {
190 0 : AliError("got list=0x0");
191 : }
192 0 : delete list;
193 0 : }
194 :
195 0 : TList* top = CreateListOfKeys(0);
196 : TObjString* stop;
197 0 : TIter nextTop(top);
198 :
199 0 : while ( ( stop = static_cast<TObjString*>(nextTop())) )
200 : {
201 0 : b->Add(TFolder::FindObject(stop->String()));
202 : }
203 :
204 0 : delete top;
205 :
206 0 : delete ids;
207 0 : }
208 :
209 : //_____________________________________________________________________________
210 : void AliMergeableCollection::ClearMessages()
211 : {
212 : /// clear pending messages
213 0 : fMessages.clear();
214 0 : }
215 :
216 : //_____________________________________________________________________________
217 : TIterator*
218 : AliMergeableCollection::CreateIterator(Bool_t direction) const
219 : {
220 : /// Create an iterator (must be deleted by the client)
221 0 : return fMap ? new AliMergeableCollectionIterator(this,direction) : 0x0;
222 0 : }
223 :
224 : //_____________________________________________________________________________
225 : AliMergeableCollectionProxy*
226 : AliMergeableCollection::CreateProxy(const char* identifier, Bool_t createIfNeeded)
227 : {
228 : /// Create a proxy starting at identifier.
229 : /// If createIfNeeded is true, then the identifier is inserted into
230 : /// the collection if it does not exist yet (in which case this method always
231 : /// returns a non null proxy)
232 :
233 0 : TString sidentifier(identifier);
234 0 : CorrectIdentifier(sidentifier);
235 :
236 0 : THashList* list = static_cast<THashList*>(Map()->GetValue(sidentifier));
237 0 : if (!list)
238 : {
239 0 : if (!createIfNeeded)
240 : {
241 0 : return 0x0;
242 : }
243 :
244 0 : list = new THashList;
245 0 : list->SetOwner(kTRUE);
246 :
247 0 : Map()->Add(new TObjString(sidentifier),list);
248 0 : list->SetName(sidentifier);
249 : }
250 0 : return new AliMergeableCollectionProxy(*this,*list);
251 0 : }
252 :
253 : //_____________________________________________________________________________
254 : AliMergeableCollection*
255 : AliMergeableCollection::Clone(const char* name) const
256 : {
257 : /// Clone this collection.
258 : /// We loose the messages.
259 :
260 0 : AliMergeableCollection* newone = new AliMergeableCollection(name,GetTitle());
261 :
262 0 : newone->fMap = static_cast<TMap*>(fMap->Clone());
263 0 : newone->fMustShowEmptyObject = fMustShowEmptyObject;
264 0 : newone->fMapVersion = fMapVersion;
265 :
266 0 : return newone;
267 0 : }
268 :
269 : //_____________________________________________________________________________
270 : void
271 : AliMergeableCollection::Delete(Option_t*)
272 : {
273 : /// Delete all the objects
274 0 : if (fMap)
275 : {
276 0 : fMap->DeleteAll();
277 0 : delete fMap;
278 0 : fMap=0x0;
279 0 : }
280 0 : }
281 :
282 : //_____________________________________________________________________________
283 : TObject*
284 : AliMergeableCollection::FindObject(const char* fullIdentifier) const
285 : {
286 : /// Find an object by its full identifier.
287 :
288 0 : return GetObject(fullIdentifier);
289 : }
290 :
291 : //_____________________________________________________________________________
292 : TObject*
293 : AliMergeableCollection::FindObject(const TObject *object) const
294 : {
295 : /// Find an object
296 0 : AliWarning("This method is awfully inefficient. Please improve it or use FindObject(const char*)");
297 0 : TIter next(CreateIterator());
298 : TObject* obj;
299 0 : while ( ( obj=next() ) )
300 : {
301 0 : if ( obj->IsEqual(object) ) return obj;
302 : }
303 0 : return 0x0;
304 0 : }
305 :
306 :
307 : //_____________________________________________________________________________
308 : TList*
309 : AliMergeableCollection::CreateListOfKeys(Int_t index) const
310 : {
311 : /// Create the list of keys at level index
312 :
313 0 : TList* list = new TList;
314 0 : list->SetOwner(kTRUE);
315 :
316 0 : TObjArray* ids = SortAllIdentifiers();
317 0 : TIter next(ids);
318 : TObjString* str;
319 :
320 0 : while ( ( str = static_cast<TObjString*>(next()) ) )
321 : {
322 0 : TString oneid = GetKey(str->String().Data(),index,kFALSE);
323 0 : if (oneid.Length()>0 && !list->Contains(oneid))
324 : {
325 0 : list->Add(new TObjString(oneid));
326 : }
327 0 : }
328 :
329 0 : delete ids;
330 : return list;
331 0 : }
332 :
333 : //_____________________________________________________________________________
334 : TList*
335 : AliMergeableCollection::CreateListOfObjectNames(const char* identifier) const
336 : {
337 : /// Create list of object names for /key1/key2/key...
338 : /// Returned list must be deleted by client
339 :
340 0 : TList* listOfNames = new TList;
341 0 : listOfNames->SetOwner(kTRUE);
342 :
343 0 : TIter next(Map());
344 : TObjString* str;
345 :
346 0 : while ( ( str = static_cast<TObjString*>(next()) ) )
347 : {
348 0 : TString currIdentifier = str->String();
349 0 : if ( currIdentifier.CompareTo(identifier) ) continue;
350 :
351 0 : THashList* list = static_cast<THashList*>(Map()->GetValue(identifier));
352 :
353 0 : TIter nextObject(list);
354 : TObject* obj;
355 :
356 0 : while ( ( obj = nextObject() ) )
357 : {
358 0 : listOfNames->Add(new TObjString(obj->GetName()));
359 : }
360 0 : }
361 :
362 : return listOfNames;
363 0 : }
364 :
365 :
366 : //_____________________________________________________________________________
367 : TString
368 : AliMergeableCollection::GetIdentifier(const char* fullIdentifier) const
369 : {
370 : /// Extract the identifier from the fullIdentifier
371 :
372 0 : TString identifier;
373 :
374 0 : Int_t n = TString(fullIdentifier).CountChar('/')-1;
375 :
376 0 : for (Int_t i=0; i < n; ++i)
377 : {
378 0 : identifier += "/";
379 0 : identifier += InternalDecode(fullIdentifier,i);
380 : }
381 0 : identifier += "/";
382 : return identifier;
383 0 : }
384 :
385 : //_____________________________________________________________________________
386 : TString
387 : AliMergeableCollection::GetKey(const char* identifier, Int_t index, Bool_t idContainsObjName) const
388 : {
389 : /// Extract the index element of the key pair from the fullIdentifier
390 :
391 0 : if ( ! idContainsObjName )
392 : {
393 0 : TString sidentifier(identifier);
394 0 : sidentifier.Append("/dummy");
395 0 : return InternalDecode(sidentifier.Data(),index);
396 0 : }
397 :
398 0 : return InternalDecode(identifier,index);
399 0 : }
400 :
401 : //_____________________________________________________________________________
402 : TString
403 : AliMergeableCollection::GetObjectName(const char* fullIdentifier) const
404 : {
405 : /// Extract the object name from an identifier
406 :
407 0 : return InternalDecode(fullIdentifier,-1);
408 : }
409 :
410 : //_____________________________________________________________________________
411 : TH1*
412 : AliMergeableCollection::Histo(const char* fullIdentifier) const
413 : {
414 : /// Get histogram key1/key2/.../objectName:action
415 : /// action is used for 2D histograms :
416 : /// might be px for projection along x-axis
417 : /// py for projection along y-axis
418 : /// pfx for profile along x-axis
419 : /// pfy for profile along y-axis
420 :
421 0 : TString sfullIdentifier(fullIdentifier);
422 :
423 0 : TString fullIdWithoutAction(fullIdentifier);
424 0 : TString action;
425 :
426 0 : if ( sfullIdentifier.First(':') != kNPOS )
427 : {
428 0 : TObjArray* arr = sfullIdentifier.Tokenize(":");
429 :
430 0 : fullIdWithoutAction = static_cast<TObjString*>(arr->At(0))->String();
431 :
432 0 : if ( arr->GetLast() > 0 )
433 : {
434 0 : action = static_cast<TObjString*>(arr->At(1))->String();
435 0 : action.ToUpper();
436 : }
437 :
438 0 : delete arr;
439 0 : }
440 :
441 0 : Int_t nslashes = sfullIdentifier.CountChar('/');
442 :
443 : TObject* o(0x0);
444 :
445 0 : if (!nslashes)
446 : {
447 0 : o = GetObject("", fullIdWithoutAction);
448 0 : }
449 : else
450 : {
451 0 : o = GetObject(GetIdentifier(fullIdWithoutAction).Data(), GetObjectName(fullIdWithoutAction));
452 : }
453 :
454 0 : return HistoWithAction(fullIdWithoutAction.Data(),o,action);
455 0 : }
456 :
457 : //_____________________________________________________________________________
458 : TH1*
459 : AliMergeableCollection::Histo(const char* identifier,
460 : const char* objectName) const
461 : {
462 : /// Get histogram key1/key2/.../objectName:action
463 : /// action is used for 2D histograms :
464 : /// might be px for projection along x-axis
465 : /// py for projection along y-axis
466 : /// pfx for profile along x-axis
467 : /// pfy for profile along y-axis
468 :
469 0 : TObject* o = GetObject(identifier,objectName);
470 :
471 0 : TString action;
472 :
473 0 : if ( strchr(objectName,':') )
474 : {
475 0 : TObjArray* arr = TString(objectName).Tokenize(":");
476 :
477 0 : if ( arr->GetLast() > 0 )
478 : {
479 0 : action = static_cast<TObjString*>(arr->At(1))->String();
480 0 : action.ToUpper();
481 : }
482 :
483 0 : delete arr;
484 :
485 0 : return HistoWithAction(identifier,o,action);
486 : }
487 :
488 0 : if (o && o->IsA()->InheritsFrom(TH1::Class()))
489 : {
490 0 : return static_cast<TH1*>(o);
491 : }
492 0 : return 0x0;
493 0 : }
494 :
495 :
496 : //_____________________________________________________________________________
497 : TH1*
498 : AliMergeableCollection::HistoWithAction(const char* identifier, TObject* o, const TString& action) const
499 : {
500 : /// Convert o to an histogram if possible, applying a given action if there
501 :
502 0 : if (!o) return 0x0;
503 :
504 0 : if (!o->InheritsFrom("TH1"))
505 : {
506 0 : AliError(Form("%s is not an histogram",o->GetName()));
507 0 : return 0x0;
508 : }
509 :
510 0 : TH2* h2 = dynamic_cast<TH2*>(o);
511 :
512 0 : if (h2)
513 : {
514 0 : if ( action == "PX" )
515 : {
516 0 : return h2->ProjectionX(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
517 : }
518 0 : if ( action == "PY" )
519 : {
520 0 : return h2->ProjectionY(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
521 : }
522 0 : if ( action == "PFX" )
523 : {
524 0 : return h2->ProfileX(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
525 : }
526 0 : if ( action == "PFY" )
527 : {
528 0 : return h2->ProfileY(NormalizeName(Form("%s/%s",identifier,o->GetName()),action.Data()).Data());
529 : }
530 : }
531 :
532 0 : return static_cast<TH1*>(o);
533 0 : }
534 :
535 : //_____________________________________________________________________________
536 : TH2*
537 : AliMergeableCollection::H2(const char* fullIdentifier) const
538 : {
539 : /// Short-cut method to grab a 2D histogram
540 : /// Will return 0x0 if the object if not a TH2xxx
541 :
542 0 : TObject* o = GetObject(fullIdentifier);
543 :
544 0 : if (o->IsA()->InheritsFrom(TH2::Class()))
545 : {
546 0 : return static_cast<TH2*>(o);
547 : }
548 0 : return 0x0;
549 0 : }
550 :
551 : //_____________________________________________________________________________
552 : TH2*
553 : AliMergeableCollection::H2(const char* identifier,
554 : const char* objectName) const
555 : {
556 : /// Short-cut method to grab a 2D histogram
557 : /// Will return 0x0 if the object if not a TH2xxx
558 :
559 0 : TObject* o = GetObject(identifier,objectName);
560 :
561 0 : if (o->IsA()->InheritsFrom(TH2::Class()))
562 : {
563 0 : return static_cast<TH2*>(o);
564 : }
565 0 : return 0x0;
566 0 : }
567 :
568 : //_____________________________________________________________________________
569 : TProfile*
570 : AliMergeableCollection::Prof(const char* fullIdentifier) const
571 : {
572 : /// Short-cut method to grab a TProfile histogram
573 : /// Will return 0x0 if the object if not a TProfile
574 :
575 0 : TObject* o = GetObject(fullIdentifier);
576 :
577 0 : if (o->IsA()->InheritsFrom(TProfile::Class()))
578 : {
579 0 : return static_cast<TProfile*>(o);
580 : }
581 0 : return 0x0;
582 0 : }
583 :
584 : //_____________________________________________________________________________
585 : TProfile*
586 : AliMergeableCollection::Prof(const char* identifier,
587 : const char* objectName) const
588 : {
589 : /// Short-cut method to grab a TProfile histogram
590 : /// Will return 0x0 if the object if not a TProfile
591 :
592 0 : TObject* o = GetObject(identifier,objectName);
593 :
594 0 : if (o->IsA()->InheritsFrom(TProfile::Class()))
595 : {
596 0 : return static_cast<TProfile*>(o);
597 : }
598 0 : return 0x0;
599 0 : }
600 :
601 : //_____________________________________________________________________________
602 : TObject*
603 : AliMergeableCollection::GetObject(const char* fullIdentifier) const
604 : {
605 : /// Get object key1/key2/.../objectName
606 : /// Note that no action is allowed for generic objects (only for histograms,
607 : /// see Histo() methods)
608 :
609 0 : TString sfullIdentifier(fullIdentifier);
610 :
611 0 : Int_t nslashes = sfullIdentifier.CountChar('/');
612 :
613 0 : if (!nslashes)
614 : {
615 0 : return GetObject("", sfullIdentifier);
616 : }
617 : else
618 : {
619 0 : return GetObject(GetIdentifier(fullIdentifier).Data(), GetObjectName(fullIdentifier));
620 : }
621 0 : }
622 :
623 : //_____________________________________________________________________________
624 : TObject*
625 : AliMergeableCollection::GetObject(const char* identifier,
626 : const char* objectName) const
627 : {
628 : /// Get object for (identifier,objectName) triplet
629 :
630 0 : TString sidentifier(identifier);
631 0 : if ( ! sidentifier.IsNull() ) {
632 0 : if ( ! sidentifier.BeginsWith("/") ) sidentifier.Prepend("/");
633 0 : if ( ! sidentifier.EndsWith("/") ) sidentifier.Append("/");
634 : }
635 0 : return InternalObject(sidentifier.Data(),objectName);
636 0 : }
637 :
638 : //_____________________________________________________________________________
639 : TObject* AliMergeableCollection::GetSum(const char* idPattern) const
640 : {
641 : /// Sum objects
642 : /// The pattern must be in the form:
643 : /// /key1_1,key1_2,.../key2_1,key2_2,.../.../objectName_1,objectName_2...
644 : /// The logical or between patterns separated by commas is taken
645 : /// Exact match is required for keys and objectNames
646 :
647 : TObject* sumObject = 0x0;
648 : TObjString* str = 0x0;
649 :
650 : // Build array of lists of pattern
651 0 : TString idPatternString(idPattern);
652 0 : TObjArray* keyList = idPatternString.Tokenize("/");
653 0 : TObjArray keyMatrix(keyList->GetEntriesFast());
654 0 : keyMatrix.SetOwner();
655 0 : TIter nextKey(keyList);
656 0 : while ( ( str = static_cast<TObjString*>(nextKey()) ) ) {
657 0 : TObjArray* subKeyList = str->String().Tokenize(",");
658 0 : keyMatrix.Add(subKeyList);
659 : }
660 0 : delete keyList;
661 :
662 0 : TString debugMsg = "Adding objects:";
663 :
664 : //
665 : // First handle the keys
666 : //
667 : TObjString* subKey = 0x0;
668 0 : TIter next(Map());
669 0 : while ( ( str = static_cast<TObjString*>(next()) ) )
670 : {
671 0 : TString identifier = str->String();
672 :
673 : Bool_t listMatchPattern = kTRUE;
674 0 : for ( Int_t ikey=0; ikey<keyMatrix.GetEntries()-1; ikey++ ) {
675 0 : TString currKey = GetKey(identifier, ikey, kFALSE);
676 : Bool_t matchKey = kFALSE;
677 0 : TObjArray* subKeyList = static_cast<TObjArray*> ( keyMatrix.At(ikey) );
678 0 : TIter nextSubKey(subKeyList);
679 0 : while ( (subKey=static_cast<TObjString*>(nextSubKey())) ) {
680 0 : TString subKeyString = subKey->String();
681 0 : if ( currKey == subKeyString ) {
682 : matchKey = kTRUE;
683 0 : break;
684 : }
685 0 : } // loop on the list of patterns of each key
686 0 : if ( ! matchKey ) {
687 : listMatchPattern = kFALSE;
688 0 : break;
689 : }
690 0 : } // loop on keys in the idPattern
691 0 : if ( ! listMatchPattern ) continue;
692 :
693 :
694 : //
695 : // Then handle the object name
696 : //
697 0 : THashList* list = static_cast<THashList*>(Map()->GetValue(identifier.Data()));
698 :
699 0 : TIter nextObj(list);
700 : TObject* obj;
701 :
702 0 : while ( ( obj = nextObj()) )
703 : {
704 0 : TString currKey = obj->GetName();
705 : Bool_t matchKey = kFALSE;
706 0 : TObjArray* subKeyList = static_cast<TObjArray*> ( keyMatrix.Last() );
707 0 : TIter nextSubKey(subKeyList);
708 0 : while ( (subKey=static_cast<TObjString*>(nextSubKey())) ) {
709 0 : TString subKeyString = subKey->String();
710 0 : if ( currKey == subKeyString ) {
711 : matchKey = kTRUE;
712 0 : break;
713 : }
714 0 : }
715 0 : if ( ! matchKey ) continue;
716 0 : if ( ! sumObject ) sumObject = obj->Clone();
717 0 : else MergeObject(sumObject, obj);
718 0 : debugMsg += Form(" %s%s",identifier.Data(),obj->GetName());
719 0 : } // loop on objects in list
720 0 : } // loop on identifiers in map
721 :
722 0 : AliDebug(1,debugMsg.Data());
723 :
724 : return sumObject;
725 0 : }
726 :
727 : //_____________________________________________________________________________
728 : Bool_t AliMergeableCollection::InternalAdopt(const char* identifier, TObject* obj)
729 : {
730 : /// Adopt an obj
731 :
732 0 : if (!obj)
733 : {
734 0 : Error("Adopt","Cannot adopt a null object");
735 0 : return kFALSE;
736 : }
737 :
738 0 : if ( ! obj->IsA()->InheritsFrom(TObject::Class()) ||
739 0 : ! obj->IsA()->GetMethodWithPrototype("Merge", "TCollection*") ) {
740 0 : Error("Adopt","Cannot adopt an object which is not mergeable!");
741 0 : }
742 :
743 : THashList* hlist = 0x0;
744 :
745 0 : hlist = static_cast<THashList*>(Map()->GetValue(identifier));
746 :
747 0 : if (!hlist)
748 : {
749 0 : hlist = new THashList;
750 0 : hlist->SetOwner(kTRUE);
751 0 : Map()->Add(new TObjString(identifier),hlist);
752 0 : hlist->SetName(identifier);
753 0 : }
754 :
755 0 : TObject* existingObj = hlist->FindObject(obj->GetName());
756 :
757 0 : if (existingObj)
758 : {
759 0 : AliError(Form("Cannot adopt an already existing object : %s -> %s",identifier,existingObj->GetName()));
760 0 : return kFALSE;
761 : }
762 :
763 0 : if ( obj->IsA()->InheritsFrom(TH1::Class()) ) (static_cast<TH1*> ( obj ))->SetDirectory(0);
764 :
765 0 : hlist->AddLast(obj);
766 :
767 0 : return kTRUE;
768 :
769 0 : }
770 :
771 : //_____________________________________________________________________________
772 : TString
773 : AliMergeableCollection::InternalDecode(const char* identifier, Int_t index) const
774 : {
775 : /// Extract the index-th element of the identifier (/key1/key2/.../keyN/objectName)
776 : /// object is index=-1 (i.e. last)
777 :
778 0 : if ( strlen(identifier) > 0 && identifier[0] != '/' )
779 : {
780 0 : AliError(Form("identifier %s is malformed (should start with /)",identifier));
781 0 : return "";
782 : }
783 :
784 0 : std::vector<Int_t> splitIndex;
785 :
786 : Int_t start(0);
787 0 : TString sidentifier(identifier);
788 :
789 0 : while (start < sidentifier.Length())
790 : {
791 0 : Int_t pos = sidentifier.Index('/', start);
792 0 : if (pos == kNPOS) break;
793 0 : splitIndex.push_back(pos);
794 0 : start = pos + 1;
795 0 : }
796 :
797 0 : Int_t nkeys = splitIndex.size() - 1;
798 :
799 0 : if ( index >= nkeys )
800 : {
801 0 : AliError(Form("Requiring index %i of identifier %s which only have %i",index, identifier, nkeys));
802 0 : return "";
803 : }
804 :
805 0 : if ( index < 0 )
806 : {
807 0 : return sidentifier(splitIndex.back()+1,sidentifier.Length()-splitIndex.back()-1);
808 : }
809 :
810 0 : return sidentifier(splitIndex[index]+1,splitIndex[index+1]-splitIndex[index]-1);
811 0 : }
812 :
813 : //_____________________________________________________________________________
814 : TObject*
815 : AliMergeableCollection::InternalObject(const char* identifier,
816 : const char* objectName) const
817 : {
818 : /// Get object for (identifier,objectName)
819 :
820 0 : if (!fMap)
821 : {
822 0 : return 0x0;
823 : }
824 :
825 0 : THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier));
826 0 : if (!hlist)
827 : {
828 0 : TString msg(Form("Did not find hashlist for identifier=%s dir=%s",identifier,gDirectory ? gDirectory->GetName() : "" ));
829 0 : fMessages[msg.Data()]++;
830 : return 0x0;
831 0 : }
832 :
833 0 : TObject* obj = hlist->FindObject(objectName);
834 0 : if (!obj)
835 : {
836 0 : TString msg(Form("Did not find objectName=%s in %s",objectName,identifier));
837 0 : fMessages[msg.Data()]++;
838 0 : }
839 : return obj;
840 0 : }
841 :
842 :
843 : //_____________________________________________________________________________
844 : Bool_t AliMergeableCollection::IsEmptyObject(TObject* obj) const
845 : {
846 : /// Check if object is empty
847 : /// (done only for TH1, so far)
848 :
849 0 : if ( obj->IsA()->InheritsFrom(TH1::Class()) ) {
850 0 : TH1* histo = static_cast<TH1*> (obj);
851 0 : if ( histo->GetEntries() == 0 ) return kTRUE;
852 0 : }
853 :
854 0 : return kFALSE;
855 :
856 0 : }
857 :
858 :
859 : //_____________________________________________________________________________
860 : TMap* AliMergeableCollection::Map() const
861 : {
862 : /// Wrapper to insure proper key formats (i.e. new vs old)
863 :
864 0 : if (!fMap)
865 : {
866 0 : fMap = new TMap;
867 0 : fMap->SetOwnerKeyValue(kTRUE,kTRUE);
868 0 : fMapVersion = 1;
869 0 : }
870 : else
871 : {
872 0 : if ( fMapVersion < 1 )
873 : {
874 0 : AliInfo("Remapping");
875 : // change the keys
876 0 : TIter next(fMap);
877 : TObjString* str;
878 :
879 0 : while ( ( str = static_cast<TObjString*>(next()) ) )
880 : {
881 0 : if ( str->String().Contains("./") )
882 : {
883 0 : TString newkey(str->String());
884 :
885 0 : newkey.ReplaceAll("./","");
886 :
887 0 : TObject* o = fMap->GetValue(str);
888 :
889 0 : TPair* p = fMap->RemoveEntry(str);
890 0 : if (!p)
891 : {
892 0 : AliError("oups oups oups");
893 0 : return 0x0;
894 : }
895 :
896 0 : fMap->Add(new TObjString(newkey.Data()),o);
897 :
898 0 : delete p;
899 0 : }
900 : }
901 :
902 0 : fMapVersion = 1;
903 0 : }
904 : }
905 :
906 0 : return fMap;
907 0 : }
908 :
909 : //_____________________________________________________________________________
910 : Long64_t
911 : AliMergeableCollection::Merge(TCollection* list)
912 : {
913 : // Merge a list of AliMergeableCollection objects with this
914 : // Returns the number of merged objects (including this).
915 :
916 0 : if (!list) return 0;
917 :
918 0 : if (list->IsEmpty()) return 1;
919 :
920 0 : TIter next(list);
921 : TObject* currObj;
922 0 : TList mapList;
923 : Long64_t count(0);
924 :
925 0 : while ( ( currObj = next() ) )
926 : {
927 0 : AliMergeableCollection* mergeCol = dynamic_cast<AliMergeableCollection*>(currObj);
928 0 : if (!mergeCol) {
929 0 : AliFatal(Form("object named \"%s\" is a %s instead of an AliMergeableCollection!", currObj->GetName(), currObj->ClassName()));
930 0 : continue;
931 : }
932 :
933 0 : ++count;
934 :
935 0 : if ( mergeCol->fMap ) mergeCol->Map(); // to insure keys in the new format
936 :
937 0 : TIter nextIdentifier(mergeCol->fMap);
938 : TObjString* identifier;
939 :
940 0 : while ( ( identifier = static_cast<TObjString*>(nextIdentifier()) ) )
941 : {
942 0 : THashList* otherList = static_cast<THashList*>(mergeCol->fMap->GetValue(identifier->String().Data()));
943 :
944 0 : TIter nextObject(otherList);
945 : TObject* obj;
946 :
947 0 : while ( ( obj = nextObject() ) )
948 : {
949 0 : TString newid(Form("%s%s",identifier->String().Data(),obj->GetName()));
950 :
951 0 : TObject* thisObject = GetObject(newid.Data());
952 :
953 0 : if (!thisObject)
954 : {
955 0 : Bool_t ok = Adopt(identifier->String(), obj->Clone());
956 :
957 0 : if (!ok)
958 : {
959 0 : AliError(Form("Adoption of object %s failed",obj->GetName()));
960 : }
961 0 : }
962 : else
963 : {
964 : // add it...
965 0 : MergeObject(thisObject, obj);
966 : }
967 0 : } // loop on objects in map
968 0 : } // loop on identifiers
969 0 : } // loop on collections in list
970 :
971 0 : return count+1;
972 0 : }
973 :
974 : //_____________________________________________________________________________
975 : Bool_t AliMergeableCollection::MergeObject(TObject* baseObject, TObject* objToAdd)
976 : {
977 : /// Add objToAdd to baseObject
978 :
979 0 : if ( baseObject->IsA()->Class() != objToAdd->IsA()->Class() ) {
980 0 : printf("MergeObject: Cannot add %s to %s", objToAdd->ClassName(), baseObject->ClassName());
981 0 : return kFALSE;
982 : }
983 0 : if ( ! baseObject->IsA()->InheritsFrom(TObject::Class()) ||
984 0 : ! baseObject->IsA()->GetMethodWithPrototype("Merge", "TCollection*") ) {
985 0 : printf("MergeObject: Objects are not mergeable!");
986 0 : return kFALSE;
987 : }
988 :
989 0 : TList list;
990 0 : list.Add(objToAdd);
991 :
992 0 : TString listArgs = Form("((TCollection*)0x%lx)", (ULong_t)&list);
993 0 : Int_t error = 0;
994 0 : baseObject->Execute("Merge", listArgs.Data(), &error);
995 : return kTRUE;
996 0 : }
997 :
998 : //_____________________________________________________________________________
999 : TString AliMergeableCollection::NormalizeName(const char* identifier,const char* action) const
1000 : {
1001 : /// Replace / by _ to build a root-compliant histo name
1002 0 : TString name(GetName());
1003 :
1004 0 : name += "_";
1005 0 : name += identifier;
1006 0 : name += "_";
1007 0 : name += action;
1008 0 : name.ReplaceAll("/","_");
1009 0 : name.ReplaceAll("-","_");
1010 : return name;
1011 0 : }
1012 :
1013 : //_____________________________________________________________________________
1014 : Int_t
1015 : AliMergeableCollection::NumberOfObjects() const
1016 : {
1017 : /// Get the number of objects we hold
1018 0 : TIter next(CreateIterator());
1019 : Int_t count(0);
1020 0 : while ( next() ) ++count;
1021 : return count;
1022 0 : }
1023 :
1024 : //_____________________________________________________________________________
1025 : Int_t
1026 : AliMergeableCollection::NumberOfKeys() const
1027 : {
1028 : /// Get the number of keys we have
1029 0 : return fMap ? fMap->GetSize() : 0;
1030 : }
1031 :
1032 : //_____________________________________________________________________________
1033 : void
1034 : AliMergeableCollection::Print(Option_t* option) const
1035 : {
1036 : /// Print all the objects we hold, in a hopefully visually pleasing
1037 : /// way.
1038 : ///
1039 : /// Option can be used to select given part only, using the schema :
1040 : /// /*/*/*/*/*
1041 : /// Where the stars are wilcards for /key1/key2/.../objectName
1042 : ///
1043 : /// if * is used it is assumed to be a wildcard for objectName
1044 : ///
1045 : /// For other selections the full syntax /*/*/*/*/* must be used.
1046 : ///
1047 : /// Use "-" as objectName to disable object's name output
1048 : ///
1049 : /// One might also use /*/*/*/*/:classname syntax to restrict
1050 : /// output to only those objects matching a given classname pattern
1051 : ///
1052 :
1053 0 : cout << Form("AliMergeableCollection(%s,%s)[%p] : %d keys and %d objects",
1054 0 : GetName(),GetTitle(),this,
1055 0 : NumberOfKeys(), NumberOfObjects()) << endl;
1056 :
1057 0 : if (!strlen(option)) return;
1058 :
1059 0 : TString soption(option);
1060 :
1061 0 : TObjArray* classes = soption.Tokenize(":");
1062 :
1063 : TRegexp* classPattern(0x0);
1064 :
1065 0 : if ( classes->GetLast() > 0 )
1066 : {
1067 0 : TString pat = static_cast<TObjString*>(classes->At(1))->String();
1068 0 : classPattern = new TRegexp(pat,kTRUE);
1069 0 : soption = static_cast<TObjString*>(classes->At(0))->String();
1070 0 : }
1071 :
1072 0 : delete classes;
1073 :
1074 0 : TObjArray* select = soption.Tokenize("/");
1075 :
1076 0 : TString sreObjectName(select->Last()->GetName());
1077 0 : TRegexp reObjectName(sreObjectName.Data(),kTRUE);
1078 :
1079 0 : TObjArray* identifiers = SortAllIdentifiers();
1080 :
1081 0 : std::cout << Form("Number of identifiers %d", identifiers->GetEntries()) << std::endl;
1082 :
1083 0 : TIter nextIdentifier(identifiers);
1084 :
1085 : TObjString* sid(0x0);
1086 :
1087 0 : while ( ( sid = static_cast<TObjString*>(nextIdentifier()) ) )
1088 : {
1089 : Bool_t identifierPrinted(kFALSE);
1090 :
1091 0 : TString identifier(sid->String());
1092 :
1093 : Bool_t matchPattern = kTRUE;
1094 0 : for ( Int_t isel=0; isel<select->GetLast(); isel++ ) {
1095 0 : if ( ! GetKey(identifier.Data(), isel, kFALSE).Contains(TRegexp(select->At(isel)->GetName(),kTRUE)) ) {
1096 : matchPattern = kFALSE;
1097 0 : break;
1098 : }
1099 : }
1100 0 : if ( ! matchPattern ) continue;
1101 :
1102 0 : if ( sreObjectName == "*" && !classPattern)
1103 : {
1104 : identifierPrinted = kTRUE;
1105 0 : cout << identifier.Data() << endl;
1106 : }
1107 :
1108 0 : THashList * list = static_cast<THashList*>(Map()->GetValue(sid->String().Data()));
1109 :
1110 0 : TObjArray names;
1111 0 : names.SetOwner(kTRUE);
1112 0 : TIter nextUnsortedObj(list);
1113 : TObject* obj;
1114 0 : while ( ( obj = nextUnsortedObj() ) )
1115 : {
1116 0 : TString cname(obj->ClassName());
1117 0 : if ( classPattern && !cname.Contains((*classPattern)) )
1118 : {
1119 0 : continue;
1120 : }
1121 0 : names.Add(new TObjString(obj->GetName()));
1122 0 : }
1123 0 : names.Sort();
1124 0 : TIter nextObjName(&names);
1125 : TObjString* oname;
1126 0 : while ( ( oname = static_cast<TObjString*>(nextObjName()) ) )
1127 : {
1128 0 : TString objName(oname->String());
1129 0 : if (objName.Contains(reObjectName) )
1130 : {
1131 0 : obj = list->FindObject(objName.Data());
1132 0 : if ( IsEmptyObject(obj) && ! fMustShowEmptyObject ) continue;
1133 :
1134 0 : if (!identifierPrinted)
1135 : {
1136 0 : cout << identifier.Data() << endl;
1137 : identifierPrinted = kTRUE;
1138 0 : }
1139 :
1140 0 : TString extra;
1141 0 : TString warning(" ");
1142 :
1143 0 : if ( obj->IsA()->InheritsFrom(TH1::Class()) )
1144 : {
1145 :
1146 0 : TH1* histo = static_cast<TH1*> (obj);
1147 0 : extra.Form("%s | Entries=%d Sum=%g",histo->GetTitle(),Int_t(histo->GetEntries()),histo->GetSumOfWeights());
1148 0 : }
1149 0 : else if ( obj->IsA()->InheritsFrom(TGraph::Class()) )
1150 : {
1151 0 : TGraph* graph = static_cast<TGraph*> (obj);
1152 0 : if ( ! TMath::Finite(graph->GetMean(2) ) )
1153 : {
1154 0 : warning = " ! ";
1155 : }
1156 0 : extra.Form("%s | Npts=%d Mean=%g RMS=%g",graph->GetTitle(),graph->GetN(),
1157 0 : graph->GetMean(2),graph->GetRMS(2));
1158 :
1159 0 : }
1160 :
1161 0 : std::cout << Form(" (%s) %s %s", obj->ClassName(),
1162 0 : warning.Data(),
1163 0 : obj->GetName());
1164 :
1165 0 : if ( extra.Length() )
1166 : {
1167 0 : std::cout << " | " << extra.Data();
1168 : }
1169 0 : std::cout << std::endl;
1170 0 : }
1171 0 : }
1172 0 : if (!identifierPrinted && sreObjectName=="-" )
1173 : {
1174 : // to handle the case where we used objectName="-" to disable showing the objectNames,
1175 : // but we still want to see the matching keys maybe...
1176 0 : cout << identifier.Data() << endl;
1177 : }
1178 0 : }
1179 :
1180 0 : delete select;
1181 :
1182 0 : delete identifiers;
1183 0 : }
1184 :
1185 : //_____________________________________________________________________________
1186 : void
1187 : AliMergeableCollection::PrintMessages(const char* prefix) const
1188 : {
1189 : /// Print pending messages
1190 :
1191 0 : std::map<std::string,int>::const_iterator it;
1192 :
1193 0 : for ( it = fMessages.begin(); it != fMessages.end(); ++it )
1194 : {
1195 0 : cout << Form("%s : message %s appeared %5d times",prefix,it->first.c_str(),it->second) << endl;
1196 : }
1197 0 : }
1198 :
1199 :
1200 : //_____________________________________________________________________________
1201 : UInt_t
1202 : AliMergeableCollection::EstimateSize(Bool_t show) const
1203 : {
1204 : /// Estimate the memory (in kilobytes) used by some objects
1205 :
1206 : // For TH1:
1207 : // sizeof(TH1) + (nbins+2)*(nbytes_per_bin) +name+title_sizes
1208 : // if you have errors add (nbins+2)*8
1209 :
1210 0 : TIter next(CreateIterator());
1211 :
1212 : TObject* obj;
1213 : UInt_t size(0);
1214 :
1215 0 : while ( ( obj = next() ) )
1216 : {
1217 : UInt_t thissize=0;
1218 0 : if ( obj->IsA()->InheritsFrom(TH1::Class()) || obj->IsA()->InheritsFrom(TProfile::Class()) )
1219 : {
1220 0 : TH1* histo = static_cast<TH1*> (obj);
1221 0 : Int_t nbins = (histo->GetNbinsX()+2);
1222 :
1223 0 : if (histo->GetNbinsY()>1)
1224 : {
1225 0 : nbins *= (histo->GetNbinsY()+2);
1226 0 : }
1227 :
1228 0 : if (histo->GetNbinsZ()>1)
1229 : {
1230 0 : nbins *= (histo->GetNbinsZ()+2);
1231 0 : }
1232 :
1233 0 : Bool_t hasErrors = ( histo->GetSumw2N() > 0 );
1234 :
1235 0 : TString cname(histo->ClassName());
1236 :
1237 : Int_t nbytesPerBin(0);
1238 :
1239 0 : if (cname.Contains(TRegexp("C$")) ) nbytesPerBin = sizeof(Char_t);
1240 0 : if (cname.Contains(TRegexp("S$")) ) nbytesPerBin = sizeof(Short_t);
1241 0 : if (cname.Contains(TRegexp("I$")) ) nbytesPerBin = sizeof(Int_t);
1242 0 : if (cname.Contains(TRegexp("F$")) ) nbytesPerBin = sizeof(Float_t);
1243 0 : if (cname.Contains(TRegexp("D$")) ) nbytesPerBin = sizeof(Double_t);
1244 0 : if (cname=="TProfile") nbytesPerBin = sizeof(Double_t);
1245 :
1246 0 : if (!nbytesPerBin)
1247 : {
1248 0 : AliError(Form("Could not get the number of bytes per bin for histo %s of class %s. Thus the size estimate will be wrong !",
1249 : histo->GetName(),histo->ClassName()));
1250 0 : continue;
1251 : }
1252 :
1253 0 : thissize = sizeof(histo) + nbins*(nbytesPerBin) + strlen(histo->GetName())
1254 0 : + strlen(histo->GetTitle());
1255 :
1256 0 : if ( hasErrors) thissize += nbins*8;
1257 :
1258 0 : if ( obj->IsA()->InheritsFrom(TProfile::Class()) )
1259 : {
1260 0 : TProfile* prof = static_cast<TProfile*>(obj);
1261 0 : TArrayD* d = prof->GetBinSumw2();
1262 0 : thissize += d->GetSize()*8*2; // 2 TArrayD
1263 0 : thissize += sizeof(prof) - sizeof(histo);
1264 0 : }
1265 0 : }
1266 0 : else if ( obj->IsA()->InheritsFrom(THnSparse::Class()) ) {
1267 0 : THnSparse* sparse = static_cast<THnSparse*> (obj);
1268 0 : thissize = sizeof(Float_t) * (UInt_t)sparse->GetNbins();
1269 : }
1270 : // else if ( obj->IsA() == AliCFGridSparse::Class() ) {
1271 : // AliCFGridSparse* sparse = static_cast<AliCFGridSparse*> (obj);
1272 : // thissize = sizeof(Float_t) * (UInt_t)sparse->GetNFilledBins();
1273 : // }
1274 : // else if ( obj->IsA() == AliCFContainer::Class() ) {
1275 : // AliCFContainer* cont = static_cast<AliCFContainer*> (obj);
1276 : // for ( Int_t istep=0; istep<cont->GetNStep(); istep++ ) {
1277 : // thissize += sizeof(Float_t) * (UInt_t)cont->GetGrid(istep)->GetNFilledBins();
1278 : // }
1279 : // }
1280 : else {
1281 0 : AliWarning(Form("Cannot estimate size of %s\n", obj->ClassName()));
1282 0 : continue;
1283 : }
1284 :
1285 0 : size += thissize;
1286 :
1287 0 : if ( show )
1288 : {
1289 0 : AliInfo(Form("Size of %30s is %20d bytes",obj->GetName(),thissize));
1290 : }
1291 0 : } // loop on objects
1292 :
1293 : return size;
1294 0 : }
1295 :
1296 : //_____________________________________________________________________________
1297 : Int_t AliMergeableCollection::Prune(const char* identifier)
1298 : {
1299 : // Delete all objects which match the beginning of the identifier
1300 : // returns the number of entries removed from the Map()
1301 : // (not to be confused with the number of leaf objects removed)
1302 : //
1303 :
1304 0 : TIter next(Map());
1305 : TObjString* key;
1306 : Int_t ndeleted(0);
1307 :
1308 0 : while ( ( key = static_cast<TObjString*>(next())) )
1309 : {
1310 0 : if (key->String().BeginsWith(identifier))
1311 : {
1312 0 : Bool_t ok = Map()->DeleteEntry(key);
1313 0 : if (ok) ++ndeleted;
1314 0 : }
1315 : }
1316 :
1317 : return ndeleted;
1318 0 : }
1319 :
1320 : //_____________________________________________________________________________
1321 : void AliMergeableCollection::PruneEmptyObjects()
1322 : {
1323 : /// Delete the empty objects
1324 : /// (Implemented for TH1 only)
1325 0 : TIter next(Map());
1326 : TObjString* key;
1327 :
1328 0 : TList toBeRemoved;
1329 0 : toBeRemoved.SetOwner(kTRUE);
1330 :
1331 0 : while ( ( key = static_cast<TObjString*>(next()) ) )
1332 : {
1333 0 : TString identifier(key->String());
1334 0 : THashList* hlist = static_cast<THashList*>(Map()->GetValue(identifier.Data()));
1335 0 : TIter nextObject(hlist);
1336 : TObject* obj;
1337 0 : while ( ( obj = nextObject() ) )
1338 : {
1339 0 : if ( IsEmptyObject(obj) ) toBeRemoved.Add(new TObjString(Form("%s%s",identifier.Data(),obj->GetName())));
1340 : }
1341 0 : }
1342 :
1343 0 : TIter nextTBR(&toBeRemoved);
1344 0 : while ( ( key = static_cast<TObjString*>(nextTBR()) ) )
1345 : {
1346 0 : Remove(key->GetString().Data());
1347 0 : AliDebug(2,Form("Removing %s", key->GetString().Data()));
1348 : }
1349 0 : }
1350 :
1351 : //_____________________________________________________________________________
1352 : AliMergeableCollection*
1353 : AliMergeableCollection::Project(const char* identifier) const
1354 : {
1355 : /// To be implemented : would create a new collection starting at /key1/key2/...
1356 :
1357 0 : if (!fMap) return 0x0;
1358 :
1359 0 : AliMergeableCollection* mergCol = new AliMergeableCollection(Form("%s %s",GetName(),identifier),
1360 0 : GetTitle());
1361 :
1362 0 : TIter next(Map());
1363 : TObjString* str;
1364 :
1365 0 : while ( ( str = static_cast<TObjString*>(next()) ) )
1366 : {
1367 0 : TString currIdentifier = str->String();
1368 0 : if ( ! currIdentifier.Contains(identifier) ) continue;
1369 :
1370 0 : THashList* list = static_cast<THashList*>(Map()->GetValue(identifier));
1371 :
1372 0 : TIter nextObj(list);
1373 : TObject* obj;
1374 :
1375 0 : while ( ( obj = nextObj()) )
1376 : {
1377 0 : TObject* clone = obj->Clone();
1378 :
1379 0 : TString newkey(currIdentifier.Data());
1380 0 : newkey.ReplaceAll(identifier,"");
1381 :
1382 0 : if (newkey=="/") newkey="";
1383 :
1384 0 : mergCol->InternalAdopt(newkey.Data(),clone);
1385 0 : }
1386 0 : }
1387 :
1388 : return mergCol;
1389 0 : }
1390 :
1391 : //_____________________________________________________________________________
1392 : TObject*
1393 : AliMergeableCollection::Remove(const char* fullIdentifier)
1394 : {
1395 : ///
1396 : /// Remove a given object (given its fullIdentifier=/key1/key2/.../objectName)
1397 : ///
1398 : /// Note that we do *not* remove the /key1/key2/... entry even if there's no
1399 : /// more object for this triplet.
1400 : ///
1401 : /// Not very efficient. Could be improved ?
1402 : ///
1403 :
1404 0 : TString identifier = GetIdentifier(fullIdentifier);
1405 :
1406 0 : THashList* hlist = dynamic_cast<THashList*>(Map()->GetValue(identifier.Data()));
1407 :
1408 0 : if (!hlist)
1409 : {
1410 0 : AliWarning(Form("Could not get hlist for key=%s",identifier.Data()));
1411 0 : return 0x0;
1412 : }
1413 :
1414 0 : TObject* obj = GetObject(fullIdentifier);
1415 0 : if (!obj)
1416 : {
1417 0 : AliError(Form("Could not find object %s",fullIdentifier));
1418 0 : return 0x0;
1419 : }
1420 :
1421 0 : TObject* rmObj = hlist->Remove(obj);
1422 0 : if (!rmObj)
1423 : {
1424 0 : AliError("Remove failed");
1425 0 : return 0x0;
1426 : }
1427 :
1428 0 : return rmObj;
1429 0 : }
1430 :
1431 : //_____________________________________________________________________________
1432 : Int_t AliMergeableCollection::RemoveByType(const char* typeName)
1433 : {
1434 : /// Remove all the objects in this collection that are of a given type
1435 0 : TIter nextIdentifier(Map());
1436 : TObjString* identifier;
1437 : Int_t nremoved(0);
1438 :
1439 0 : while ( (identifier = static_cast<TObjString*>(nextIdentifier()) ) )
1440 : {
1441 0 : THashList* list = static_cast<THashList*>(Map()->GetValue(identifier->String()));
1442 0 : TIter next(list);
1443 : TObject* o;
1444 :
1445 0 : while ( ( o = next() ) )
1446 : {
1447 0 : if ( strcmp(o->ClassName(),typeName) == 0 )
1448 : {
1449 0 : list->Remove(o);
1450 0 : ++nremoved;
1451 0 : }
1452 : }
1453 0 : }
1454 : return nremoved;
1455 0 : }
1456 :
1457 :
1458 : //_____________________________________________________________________________
1459 : TObjArray*
1460 : AliMergeableCollection::SortAllIdentifiers() const
1461 : {
1462 : /// Sort our internal identifiers. Returned array must be deleted.
1463 0 : TObjArray* identifiers = new TObjArray;
1464 0 : identifiers->SetOwner(kFALSE);
1465 0 : TIter next(Map());
1466 : TObjString* sid;
1467 :
1468 0 : while ( ( sid = static_cast<TObjString*>(next()) ) )
1469 : {
1470 0 : if ( !identifiers->FindObject(sid->String().Data()) )
1471 : {
1472 0 : identifiers->Add(sid);
1473 : }
1474 : }
1475 0 : identifiers->Sort();
1476 : return identifiers;
1477 0 : }
1478 :
1479 :
1480 : ///////////////////////////////////////////////////////////////////////////////
1481 : //
1482 : // AliMergeableCollectionIterator
1483 : //
1484 : ///////////////////////////////////////////////////////////////////////////////
1485 :
1486 : class AliMergeableCollectionIterator;
1487 :
1488 : //_____________________________________________________________________________
1489 0 : AliMergeableCollectionIterator::AliMergeableCollectionIterator(const AliMergeableCollection* mcol, Bool_t dir)
1490 0 : : fkMergeableCollection(mcol), fMapIterator(0x0), fHashListIterator(0x0), fDirection(dir)
1491 0 : {
1492 : /// Default ctor
1493 0 : }
1494 :
1495 : //_____________________________________________________________________________
1496 : AliMergeableCollectionIterator&
1497 : AliMergeableCollectionIterator::operator=(const TIterator&)
1498 : {
1499 : /// Overriden operator= (imposed by Root's declaration of TIterator ?)
1500 0 : Fatal("TIterator::operator=","Not implementeable"); // because there's no clone in TIterator :-(
1501 0 : return *this;
1502 : }
1503 :
1504 : //_____________________________________________________________________________
1505 : AliMergeableCollectionIterator::~AliMergeableCollectionIterator()
1506 0 : {
1507 : /// dtor
1508 0 : Reset();
1509 0 : }
1510 :
1511 : //_____________________________________________________________________________
1512 : TObject* AliMergeableCollectionIterator::Next()
1513 : {
1514 : /// Advance to next object in the collection
1515 :
1516 0 : if (!fHashListIterator)
1517 : {
1518 0 : if ( !fMapIterator )
1519 : {
1520 0 : fMapIterator = fkMergeableCollection->fMap->MakeIterator(fDirection);
1521 0 : }
1522 0 : TObjString* key = static_cast<TObjString*>(fMapIterator->Next());
1523 0 : if (!key)
1524 : {
1525 : // we are done
1526 0 : return 0x0;
1527 : }
1528 0 : THashList* list = static_cast<THashList*>(fkMergeableCollection->Map()->GetValue(key->String().Data()));
1529 0 : if (!list) return 0x0;
1530 0 : fHashListIterator = list->MakeIterator(fDirection);
1531 0 : }
1532 :
1533 0 : TObject* obj = fHashListIterator->Next();
1534 :
1535 0 : if (!obj)
1536 : {
1537 0 : delete fHashListIterator;
1538 0 : fHashListIterator = 0x0;
1539 0 : return Next();
1540 : }
1541 :
1542 0 : return obj;
1543 0 : }
1544 :
1545 : //_____________________________________________________________________________
1546 : void AliMergeableCollectionIterator::Reset()
1547 : {
1548 : /// Reset the iterator
1549 0 : delete fHashListIterator;
1550 0 : delete fMapIterator;
1551 0 : }
1552 :
1553 :
1554 : ///////////////////////////////////////////////////////////////////////////////
1555 : //
1556 : // AliMergeableCollectionProxy
1557 : //
1558 : ///////////////////////////////////////////////////////////////////////////////
1559 :
1560 : class AliMergeableCollectionProxy;
1561 :
1562 : //_____________________________________________________________________________
1563 0 : AliMergeableCollectionProxy::AliMergeableCollectionProxy(AliMergeableCollection& oc,
1564 : THashList& list)
1565 0 : : fOC(oc), fList(list)
1566 0 : {
1567 0 : fName = fList.GetName();
1568 0 : }
1569 :
1570 : //_____________________________________________________________________________
1571 : Bool_t AliMergeableCollectionProxy::Adopt(TObject* obj)
1572 : {
1573 0 : return fOC.Adopt(fList.GetName(),obj);
1574 : }
1575 :
1576 : //_____________________________________________________________________________
1577 : Bool_t
1578 : AliMergeableCollectionProxy::Adopt(const char* identifier, TObject* obj)
1579 : {
1580 : /// Adopt a given object, and associate it with pair key
1581 :
1582 0 : TString path;
1583 0 : path.Form("%s%s",fList.GetName(),identifier);
1584 0 : return fOC.Adopt(path,obj);
1585 0 : }
1586 :
1587 : //_____________________________________________________________________________
1588 : TObject* AliMergeableCollectionProxy::GetObject(const char* objectName) const
1589 : {
1590 0 : return fList.FindObject(objectName);
1591 : }
1592 :
1593 : //_____________________________________________________________________________
1594 : TH1* AliMergeableCollectionProxy::Histo(const char* objectName) const
1595 : {
1596 0 : if ( strchr(objectName,':') )
1597 : {
1598 0 : TString action;
1599 :
1600 0 : TObjArray* arr = TString(objectName).Tokenize(":");
1601 :
1602 0 : if ( arr->GetLast() > 0 )
1603 : {
1604 0 : action = static_cast<TObjString*>(arr->At(1))->String();
1605 0 : action.ToUpper();
1606 : }
1607 :
1608 0 : TString oname = static_cast<TObjString*>(arr->At(0))->String();
1609 :
1610 0 : delete arr;
1611 :
1612 0 : TObject* o = GetObject(oname);
1613 :
1614 0 : return fOC.HistoWithAction("",o,action);
1615 0 : }
1616 :
1617 0 : TObject* o = GetObject(objectName);
1618 :
1619 0 : if (o && o->IsA()->InheritsFrom(TH1::Class()))
1620 : {
1621 0 : return static_cast<TH1*>(o);
1622 : }
1623 :
1624 0 : return 0x0;
1625 0 : }
1626 :
1627 : //_____________________________________________________________________________
1628 : TH2* AliMergeableCollectionProxy::H2(const char* objectName) const
1629 : {
1630 0 : TObject* o = GetObject(objectName);
1631 :
1632 0 : if (o->IsA()->InheritsFrom(TH2::Class()))
1633 : {
1634 0 : return static_cast<TH2*>(o);
1635 : }
1636 0 : return 0x0;
1637 0 : }
1638 :
1639 : //_____________________________________________________________________________
1640 : TProfile* AliMergeableCollectionProxy::Prof(const char* objectName) const
1641 : {
1642 0 : TObject* o = GetObject(objectName);
1643 :
1644 0 : if (o->IsA()->InheritsFrom(TProfile::Class()))
1645 : {
1646 0 : return static_cast<TProfile*>(o);
1647 : }
1648 0 : return 0x0;
1649 0 : }
1650 :
1651 : //_____________________________________________________________________________
1652 : void AliMergeableCollectionProxy::Print(Option_t* opt) const
1653 : {
1654 0 : fList.Print(opt);
1655 0 : }
1656 :
1657 : //_____________________________________________________________________________
1658 : TIterator* AliMergeableCollectionProxy::CreateIterator(Bool_t dir) const
1659 : {
1660 0 : return fList.MakeIterator(dir);
1661 : }
|