Fix Coverity 24835
[u/mrichter/AliRoot.git] / PWG / muondep / AliAnalysisMuMuResult.cxx
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 ///
17 /// Base class to hold a set of results for the same quantity,
18 /// computed using various methods, each with their errors
19 ///
20 /// author: Laurent Aphecetche (Subatech)
21 ///
22
23 #include "AliAnalysisMuMuResult.h"
24
25 ClassImp(AliAnalysisMuMuResult)
26
27 #include "THashList.h"
28 #include "TLine.h"
29 #include "TList.h"
30 #include "TMap.h"
31 #include "TMath.h"
32 #include "TObjArray.h"
33 #include "TParameter.h"
34 #include "AliLog.h"
35 #include "TPRegexp.h"
36 #include <map>
37
38 //_____________________________________________________________________________
39 AliAnalysisMuMuResult::AliAnalysisMuMuResult(const char* name, const char* title, AliAnalysisMuMuResult::EResultMergingMethod mergingMethod) :
40 TNamed(name,title),
41 fSubResults(0x0),
42 fMap(0x0),
43 fMother(0x0),
44 fKeys(0x0),
45 fWeight(0.0),
46 fAlias(),
47 fSubResultsToBeIncluded(0x0),
48 fResultMergingMethod(mergingMethod),
49 fIsValid(kTRUE),
50 fVisibleKeys(0x0)
51 {
52   /// default ctor
53 }
54
55 //_____________________________________________________________________________
56 AliAnalysisMuMuResult::AliAnalysisMuMuResult(const AliAnalysisMuMuResult& rhs)
57 :
58 TNamed(rhs),
59 fSubResults(0x0),
60 fMap(0x0),
61 fMother(0x0),
62 fKeys(0x0),
63 fWeight(rhs.fWeight),
64 fAlias(),
65 fSubResultsToBeIncluded(0x0),
66 fIsValid(kTRUE),
67 fVisibleKeys(0x0)
68 {
69   /// copy ctor
70   /// Note that the mother is lost
71   /// fKeys remains 0x0 so it will be recomputed if need be
72
73   if (rhs.fSubResults)
74   {
75     fSubResults = static_cast<TObjArray*>(rhs.fSubResults->Clone());
76   }
77   
78   if ( rhs.fMap )
79   {
80     fMap = static_cast<TMap*>(rhs.fMap->Clone());
81   }
82   
83   if ( rhs.fAlias.Length() > 0 )
84   {
85     fAlias = rhs.fAlias;
86   }
87   
88   if ( rhs.fSubResultsToBeIncluded )
89   {
90     fSubResultsToBeIncluded = static_cast<TList*>(rhs.fSubResultsToBeIncluded->Clone());
91   }
92
93   if ( rhs.fVisibleKeys )
94   {
95     fVisibleKeys = static_cast<THashList*>(rhs.Clone());
96   }
97 }
98
99 //_____________________________________________________________________________
100 AliAnalysisMuMuResult& AliAnalysisMuMuResult::operator=(const AliAnalysisMuMuResult& rhs)
101 {
102   /// Assignment operator
103   
104   if (this!=&rhs)
105   {
106     delete fMap;
107     delete fSubResults;
108     delete fSubResultsToBeIncluded;
109     
110     fMap = 0x0;
111     fSubResults = 0x0;
112     fKeys = 0x0;
113     fSubResultsToBeIncluded = 0x0;
114     
115     if (rhs.fSubResults)
116     {
117       fSubResults = static_cast<TObjArray*>(rhs.fSubResults->Clone());
118     }
119     
120     if ( rhs.fMap )
121     {
122       fMap = static_cast<TMap*>(rhs.fMap->Clone());
123     }
124
125     if ( rhs.fSubResultsToBeIncluded )
126     {
127       fSubResultsToBeIncluded = static_cast<TList*>(rhs.fSubResultsToBeIncluded->Clone());
128     }
129
130     static_cast<TNamed&>(*this)=rhs;
131
132     fWeight = rhs.fWeight;
133     fAlias="";
134     
135     if ( rhs.fAlias.Length() > 0 )
136     {
137       fAlias = rhs.fAlias;
138     }
139     
140     fIsValid = rhs.fIsValid;
141     
142     if ( rhs.fVisibleKeys )
143     {
144       fVisibleKeys = static_cast<THashList*>(rhs.Clone());
145     }
146
147   }
148   
149   return *this;
150 }
151
152 //_____________________________________________________________________________
153 AliAnalysisMuMuResult::~AliAnalysisMuMuResult()
154 {
155   // dtor
156   delete fMap;
157   delete fSubResults;
158   delete fKeys;
159   delete fSubResultsToBeIncluded;
160   delete fVisibleKeys;
161 }
162
163 //_____________________________________________________________________________
164 Bool_t AliAnalysisMuMuResult::AdoptSubResult(AliAnalysisMuMuResult* r)
165 {
166   /// Adopt (i.e. becomes owner) of a subresult
167   if (!fSubResults)
168   {
169     fSubResults = new TObjArray;
170     fSubResults->SetOwner(kTRUE);
171   }
172
173   Int_t subresultsBeforeAdd = fSubResults->GetEntriesFast();
174   
175   fSubResults->Add(r);
176   
177   Int_t subresultsAfterAdd = fSubResults->GetEntriesFast();
178   
179   SubResultsToBeIncluded()->Add(new TObjString(r->Alias()));
180   
181   if ( subresultsBeforeAdd < subresultsAfterAdd ) return kTRUE;
182   else return kFALSE;
183 }
184
185 //_____________________________________________________________________________
186 TObject* AliAnalysisMuMuResult::Clone(const char* /*newname*/) const
187 {
188   /// Clone this result
189   return new AliAnalysisMuMuResult(*this);
190 }
191
192
193 //_____________________________________________________________________________
194 Double_t AliAnalysisMuMuResult::ErrorAB(Double_t a, Double_t aerr, Double_t b, Double_t berr)
195 {
196   /// Compute the quadratic sum of 2 errors
197
198   Double_t e(0.0);
199   
200   if ( TMath::Abs(a) > 1E-12 )
201   {
202     e += (aerr*aerr)/(a*a);
203   }
204   
205   if ( TMath::Abs(b) > 1E-12 )
206   {
207     e += (berr*berr)/(b*b);
208   }
209   
210   return TMath::Sqrt(e);
211 }
212
213 //_____________________________________________________________________________
214 Double_t AliAnalysisMuMuResult::ErrorABC(Double_t a, Double_t aerr, Double_t b, Double_t berr, Double_t c, Double_t cerror)
215 {
216   /// Compute the quadratic sum of 3 errors
217   
218   Double_t e(0.0);
219   
220   if ( TMath::Abs(a) > 1E-12 )
221   {
222     e += (aerr*aerr)/(a*a);
223   }
224   
225   if ( TMath::Abs(b) > 1E-12 )
226   {
227     e += (berr*berr)/(b*b);
228   }
229   
230   if ( TMath::Abs(c) > 1E-12 )
231   {
232     e += (cerror*cerror)/(c*c);
233   }
234   
235   return TMath::Sqrt(e);
236 }
237
238 //_____________________________________________________________________________
239 Double_t AliAnalysisMuMuResult::ErrorABCD(Double_t a, Double_t aerr, Double_t b, Double_t berr, Double_t c, Double_t cerror, Double_t d, Double_t derror)
240 {
241   /// Compute the quadratic sum of 4 errors
242   
243   Double_t e(0.0);
244   
245   if ( TMath::Abs(a) > 1E-12 )
246   {
247     e += (aerr*aerr)/(a*a);
248   }
249   
250   if ( TMath::Abs(b) > 1E-12 )
251   {
252     e += (berr*berr)/(b*b);
253   }
254   
255   if ( TMath::Abs(c) > 1E-12 )
256   {
257     e += (cerror*cerror)/(c*c);
258   }
259
260   if ( TMath::Abs(d) > 1E-12 )
261   {
262     e += (derror*derror)/(d*d);
263   }
264
265   return TMath::Sqrt(e);
266 }
267
268 //_____________________________________________________________________________
269 Double_t AliAnalysisMuMuResult::ErrorABCDE(Double_t a, Double_t aerr, Double_t b, Double_t berr, Double_t c, Double_t cerror, Double_t d, Double_t derror, Double_t ee, Double_t eeerror)
270 {
271   /// Compute the quadratic sum of 4 errors
272   
273   Double_t e(0.0);
274   
275   if ( TMath::Abs(a) > 1E-12 )
276   {
277     e += (aerr*aerr)/(a*a);
278   }
279   
280   if ( TMath::Abs(b) > 1E-12 )
281   {
282     e += (berr*berr)/(b*b);
283   }
284   
285   if ( TMath::Abs(c) > 1E-12 )
286   {
287     e += (cerror*cerror)/(c*c);
288   }
289   
290   if ( TMath::Abs(d) > 1E-12 )
291   {
292     e += (derror*derror)/(d*d);
293   }
294
295   if ( TMath::Abs(e) > 1E-12 )
296   {
297     e += (eeerror*eeerror)/(ee*ee);
298   }
299
300   return TMath::Sqrt(e);
301 }
302
303
304 //_____________________________________________________________________________
305 void AliAnalysisMuMuResult::Exclude(const char* subResultList)
306 {
307   // exclude some subresult names from the list of subresult
308   // to be used when computing the mean 
309   
310   TString slist(subResultList);
311   
312   TString tobeincluded = GetSubResultNameList();
313   
314   if ( slist == "*" )
315   {
316     Exclude(tobeincluded);
317     return;
318   }
319   
320   if ( fSubResultsToBeIncluded )
321   {
322     TObjArray* a = slist.Tokenize(",");
323     TIter nextA(a);
324     TObjString* s;
325
326     while ( ( s = static_cast<TObjString*>(nextA())) )
327     {
328       TObject* o = fSubResultsToBeIncluded->FindObject(s->String());
329       fSubResultsToBeIncluded->Remove(o);
330     }
331     
332     delete a;
333   }
334 }
335
336 //_____________________________________________________________________________
337 Double_t AliAnalysisMuMuResult::GetErrorStat(const char* name, const char* subResultName) const
338 {
339   // compute the mean value from all subresults that are included
340   
341   if ( strlen(subResultName) > 0 )
342   {
343     if ( !fSubResults)
344     {
345       AliError(Form("No subresult from which I could get the %s one...",subResultName));
346       return TMath::Limits<Double_t>::Max();
347     }
348     AliAnalysisMuMuResult* sub = static_cast<AliAnalysisMuMuResult*>(fSubResults->FindObject(subResultName));
349     if (!sub)
350     {
351       AliError(Form("Could not get subresult named %s",subResultName));
352       return TMath::Limits<Double_t>::Max();
353     }
354     return sub->GetErrorStat(name);
355   }
356   
357   if ( fMap )
358   {
359     TObjArray* p = static_cast<TObjArray*>(fMap->GetValue(name));
360     if (p)
361     {
362       TParameter<double>* val = static_cast<TParameter<double>*>(p->At(kErrorStat));
363       return val->GetVal();
364     }
365   }
366   
367   TIter next(fSubResults);
368   AliAnalysisMuMuResult* r;
369   
370   if ( fResultMergingMethod == kMean )
371   {
372     
373     Int_t n(0);
374 //    Double_t v1(0);
375 //    Double_t v2(0);
376 //    Double_t d(0);
377     
378 //    Double_t mean = GetValue(name);
379     Double_t wval = 0, wval2 = 0, w2err2 = 0, sumw = 0;
380     while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
381     {
382       if ( IsIncluded(r->Alias()) && r->HasValue(name) )
383       {
384         Double_t val = r->GetValue(name);
385         Double_t err = r->GetErrorStat(name);
386         // weight
387         Double_t wstat = 1./val;
388         Double_t w = 1./err/err/wstat;
389         sumw += w;
390         
391         // mean
392         wval += w*val;
393         
394         // stat
395         w2err2 += w*w*err*err;
396         
397         // rms
398         wval2 += w*val*val;
399         
400 //        Double_t error = r->GetErrorStat(name);
401 //
402 //        Double_t e2 = error*error;
403 //        
404 //        if ( !(e2>0.0 ) ) e2 = TMath::Sqrt(r->GetValue(name));
405 //
406 //
407 //        v1 += 1.0/e2;
408 //        v2 += 1.0/(e2*e2);
409 //          
410 //        d += ( (r->GetValue(name) - mean)*(r->GetValue(name)-mean) / e2);
411         ++n;
412       }
413     }
414     
415     if ( n<1 ) return 0.0;
416     
417     if ( n == 1 )
418     {
419       next.Reset();
420       while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
421       {
422         if ( IsIncluded(r->Alias()) && r->HasValue(name) )
423         {
424           return r->GetErrorStat(name);
425         }
426       }
427     }
428     // results
429 //    mean = wval/sumw;
430     return TMath::Sqrt(w2err2*n)/sumw;
431 //    sys = TMath::Sqrt(wval2/sumw - mean*mean);
432     
433 //    Double_t variance= (1.0/v1)*(1.0/(n-1))*d;
434 //    // variance corrected by over/under-estimation of errors
435 //    // i.e. scaled by chisquare per ndf
436     
437 //    return TMath::Sqrt(variance);
438   }
439   else
440   {
441     Double_t sume2(0.0);
442     Double_t sum(0.0);
443     Int_t n(0);
444     
445     while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
446     {
447       if ( IsIncluded(r->Alias()) && r->HasValue(name) )
448       {
449         Double_t e = r->GetErrorStat(name)/r->GetValue(name);
450         sume2 += e*e;
451         sum += r->GetValue(name);
452         ++n;
453       }
454     }
455     if (n)
456     {
457       return sum*TMath::Sqrt(sume2);
458     }
459     else
460     {
461       return TMath::Limits<Double_t>::Max();
462     }
463   }
464 }
465
466 //_____________________________________________________________________________
467 Double_t AliAnalysisMuMuResult::GetRMS(const char* name, const char* subResultName) const
468 {
469   // compute the rms of the subresults
470   // returns zero if no subresults
471
472   if ( strlen(subResultName) > 0 )
473   {
474     if ( !fSubResults)
475     {
476       AliError(Form("No subresult from which I could get the %s one...",subResultName));
477       return TMath::Limits<Double_t>::Max();
478     }
479     AliAnalysisMuMuResult* sub = static_cast<AliAnalysisMuMuResult*>(fSubResults->FindObject(subResultName));
480     if (!sub)
481     {
482       AliError(Form("Could not get subresult named %s",subResultName));
483       return TMath::Limits<Double_t>::Max();
484     }
485     return sub->GetRMS(name);
486   }
487   
488   if ( fMap )
489   {
490     TObjArray* p = static_cast<TObjArray*>(fMap->GetValue(name));
491     if (p)
492     {
493       TParameter<double>* val = static_cast<TParameter<double>*>(p->At(kRMS));
494       return val ? val->GetVal() : 0.0; // val can be null for old results which did not have the rms set
495     }
496   }
497   
498   TIter next(fSubResults);
499   AliAnalysisMuMuResult* r;
500   Double_t v1(0);
501   Double_t v2(0);
502   Double_t sum(0);
503   Int_t n(0);
504   
505   Double_t xmean = GetValue(name);
506   
507   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
508   {
509     if ( IsIncluded(r->Alias()) && r->HasValue(name) )
510     {
511       Double_t e2 = r->GetErrorStat(name);
512       
513       e2 *= e2;
514       
515       if ( !(e2>0.0) ) e2 = TMath::Sqrt(r->GetValue(name));
516       
517       Double_t wi = 1.0/e2;
518       v1 += wi;
519       v2 += wi*wi;
520       Double_t diff = r->GetValue(name) - xmean;
521       sum += wi*diff*diff;
522       ++n;
523     }
524   }
525   
526   if ( n < 1 ) return 0.0;
527   
528   if ( n == 1 )
529   {
530     next.Reset();
531     while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
532     {
533       if ( IsIncluded(r->Alias()) && r->HasValue(name) )
534       {
535         return r->GetRMS(name);
536       }
537     }
538   }
539   
540   Double_t unbiased = TMath::Sqrt( (v1/(v1*v1-v2)) * sum);
541   
542   Double_t biased = TMath::Sqrt( sum/v1 );
543   
544   AliDebug(1,Form("v1 %e v1*v1 %e v2 %e -> biased %e unbiased %e (ratio %e)",v1,v1*v1,v2,biased,unbiased,unbiased/biased));
545   
546   return unbiased;
547 }
548
549 //_____________________________________________________________________________
550 TString AliAnalysisMuMuResult::GetSubResultNameList() const
551 {
552   // get a comma separated list of our subresult aliases
553   TString tobeincluded;
554   TIter next(fSubResults);
555   AliAnalysisMuMuResult* r;
556   
557   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next())) )
558   {
559     if (tobeincluded.Length()>0) tobeincluded+=",";
560     tobeincluded += r->Alias();
561   }
562   return tobeincluded;
563 }
564
565 //_____________________________________________________________________________
566 Double_t AliAnalysisMuMuResult::GetValue(const char* name, const char* subResultName) const
567 {
568   // get a value (either directly or by computing the mean of the subresults)
569   
570   if ( strlen(subResultName) > 0 )
571   {
572     if ( !fSubResults)
573     {
574       AliError(Form("No subresult from which I could get the %s one...",subResultName));
575       return TMath::Limits<Double_t>::Max();
576     }
577     AliAnalysisMuMuResult* sub = static_cast<AliAnalysisMuMuResult*>(fSubResults->FindObject(subResultName));
578     if (!sub)
579     {
580       AliError(Form("Could not get subresult named %s",subResultName));
581       return TMath::Limits<Double_t>::Max();
582     }
583     return sub->GetValue(name);
584   }
585   
586   if (fMap)
587   {
588     TObjArray* p = static_cast<TObjArray*>(fMap->GetValue(name));
589     if (p)
590     {
591       TParameter<double>* val = static_cast<TParameter<double>*>(p->At(kValue));
592       return val->GetVal();
593     }
594   }
595   
596   // merge the value from all subresults
597   TIter next(fSubResults);
598   AliAnalysisMuMuResult* r;
599   
600   if ( fResultMergingMethod == kMean )
601   {
602     Double_t mean(0);
603     Double_t errorSum(0.0);
604
605     while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
606     {
607       if ( IsIncluded(r->Alias()) && r->HasValue(name) )
608       {
609         Double_t e = r->GetErrorStat(name)/TMath::Sqrt(r->GetValue(name)); //The Sqrt(r->GetValue(name)) was not here before
610         Double_t e2 = e*e;
611         if ( !(e2>0.0 ) ) e2 = TMath::Sqrt(r->GetValue(name));
612
613         mean += r->GetValue(name)/e2;
614         errorSum += 1.0/e2;
615       }
616     }
617     if ( errorSum != 0.0 )
618     {
619       return mean/errorSum;
620     }
621     else
622     {
623       return TMath::Limits<Double_t>::Max();
624     }
625   }
626   else
627   {
628     Double_t sum(0.0);
629     
630     while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
631     {
632       if ( IsIncluded(r->Alias()) && r->HasValue(name) )
633       {
634         sum += r->GetValue(name);
635       }
636     }
637     
638     return sum;
639   }
640 }
641
642 //_____________________________________________________________________________
643 Int_t AliAnalysisMuMuResult::HasValue(const char* name, const char* subResultName) const
644 {
645   /// Whether this result (or subresult if subResultName is provided) has a property
646   /// named "name"
647   ///
648   /// When having subresults, return the number of subresults that have this value
649   ///
650   
651   if ( strlen(subResultName) > 0 )
652   {
653     if ( !fSubResults)
654     {
655       AliError(Form("No subresult from which I could get the %s one...",subResultName));
656       return 0;
657     }
658     AliAnalysisMuMuResult* sub = static_cast<AliAnalysisMuMuResult*>(fSubResults->FindObject(subResultName));
659     if (!sub)
660     {
661       AliError(Form("Could not get subresult named %s",subResultName));
662       return 0;
663     }
664     return sub->HasValue(name);
665   }
666
667   if ( fMap && ( fMap->GetValue(name) != 0x0 ) )
668   {
669     return 1;
670   }
671   
672   TIter next(fSubResults);
673   AliAnalysisMuMuResult* r;
674   Int_t n(0);
675   
676   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
677   {
678     if ( r->HasValue(name) ) ++n;
679   }
680   
681   return n;
682 }
683
684 //_____________________________________________________________________________
685 void AliAnalysisMuMuResult::Hide(const char* keyPattern)
686 {
687   /// Specify which keys will be hidden in the Print method...
688   
689   if (!fVisibleKeys)
690   {
691     fVisibleKeys = new THashList;
692     fVisibleKeys->SetOwner(kTRUE);
693   }
694   fVisibleKeys->Clear();
695   
696   TIter next(fSubResults);
697   AliAnalysisMuMuResult* r;
698   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next())) )
699   {
700     r->Hide(keyPattern);
701   }
702   
703   TIter nextKey(Keys());
704   TObjString* str;
705   
706   TPRegexp re(keyPattern);
707   
708   while ( ( str = static_cast<TObjString*>(nextKey()) ) )
709   {
710     if ( !re.MatchB(str->String()) )
711     {
712       fVisibleKeys->Add(new TObjString(*str));
713     }
714   }
715   
716 }
717 //_____________________________________________________________________________
718 void AliAnalysisMuMuResult::Include(const char* subResultList)
719 {
720   // (re)include some subresult names
721   
722   TString slist(subResultList);
723
724   if ( slist.Length()==0 )
725   {
726     Exclude("*");
727     return;
728   }
729   
730   if ( slist == "*" )
731   {
732     slist = GetSubResultNameList();
733   }
734
735   TObjArray* a = slist.Tokenize(",");
736   a->SetOwner(kFALSE);
737   TIter next(a);
738   TObjString* s;
739   
740   while ( ( s = static_cast<TObjString*>(next()) ) )
741   {
742     if (!fSubResultsToBeIncluded )
743     {
744       fSubResultsToBeIncluded = new TList;
745       fSubResultsToBeIncluded->SetOwner(kTRUE);
746     }
747     if (!IsIncluded(s->String()))
748     {
749       fSubResultsToBeIncluded->Add(s);      
750     }
751   }
752   
753   delete a;
754 }
755
756 //_____________________________________________________________________________
757 Bool_t AliAnalysisMuMuResult::IsIncluded(const TString& alias) const
758 {
759   // whether that subresult alias should be included when computing means, etc...
760   
761   if (!fSubResultsToBeIncluded) return kTRUE;
762   
763   return ( fSubResultsToBeIncluded->FindObject(alias) != 0x0 );
764 }
765
766 //_____________________________________________________________________________
767 Bool_t AliAnalysisMuMuResult::IsValidValue(Double_t val) const
768 {
769   /// Whether val is a valid one
770   return ( val < TMath::Limits<Double_t>::Max() );
771 }
772
773 //_____________________________________________________________________________
774 THashList* AliAnalysisMuMuResult::Keys() const
775 {
776   /// Return the complete list of keys we're using
777   if (!fKeys)
778   {
779     fKeys = new THashList;
780     fKeys->SetOwner(kTRUE);
781     TIter next(fMap);
782     TObjString* key;
783     
784     while ( ( key = static_cast<TObjString*>(next()) ) )
785     {
786       if ( !fKeys->FindObject(key->String()) )
787       {
788         fKeys->Add(new TObjString(key->String()));
789       }
790     }
791     
792     AliAnalysisMuMuResult* r;
793     TIter nextResult(fSubResults);
794     
795     while ( ( r = static_cast<AliAnalysisMuMuResult*>(nextResult())) )
796     {
797       TIter nextHL(r->Keys());
798       TObjString* s;
799       
800       while ( ( s = static_cast<TObjString*>(nextHL())) )
801       {
802         if ( !fKeys->FindObject(s->String()) )
803         {
804           fKeys->Add(new TObjString(s->String()));
805         }
806       }
807     }
808
809     fKeys->Sort();
810   }
811   return fKeys;
812 }
813
814 //_____________________________________________________________________________
815 Long64_t AliAnalysisMuMuResult::Merge(TCollection* list)
816 {
817   /// Merge method
818   ///
819   /// Merge a list of AliAnalysisMuMuResult objects with this
820   /// Returns the number of merged objects (including this).
821   ///
822   /// Note that the merging is to be understood here as a weighed mean operation
823   
824   if (!list) return 0;
825   
826   if (list->IsEmpty()) return 1;
827   
828   TIter next(list);
829   TObject* currObj;
830
831   Double_t sumw(Weight()); // sum of weights
832   
833   while ( ( currObj = next() ) )
834   {
835     AliAnalysisMuMuResult* result = dynamic_cast<AliAnalysisMuMuResult*>(currObj);
836     if (!result)
837     {
838       AliFatal(Form("object named \"%s\" is a %s instead of an AliAnalysisMuMuResult!", currObj->GetName(), currObj->ClassName()));
839       continue;
840     }
841     
842     sumw += result->Weight();
843   }
844   
845   TIter nextKey(Keys());
846   TObjString* key;
847   
848   while ( ( key = static_cast<TObjString*>(nextKey())) )
849   {
850     Double_t value = GetValue(key->String())*Weight()/sumw;
851     Double_t e = GetErrorStat(key->String());
852     Double_t e2 = e*e*Weight()*Weight()/sumw/sumw;
853
854     next.Reset();
855     
856     while ( ( currObj = next() ) )
857     {
858       AliAnalysisMuMuResult* result = dynamic_cast<AliAnalysisMuMuResult*>(currObj);
859     
860       if (!result)
861       { 
862         continue;
863       }
864       
865       if (!result->HasValue(key->String()))
866       {
867         AliError(Form("Did not find key %s in of the result to merge",key->String().Data()));
868         continue;
869       }
870       
871       // can only merge under the condition we have the same bin
872     
873       Double_t w = result->Weight()/sumw;
874       
875       Double_t w2 = w*w;
876       
877       value += result->GetValue(key->String())*w;
878       e2 += result->GetErrorStat(key->String())*result->GetErrorStat(key->String())*w2;
879       
880     }
881     
882     Set(key->String(),
883         value,
884         TMath::Sqrt(e2));
885   }
886   
887   TIter nextSubresult(fSubResults);
888   AliAnalysisMuMuResult* r;
889   
890   while ( ( r = static_cast<AliAnalysisMuMuResult*>(nextSubresult())) )
891   {
892     TList sublist;
893
894     next.Reset();
895     
896     while ( ( currObj = next() ) )
897     {
898       sublist.Add(currObj);
899     }
900
901     r->Merge(&sublist);
902   }
903   
904   fWeight = sumw;
905   
906   return list->GetEntries()+1;
907 }
908
909 //_____________________________________________________________________________
910 Int_t AliAnalysisMuMuResult::NofIncludedSubResults(const char* name) const
911 {
912   // Return the number of subresults which have key name and are included
913   
914   TIter next(fSubResults);
915   AliAnalysisMuMuResult* r;
916   Int_t n(0);
917   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
918   {
919     if ( IsIncluded(r->Alias()) && r->HasValue(name) )
920     {
921       ++n;
922     }
923   }
924   return n;
925 }
926
927 //_____________________________________________________________________________
928 void AliAnalysisMuMuResult::Print(Option_t* opt) const
929 {
930   /// printout
931   
932   TString sopt(opt);
933   sopt.ToUpper();
934   
935   for ( Int_t i = 0; i < 9; ++i )
936   {
937     sopt.ReplaceAll(Form("%d",i),"");
938   }
939   
940   TString pot(sopt);
941   pot.ReplaceAll("ALL","");
942   pot.ReplaceAll("FULL","");
943
944   std::cout << pot.Data() << " ";
945   
946     if ( fAlias.Length() > 0 )
947     {
948       std::cout << Form("%s - ",fAlias.Data());
949     }
950   
951     std::cout << Form("%s %s %s",
952                       GetName(),GetTitle(),fWeight > 0.0 ? Form(" WEIGHT %e",fWeight) : "");
953   
954   if ( fSubResults && fSubResults->GetEntries()>1 )
955   {
956     std::cout << " (" << fSubResults->GetEntries() << " subresults)";
957   }
958
959   std::cout << std::endl;
960   
961   TIter next(Keys());
962   TObjString* key;
963   
964   Int_t nsub = fSubResults ? fSubResults->GetEntries() : 0;
965   
966   while ( ( key = static_cast<TObjString*>(next())) )
967   {
968     if ( fVisibleKeys  && ! fVisibleKeys->FindObject(key->String()) ) continue;
969         
970     if ( nsub==0 || nsub == HasValue(key->String().Data()) )
971     {
972       PrintValue(key->String().Data(),pot.Data(),
973                  GetValue(key->String()),
974                  GetErrorStat(key->String()),
975                  GetRMS(key->String()));
976     }
977   }
978
979   if ( fSubResults /* && fSubResults->GetEntries() > 1 */ && ( sopt.Contains("ALL") || sopt.Contains("FULL") ) )
980   {
981     std::cout << pot.Data() << "\t===== sub results ===== " << std::endl;
982     
983     sopt += "\t\t";
984     
985     TIter nextSubresult(fSubResults);
986     AliAnalysisMuMuResult* r;
987     
988     while ( ( r = static_cast<AliAnalysisMuMuResult*>(nextSubresult()) ) )
989     {
990       if ( !IsIncluded(r->Alias()) )
991       {
992         std::cout << " [EXCLUDED]";
993       }
994       r->Print(sopt.Data());
995     }
996   }
997 }
998
999 //_____________________________________________________________________________
1000 void AliAnalysisMuMuResult::PrintValue(const char* key, const char* opt,
1001                                        Double_t value, Double_t errorStat, Double_t rms) const
1002 {
1003   // print one value and its associated error
1004   
1005   if ( TString(key).Contains("AccEff") )
1006   {
1007     std::cout << opt << Form("\t\t%20s %9.2f +- %5.2f %% (%5.2f %%)",key,value*100,errorStat*100,
1008                              value != 0.0 ? errorStat*100.0/value : 0.0 );
1009     
1010     if ( rms )
1011     {
1012       std::cout << Form(" RMS %9.2f (%5.2f %%)",rms,100.0*rms/value);
1013     }
1014
1015     std::cout << std::endl;
1016   }
1017   else if ( TString(key).BeginsWith("Sigma") ||  TString(key).BeginsWith("Mean") )
1018   {
1019     std::cout << opt << Form("\t\t%20s %9.2f +- %5.2f (%5.2f %%) MeV/c^2",key,value*1E3,1E3*errorStat,
1020                              value != 0.0 ? errorStat*100.0/value : 0.0);
1021     
1022     if ( rms )
1023     {
1024       std::cout << Form(" RMS %9.2f (%5.2f %%)",rms,100.0*rms/value);
1025     }
1026
1027     std::cout << std::endl;
1028   }
1029   else if ( TString(key).Contains("Nof") || ( TString(key).Contains("Fnorm") && !TString(key).Contains("persion") ) )
1030   {
1031     std::cout << opt << Form("\t\t%20s %9.3f +- %5.3f (%5.2f %%)",key,value,errorStat,
1032                              value != 0.0 ? errorStat*100.0/value : 0.0);
1033     
1034     if ( rms )
1035     {
1036       std::cout << Form(" RMS %9.2f (%5.2f %%)",rms,100.0*rms/value);
1037     }
1038     std::cout << std::endl;
1039   }
1040   else if ( value > 1E-3 && value < 1E3 )
1041   {
1042     if (errorStat > 0.0)
1043     {
1044       std::cout << opt << Form("\t\t%20s %9.3f +- %5.3f (%5.3f %%)",key,value,errorStat,
1045                              value != 0.0 ? errorStat*100.0/value : 0.0);
1046       if ( rms )
1047       {
1048         std::cout << Form(" RMS %9.2f (%5.2f %%)",rms,100.0*rms/value);
1049       }
1050     }
1051     else
1052     {
1053       std::cout << opt << Form("\t\t%20s %9.3f",key,value);
1054     }
1055     std::cout << std::endl;
1056   }
1057   else
1058   {
1059     if ( errorStat > 0.0 )
1060     {
1061       
1062       std::cout << opt << Form("\t\t%20s %9.2e +- %9.2e (%5.2f %%)",key,value,errorStat,
1063                                value != 0.0 ? errorStat*100.0/value : 0.0);
1064       if ( rms )
1065       {
1066         std::cout << Form(" RMS %9.2e (%5.2f %%)",rms,100.0*rms/value);
1067       }
1068     }
1069     else
1070     {
1071       std::cout << opt << Form("\t\t%20s %9.2e ",key,value);
1072     }
1073     std::cout << std::endl;
1074   }
1075 }
1076
1077 //_____________________________________________________________________________
1078 void AliAnalysisMuMuResult::Scale(Double_t w)
1079 {
1080   /// Scale all our internal values by value
1081   
1082   TIter next(Keys());
1083   TObjString* key;
1084   
1085   while ( ( key = static_cast<TObjString*>(next())) )
1086   {
1087     Double_t value = GetValue(key->String());
1088     Double_t error = GetErrorStat(key->String());
1089     Double_t rms = GetRMS(key->String());
1090     
1091     Set(key->String(),value*w,error*w,rms*w);
1092   }
1093
1094 }
1095
1096 //_____________________________________________________________________________
1097 void AliAnalysisMuMuResult::Set(const char* name, Double_t value, Double_t errorStat, Double_t rms)
1098 {
1099   /// Set a (value,error) pair with a given name
1100   
1101   if ( !fMap )
1102   {
1103     fMap = new TMap;
1104     fMap->SetOwnerKeyValue(kTRUE,kTRUE);
1105   }
1106   
1107   TObjArray* p = static_cast<TObjArray*>(fMap->GetValue(name));
1108   if (!p)
1109   {
1110     p = new TObjArray(4);
1111     
1112     p->SetOwner(kTRUE);
1113     
1114     p->AddAt(new TParameter<Double_t>(name,value),kValue);
1115     p->AddAt(new TParameter<Double_t>(name,errorStat),kErrorStat);
1116     p->AddAt(new TParameter<Double_t>(name,rms),kRMS);
1117     
1118     fMap->Add(new TObjString(name),p);
1119     
1120     delete fKeys; // invalidate previously computed keys arrays, if any
1121     fKeys=0x0;
1122 //    Show("*"); // invalidate as well any printout filter that may have been set
1123   }
1124   else
1125   {
1126     static_cast<TParameter<double>*>(p->At(kValue))->SetVal(value);
1127     static_cast<TParameter<double>*>(p->At(kErrorStat))->SetVal(errorStat);
1128     static_cast<TParameter<double>*>(p->At(kRMS))->SetVal(rms);
1129   }
1130 }
1131
1132 //_____________________________________________________________________________
1133 void AliAnalysisMuMuResult::Show(const char* keyPattern)
1134 {
1135   /// Specify which keys will be shown in the Print method...
1136
1137   if (!fVisibleKeys)
1138   {
1139     fVisibleKeys = new THashList;
1140     fVisibleKeys->SetOwner(kTRUE);
1141   }
1142   fVisibleKeys->Clear();
1143
1144   TIter next(fSubResults);
1145   AliAnalysisMuMuResult* r;
1146   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next())) )
1147   {
1148     r->Show(keyPattern);
1149   }
1150
1151   TIter nextKey(Keys());
1152   TObjString* str;
1153   
1154   TPRegexp re(keyPattern);
1155   
1156   while ( ( str = static_cast<TObjString*>(nextKey()) ) )
1157   {
1158     if ( re.MatchB(str->String()) )
1159     {
1160       fVisibleKeys->Add(new TObjString(*str));
1161     }
1162   }
1163   
1164 }
1165
1166 //_____________________________________________________________________________
1167 AliAnalysisMuMuResult*
1168 AliAnalysisMuMuResult::SubResult(const char* subResultName) const
1169 {
1170   /// get a given subresult
1171   if (!fSubResults)
1172   {
1173     return 0x0;
1174   }
1175   TIter next(fSubResults);
1176   AliAnalysisMuMuResult* r;
1177   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next())) )
1178   {
1179     if ( r->Alias() == subResultName )
1180     {
1181       return r;
1182     }
1183   }
1184   return 0x0;
1185 }
1186
1187 //_____________________________________________________________________________
1188 TList* AliAnalysisMuMuResult::SubResultsToBeIncluded() const
1189 {
1190   if (!fSubResultsToBeIncluded)
1191   {
1192     fSubResultsToBeIncluded = new TList;
1193     fSubResultsToBeIncluded->SetOwner(kTRUE);
1194   }
1195   return fSubResultsToBeIncluded;
1196 }
1197