6ec70ad0c62a3135e0223e797dfd314761acd598
[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   return TMath::Limits<Double_t>::Max();
465 }
466
467 //_____________________________________________________________________________
468 Double_t AliAnalysisMuMuResult::GetRMS(const char* name, const char* subResultName) const
469 {
470   // compute the rms of the subresults
471   // returns zero if no subresults
472
473   if ( strlen(subResultName) > 0 )
474   {
475     if ( !fSubResults)
476     {
477       AliError(Form("No subresult from which I could get the %s one...",subResultName));
478       return TMath::Limits<Double_t>::Max();
479     }
480     AliAnalysisMuMuResult* sub = static_cast<AliAnalysisMuMuResult*>(fSubResults->FindObject(subResultName));
481     if (!sub)
482     {
483       AliError(Form("Could not get subresult named %s",subResultName));
484       return TMath::Limits<Double_t>::Max();
485     }
486     return sub->GetRMS(name);
487   }
488   
489   if ( fMap )
490   {
491     TObjArray* p = static_cast<TObjArray*>(fMap->GetValue(name));
492     if (p)
493     {
494       TParameter<double>* val = static_cast<TParameter<double>*>(p->At(kRMS));
495       return val ? val->GetVal() : 0.0; // val can be null for old results which did not have the rms set
496     }
497   }
498   
499   TIter next(fSubResults);
500   AliAnalysisMuMuResult* r;
501   Double_t v1(0);
502   Double_t v2(0);
503   Double_t sum(0);
504   Int_t n(0);
505   
506   Double_t xmean = GetValue(name);
507   
508   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
509   {
510     if ( IsIncluded(r->Alias()) && r->HasValue(name) )
511     {
512       Double_t e2 = r->GetErrorStat(name);
513       
514       e2 *= e2;
515       
516       if ( !(e2>0.0) ) e2 = TMath::Sqrt(r->GetValue(name));
517       
518       Double_t wi = 1.0/e2;
519       v1 += wi;
520       v2 += wi*wi;
521       Double_t diff = r->GetValue(name) - xmean;
522       sum += wi*diff*diff;
523       ++n;
524     }
525   }
526   
527   if ( n < 1 ) return 0.0;
528   
529   if ( n == 1 )
530   {
531     next.Reset();
532     while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
533     {
534       if ( IsIncluded(r->Alias()) && r->HasValue(name) )
535       {
536         return r->GetRMS(name);
537       }
538     }
539   }
540   
541   Double_t unbiased = TMath::Sqrt( (v1/(v1*v1-v2)) * sum);
542   
543   Double_t biased = TMath::Sqrt( sum/v1 );
544   
545   AliDebug(1,Form("v1 %e v1*v1 %e v2 %e -> biased %e unbiased %e (ratio %e)",v1,v1*v1,v2,biased,unbiased,unbiased/biased));
546   
547   return unbiased;
548 }
549
550 //_____________________________________________________________________________
551 TString AliAnalysisMuMuResult::GetSubResultNameList() const
552 {
553   // get a comma separated list of our subresult aliases
554   TString tobeincluded;
555   TIter next(fSubResults);
556   AliAnalysisMuMuResult* r;
557   
558   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next())) )
559   {
560     if (tobeincluded.Length()>0) tobeincluded+=",";
561     tobeincluded += r->Alias();
562   }
563   return tobeincluded;
564 }
565
566 //_____________________________________________________________________________
567 Double_t AliAnalysisMuMuResult::GetValue(const char* name, const char* subResultName) const
568 {
569   // get a value (either directly or by computing the mean of the subresults)
570   
571   if ( strlen(subResultName) > 0 )
572   {
573     if ( !fSubResults)
574     {
575       AliError(Form("No subresult from which I could get the %s one...",subResultName));
576       return TMath::Limits<Double_t>::Max();
577     }
578     AliAnalysisMuMuResult* sub = static_cast<AliAnalysisMuMuResult*>(fSubResults->FindObject(subResultName));
579     if (!sub)
580     {
581       AliError(Form("Could not get subresult named %s",subResultName));
582       return TMath::Limits<Double_t>::Max();
583     }
584     return sub->GetValue(name);
585   }
586   
587   if (fMap)
588   {
589     TObjArray* p = static_cast<TObjArray*>(fMap->GetValue(name));
590     if (p)
591     {
592       TParameter<double>* val = static_cast<TParameter<double>*>(p->At(kValue));
593       return val->GetVal();
594     }
595   }
596   
597   // merge the value from all subresults
598   TIter next(fSubResults);
599   AliAnalysisMuMuResult* r;
600   
601   if ( fResultMergingMethod == kMean )
602   {
603     Double_t mean(0);
604     Double_t errorSum(0.0);
605
606     while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
607     {
608       if ( IsIncluded(r->Alias()) && r->HasValue(name) )
609       {
610         Double_t e = r->GetErrorStat(name)/TMath::Sqrt(r->GetValue(name)); //The Sqrt(r->GetValue(name)) was not here before
611         Double_t e2 = e*e;
612         if ( !(e2>0.0 ) ) e2 = TMath::Sqrt(r->GetValue(name));
613
614         mean += r->GetValue(name)/e2;
615         errorSum += 1.0/e2;
616       }
617     }
618     if ( errorSum != 0.0 )
619     {
620       return mean/errorSum;
621     }
622     else
623     {
624       return TMath::Limits<Double_t>::Max();
625     }
626   }
627   else
628   {
629     Double_t sum(0.0);
630     
631     while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
632     {
633       if ( IsIncluded(r->Alias()) && r->HasValue(name) )
634       {
635         sum += r->GetValue(name);
636       }
637     }
638     
639     return sum;
640   }
641 }
642
643 //_____________________________________________________________________________
644 Int_t AliAnalysisMuMuResult::HasValue(const char* name, const char* subResultName) const
645 {
646   /// Whether this result (or subresult if subResultName is provided) has a property
647   /// named "name"
648   ///
649   /// When having subresults, return the number of subresults that have this value
650   ///
651   
652   if ( strlen(subResultName) > 0 )
653   {
654     if ( !fSubResults)
655     {
656       AliError(Form("No subresult from which I could get the %s one...",subResultName));
657       return 0;
658     }
659     AliAnalysisMuMuResult* sub = static_cast<AliAnalysisMuMuResult*>(fSubResults->FindObject(subResultName));
660     if (!sub)
661     {
662       AliError(Form("Could not get subresult named %s",subResultName));
663       return 0;
664     }
665     return sub->HasValue(name);
666   }
667
668   if ( fMap && ( fMap->GetValue(name) != 0x0 ) )
669   {
670     return 1;
671   }
672   
673   TIter next(fSubResults);
674   AliAnalysisMuMuResult* r;
675   Int_t n(0);
676   
677   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
678   {
679     if ( r->HasValue(name) ) ++n;
680   }
681   
682   return n;
683 }
684
685 //_____________________________________________________________________________
686 void AliAnalysisMuMuResult::Hide(const char* keyPattern)
687 {
688   /// Specify which keys will be hidden in the Print method...
689   
690   if (!fVisibleKeys)
691   {
692     fVisibleKeys = new THashList;
693     fVisibleKeys->SetOwner(kTRUE);
694   }
695   fVisibleKeys->Clear();
696   
697   TIter next(fSubResults);
698   AliAnalysisMuMuResult* r;
699   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next())) )
700   {
701     r->Hide(keyPattern);
702   }
703   
704   TIter nextKey(Keys());
705   TObjString* str;
706   
707   TPRegexp re(keyPattern);
708   
709   while ( ( str = static_cast<TObjString*>(nextKey()) ) )
710   {
711     if ( !re.MatchB(str->String()) )
712     {
713       fVisibleKeys->Add(new TObjString(*str));
714     }
715   }
716   
717 }
718 //_____________________________________________________________________________
719 void AliAnalysisMuMuResult::Include(const char* subResultList)
720 {
721   // (re)include some subresult names
722   
723   TString slist(subResultList);
724
725   if ( slist.Length()==0 )
726   {
727     Exclude("*");
728     return;
729   }
730   
731   if ( slist == "*" )
732   {
733     slist = GetSubResultNameList();
734   }
735
736   TObjArray* a = slist.Tokenize(",");
737   a->SetOwner(kFALSE);
738   TIter next(a);
739   TObjString* s;
740   
741   while ( ( s = static_cast<TObjString*>(next()) ) )
742   {
743     if (!fSubResultsToBeIncluded )
744     {
745       fSubResultsToBeIncluded = new TList;
746       fSubResultsToBeIncluded->SetOwner(kTRUE);
747     }
748     if (!IsIncluded(s->String()))
749     {
750       fSubResultsToBeIncluded->Add(s);      
751     }
752   }
753   
754   delete a;
755 }
756
757 //_____________________________________________________________________________
758 Bool_t AliAnalysisMuMuResult::IsIncluded(const TString& alias) const
759 {
760   // whether that subresult alias should be included when computing means, etc...
761   
762   if (!fSubResultsToBeIncluded) return kTRUE;
763   
764   return ( fSubResultsToBeIncluded->FindObject(alias) != 0x0 );
765 }
766
767 //_____________________________________________________________________________
768 Bool_t AliAnalysisMuMuResult::IsValidValue(Double_t val) const
769 {
770   /// Whether val is a valid one
771   return ( val < TMath::Limits<Double_t>::Max() );
772 }
773
774 //_____________________________________________________________________________
775 THashList* AliAnalysisMuMuResult::Keys() const
776 {
777   /// Return the complete list of keys we're using
778   if (!fKeys)
779   {
780     fKeys = new THashList;
781     fKeys->SetOwner(kTRUE);
782     TIter next(fMap);
783     TObjString* key;
784     
785     while ( ( key = static_cast<TObjString*>(next()) ) )
786     {
787       if ( !fKeys->FindObject(key->String()) )
788       {
789         fKeys->Add(new TObjString(key->String()));
790       }
791     }
792     
793     AliAnalysisMuMuResult* r;
794     TIter nextResult(fSubResults);
795     
796     while ( ( r = static_cast<AliAnalysisMuMuResult*>(nextResult())) )
797     {
798       TIter nextHL(r->Keys());
799       TObjString* s;
800       
801       while ( ( s = static_cast<TObjString*>(nextHL())) )
802       {
803         if ( !fKeys->FindObject(s->String()) )
804         {
805           fKeys->Add(new TObjString(s->String()));
806         }
807       }
808     }
809
810     fKeys->Sort();
811   }
812   return fKeys;
813 }
814
815 //_____________________________________________________________________________
816 Long64_t AliAnalysisMuMuResult::Merge(TCollection* list)
817 {
818   /// Merge method
819   ///
820   /// Merge a list of AliAnalysisMuMuResult objects with this
821   /// Returns the number of merged objects (including this).
822   ///
823   /// Note that the merging is to be understood here as a weighed mean operation
824   
825   if (!list) return 0;
826   
827   if (list->IsEmpty()) return 1;
828   
829   TIter next(list);
830   TObject* currObj;
831
832   Double_t sumw(Weight()); // sum of weights
833   
834   while ( ( currObj = next() ) )
835   {
836     AliAnalysisMuMuResult* result = dynamic_cast<AliAnalysisMuMuResult*>(currObj);
837     if (!result)
838     {
839       AliFatal(Form("object named \"%s\" is a %s instead of an AliAnalysisMuMuResult!", currObj->GetName(), currObj->ClassName()));
840       continue;
841     }
842     
843     sumw += result->Weight();
844   }
845   
846   TIter nextKey(Keys());
847   TObjString* key;
848   
849   while ( ( key = static_cast<TObjString*>(nextKey())) )
850   {
851     Double_t value = GetValue(key->String())*Weight()/sumw;
852     Double_t e = GetErrorStat(key->String());
853     Double_t e2 = e*e*Weight()*Weight()/sumw/sumw;
854
855     next.Reset();
856     
857     while ( ( currObj = next() ) )
858     {
859       AliAnalysisMuMuResult* result = dynamic_cast<AliAnalysisMuMuResult*>(currObj);
860     
861       if (!result)
862       { 
863         continue;
864       }
865       
866       if (!result->HasValue(key->String()))
867       {
868         AliError(Form("Did not find key %s in of the result to merge",key->String().Data()));
869         continue;
870       }
871       
872       // can only merge under the condition we have the same bin
873     
874       Double_t w = result->Weight()/sumw;
875       
876       Double_t w2 = w*w;
877       
878       value += result->GetValue(key->String())*w;
879       e2 += result->GetErrorStat(key->String())*result->GetErrorStat(key->String())*w2;
880       
881     }
882     
883     Set(key->String(),
884         value,
885         TMath::Sqrt(e2));
886   }
887   
888   TIter nextSubresult(fSubResults);
889   AliAnalysisMuMuResult* r;
890   
891   while ( ( r = static_cast<AliAnalysisMuMuResult*>(nextSubresult())) )
892   {
893     TList sublist;
894
895     next.Reset();
896     
897     while ( ( currObj = next() ) )
898     {
899       sublist.Add(currObj);
900     }
901
902     r->Merge(&sublist);
903   }
904   
905   fWeight = sumw;
906   
907   return list->GetEntries()+1;
908 }
909
910 //_____________________________________________________________________________
911 Int_t AliAnalysisMuMuResult::NofIncludedSubResults(const char* name) const
912 {
913   // Return the number of subresults which have key name and are included
914   
915   TIter next(fSubResults);
916   AliAnalysisMuMuResult* r;
917   Int_t n(0);
918   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next()) ) )
919   {
920     if ( IsIncluded(r->Alias()) && r->HasValue(name) )
921     {
922       ++n;
923     }
924   }
925   return n;
926 }
927
928 //_____________________________________________________________________________
929 void AliAnalysisMuMuResult::Print(Option_t* opt) const
930 {
931   /// printout
932   
933   TString sopt(opt);
934   sopt.ToUpper();
935   
936   for ( Int_t i = 0; i < 9; ++i )
937   {
938     sopt.ReplaceAll(Form("%d",i),"");
939   }
940   
941   TString pot(sopt);
942   pot.ReplaceAll("ALL","");
943   pot.ReplaceAll("FULL","");
944
945   std::cout << pot.Data() << " ";
946   
947     if ( fAlias.Length() > 0 )
948     {
949       std::cout << Form("%s - ",fAlias.Data());
950     }
951   
952     std::cout << Form("%s %s %s",
953                       GetName(),GetTitle(),fWeight > 0.0 ? Form(" WEIGHT %e",fWeight) : "");
954   
955   if ( fSubResults && fSubResults->GetEntries()>1 )
956   {
957     std::cout << " (" << fSubResults->GetEntries() << " subresults)";
958   }
959
960   std::cout << std::endl;
961   
962   TIter next(Keys());
963   TObjString* key;
964   
965   Int_t nsub = fSubResults ? fSubResults->GetEntries() : 0;
966   
967   while ( ( key = static_cast<TObjString*>(next())) )
968   {
969     if ( fVisibleKeys  && ! fVisibleKeys->FindObject(key->String()) ) continue;
970         
971     if ( nsub==0 || nsub == HasValue(key->String().Data()) )
972     {
973       PrintValue(key->String().Data(),pot.Data(),
974                  GetValue(key->String()),
975                  GetErrorStat(key->String()),
976                  GetRMS(key->String()));
977     }
978   }
979
980   if ( fSubResults /* && fSubResults->GetEntries() > 1 */ && ( sopt.Contains("ALL") || sopt.Contains("FULL") ) )
981   {
982     std::cout << pot.Data() << "\t===== sub results ===== " << std::endl;
983     
984     sopt += "\t\t";
985     
986     TIter nextSubresult(fSubResults);
987     AliAnalysisMuMuResult* r;
988     
989     while ( ( r = static_cast<AliAnalysisMuMuResult*>(nextSubresult()) ) )
990     {
991       if ( !IsIncluded(r->Alias()) )
992       {
993         std::cout << " [EXCLUDED]";
994       }
995       r->Print(sopt.Data());
996     }
997   }
998 }
999
1000 //_____________________________________________________________________________
1001 void AliAnalysisMuMuResult::PrintValue(const char* key, const char* opt,
1002                                        Double_t value, Double_t errorStat, Double_t rms) const
1003 {
1004   // print one value and its associated error
1005   
1006   if ( TString(key).Contains("AccEff") )
1007   {
1008     std::cout << opt << Form("\t\t%20s %9.2f +- %5.2f %% (%5.2f %%)",key,value*100,errorStat*100,
1009                              value != 0.0 ? errorStat*100.0/value : 0.0 );
1010     
1011     if ( rms )
1012     {
1013       std::cout << Form(" RMS %9.2f (%5.2f %%)",rms,100.0*rms/value);
1014     }
1015
1016     std::cout << std::endl;
1017   }
1018   else if ( TString(key).BeginsWith("Sigma") ||  TString(key).BeginsWith("Mean") )
1019   {
1020     std::cout << opt << Form("\t\t%20s %9.2f +- %5.2f (%5.2f %%) MeV/c^2",key,value*1E3,1E3*errorStat,
1021                              value != 0.0 ? errorStat*100.0/value : 0.0);
1022     
1023     if ( rms )
1024     {
1025       std::cout << Form(" RMS %9.2f (%5.2f %%)",rms,100.0*rms/value);
1026     }
1027
1028     std::cout << std::endl;
1029   }
1030   else if ( TString(key).Contains("Nof") || ( TString(key).Contains("Fnorm") && !TString(key).Contains("persion") ) )
1031   {
1032     std::cout << opt << Form("\t\t%20s %9.3f +- %5.3f (%5.2f %%)",key,value,errorStat,
1033                              value != 0.0 ? errorStat*100.0/value : 0.0);
1034     
1035     if ( rms )
1036     {
1037       std::cout << Form(" RMS %9.2f (%5.2f %%)",rms,100.0*rms/value);
1038     }
1039     std::cout << std::endl;
1040   }
1041   else if ( value > 1E-3 && value < 1E3 )
1042   {
1043     if (errorStat > 0.0)
1044     {
1045       std::cout << opt << Form("\t\t%20s %9.3f +- %5.3f (%5.3f %%)",key,value,errorStat,
1046                              value != 0.0 ? errorStat*100.0/value : 0.0);
1047       if ( rms )
1048       {
1049         std::cout << Form(" RMS %9.2f (%5.2f %%)",rms,100.0*rms/value);
1050       }
1051     }
1052     else
1053     {
1054       std::cout << opt << Form("\t\t%20s %9.3f",key,value);
1055     }
1056     std::cout << std::endl;
1057   }
1058   else
1059   {
1060     if ( errorStat > 0.0 )
1061     {
1062       
1063       std::cout << opt << Form("\t\t%20s %9.2e +- %9.2e (%5.2f %%)",key,value,errorStat,
1064                                value != 0.0 ? errorStat*100.0/value : 0.0);
1065       if ( rms )
1066       {
1067         std::cout << Form(" RMS %9.2e (%5.2f %%)",rms,100.0*rms/value);
1068       }
1069     }
1070     else
1071     {
1072       std::cout << opt << Form("\t\t%20s %9.2e ",key,value);
1073     }
1074     std::cout << std::endl;
1075   }
1076 }
1077
1078 //_____________________________________________________________________________
1079 void AliAnalysisMuMuResult::Scale(Double_t w)
1080 {
1081   /// Scale all our internal values by value
1082   
1083   TIter next(Keys());
1084   TObjString* key;
1085   
1086   while ( ( key = static_cast<TObjString*>(next())) )
1087   {
1088     Double_t value = GetValue(key->String());
1089     Double_t error = GetErrorStat(key->String());
1090     Double_t rms = GetRMS(key->String());
1091     
1092     Set(key->String(),value*w,error*w,rms*w);
1093   }
1094
1095 }
1096
1097 //_____________________________________________________________________________
1098 void AliAnalysisMuMuResult::Set(const char* name, Double_t value, Double_t errorStat, Double_t rms)
1099 {
1100   /// Set a (value,error) pair with a given name
1101   
1102   if ( !fMap )
1103   {
1104     fMap = new TMap;
1105     fMap->SetOwnerKeyValue(kTRUE,kTRUE);
1106   }
1107   
1108   TObjArray* p = static_cast<TObjArray*>(fMap->GetValue(name));
1109   if (!p)
1110   {
1111     p = new TObjArray(4);
1112     
1113     p->SetOwner(kTRUE);
1114     
1115     p->AddAt(new TParameter<Double_t>(name,value),kValue);
1116     p->AddAt(new TParameter<Double_t>(name,errorStat),kErrorStat);
1117     p->AddAt(new TParameter<Double_t>(name,rms),kRMS);
1118     
1119     fMap->Add(new TObjString(name),p);
1120     
1121     delete fKeys; // invalidate previously computed keys arrays, if any
1122     fKeys=0x0;
1123 //    Show("*"); // invalidate as well any printout filter that may have been set
1124   }
1125   else
1126   {
1127     static_cast<TParameter<double>*>(p->At(kValue))->SetVal(value);
1128     static_cast<TParameter<double>*>(p->At(kErrorStat))->SetVal(errorStat);
1129     static_cast<TParameter<double>*>(p->At(kRMS))->SetVal(rms);
1130   }
1131 }
1132
1133 //_____________________________________________________________________________
1134 void AliAnalysisMuMuResult::Show(const char* keyPattern)
1135 {
1136   /// Specify which keys will be shown in the Print method...
1137
1138   if (!fVisibleKeys)
1139   {
1140     fVisibleKeys = new THashList;
1141     fVisibleKeys->SetOwner(kTRUE);
1142   }
1143   fVisibleKeys->Clear();
1144
1145   TIter next(fSubResults);
1146   AliAnalysisMuMuResult* r;
1147   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next())) )
1148   {
1149     r->Show(keyPattern);
1150   }
1151
1152   TIter nextKey(Keys());
1153   TObjString* str;
1154   
1155   TPRegexp re(keyPattern);
1156   
1157   while ( ( str = static_cast<TObjString*>(nextKey()) ) )
1158   {
1159     if ( re.MatchB(str->String()) )
1160     {
1161       fVisibleKeys->Add(new TObjString(*str));
1162     }
1163   }
1164   
1165 }
1166
1167 //_____________________________________________________________________________
1168 AliAnalysisMuMuResult*
1169 AliAnalysisMuMuResult::SubResult(const char* subResultName) const
1170 {
1171   /// get a given subresult
1172   if (!fSubResults)
1173   {
1174     return 0x0;
1175   }
1176   TIter next(fSubResults);
1177   AliAnalysisMuMuResult* r;
1178   while ( ( r = static_cast<AliAnalysisMuMuResult*>(next())) )
1179   {
1180     if ( r->Alias() == subResultName )
1181     {
1182       return r;
1183     }
1184   }
1185   return 0x0;
1186 }
1187
1188 //_____________________________________________________________________________
1189 TList* AliAnalysisMuMuResult::SubResultsToBeIncluded() const
1190 {
1191   if (!fSubResultsToBeIncluded)
1192   {
1193     fSubResultsToBeIncluded = new TList;
1194     fSubResultsToBeIncluded->SetOwner(kTRUE);
1195   }
1196   return fSubResultsToBeIncluded;
1197 }
1198