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