1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 /// AliAnalysisMuMuFnorm : class to encapsulate computation(s)
18 /// of the normalisation factor used to get the equivalent
19 /// number of MB events from the number of CMUL triggers
21 /// The computed objects are stored within a AliMergeableCollection
22 /// with 3 subdirectories, dependinf on their type
28 /// author: Laurent Aphecetche (Subatech)
30 #include "AliAnalysisMuMuFnorm.h"
32 #include "AliAnalysisMuMuGraphUtil.h"
33 #include "AliAnalysisMuMuResult.h"
34 #include "AliAnalysisTriggerScalers.h"
35 #include "AliCounterCollection.h"
37 #include "AliMergeableCollection.h"
38 #include "Riostream.h"
41 #include "TGraphErrors.h"
46 #include "TObjArray.h"
47 #include "TObjString.h"
48 #include "TPaveText.h"
53 ClassImp(AliAnalysisMuMuFnorm)
55 //_____________________________________________________________________________
56 AliAnalysisMuMuFnorm::AliAnalysisMuMuFnorm(AliCounterCollection& cc,
57 AliAnalysisMuMuFnorm::ETriggerType refTriggerType,
59 Bool_t compactGraphs) :
61 fCounterCollection(cc),
62 fMergeableCollection(0x0),
65 fIsCompactGraphs(compactGraphs),
66 fReferenceTriggerType(refTriggerType)
73 //_____________________________________________________________________________
74 AliAnalysisMuMuFnorm::~AliAnalysisMuMuFnorm()
79 delete fMergeableCollection;
83 //_____________________________________________________________________________
84 void AliAnalysisMuMuFnorm::ComputeFnorm()
86 /// Compute the CMUL to CINT ratio(s)
88 /// Using offline method
89 /// - in one go CINT/CMUL
90 /// - in two steps CINT/CMSL and CMSL/CMUL
92 /// Using scaler method
93 /// - bare scaler values
94 /// - scaler values corrected for pile-up
95 /// - scaler values corrected for pile-up and physics selection
97 const ETriggerType triggerTypes[] = { kMB, kMUL, kMSL, kMSH };
98 const Bool_t trueFalse[] = { kTRUE, kFALSE };
100 for ( Int_t i = 0; i < 4; ++i )
102 for ( Int_t pileup = 0; pileup < 2; ++pileup )
104 for ( Int_t ps = 0; ps < 2; ++ps )
106 ComputeNofEvents(triggerTypes[i],trueFalse[pileup],ps);
111 ComputeFnormOffline(1,kFALSE,0);
112 ComputeFnormOffline(1,kFALSE,1);
113 ComputeFnormOffline(1,kTRUE,1);
115 ComputeFnormOffline(2,kFALSE,0);
116 ComputeFnormOffline(2,kFALSE,1);
117 ComputeFnormOffline(2,kTRUE,1);
119 // ComputeFnormOffline(2,kFALSE,2);
120 // ComputeFnormOffline(2,kTRUE,2);
122 ComputeFnormScalers(kFALSE,0);
123 ComputeFnormScalers(kTRUE,0);
124 ComputeFnormScalers(kTRUE,1);
125 // ComputeFnormScalers(kTRUE,2);
127 WeightedMeanGraphs("Offline");
128 WeightedMeanGraphs("Scalers");
129 WeightedMeanGraphs("FnormOffline2PUPS,FnormOffline1PUPS","FnormOffline12PUPS");
131 WeightedMeanGraphs("FnormOffline2PUPS,FnormScalersPUPS","FnormBest2");
133 ComputeGraphRelDif("FnormOffline2PUPS","FnormScalersPUPS");
135 ComputeGraphRelDif("FnormOffline2PUPS","FnormOffline2");
136 ComputeGraphRelDif("FnormOffline2PUPS","FnormOffline2PS");
138 ComputeGraphRelDif("CorrectionPSMB","CorrectionPSMUL");
140 // for ( Int_t i = 0; i < 4; ++i )
142 TString triggerEvents;
144 // triggerEvents.Form("NofEvent%sPUPS",GetTriggerTypeName(triggerTypes[i]).Data());
145 triggerEvents.Form("NofEvent%sPUPS",GetTriggerTypeName(fReferenceTriggerType).Data());
147 MultiplyGraphs(triggerEvents.Data(),"FnormBest2","NMBeqBest2");
149 MultiplyGraphs(triggerEvents.Data(),"FnormOffline2PUPS","NMBeqOffline2PUPS");
150 MultiplyGraphs(triggerEvents.Data(),"FnormScalersPUPS","NMBeqScalersPUPS");
153 // MultiplyGraphs(Form("NofEvent%sPUTS",GetTriggerTypeName(fReferenceTriggerType).Data()),"FnormOffline2PUTS","NMBeqOffline2PUTS");
154 // MultiplyGraphs(Form("NofEvent%sPUTS",GetTriggerTypeName(fReferenceTriggerType).Data()),"FnormOffline2TS","NMBeqOffline2TS");
156 ComputeResultsFromGraphs();
158 AliAnalysisMuMuResult* result = GetResult("Fnorm");
161 result->Exclude("*");
162 result->Include("FnormBest2");
166 //_____________________________________________________________________________
167 void AliAnalysisMuMuFnorm::ComputeCorrectionFactors(Int_t eventSelectionCorrected)
169 /// Compute individual graphs for the correction factors (PS_CMUL, PS_CINT,
170 /// F_pile-up,PS_CINT/PS_CMUL) used in the computation of (some) Fnorm factors
173 TString graphName(Form("CorrectionGlobal%s",GetEventSelectionName(eventSelectionCorrected).Data()));;
175 if ( GetGraph(graphName) )
177 // insure we compute it only once
183 std::vector<double> vx;
184 std::vector<double> vxerr;
185 std::vector<double> vy;
186 std::vector<double> vyerr;
188 std::vector<double> vyGlobal;
189 std::vector<double> vyGlobalErr;
191 const ETriggerType triggerTypes[] = { kMB, kMUL, kMSL, kMSH };
193 for ( Int_t i = 0; i < 4; ++i )
195 ComputeEventSelectionGraph(triggerTypes[i],eventSelectionCorrected);
196 ComputePileUpGraph(triggerTypes[i],eventSelectionCorrected);
199 TGraphErrors* gPSCINT = GetGraph(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(AliAnalysisMuMuFnorm::kMB).Data()));
201 TGraphErrors* gPSCMUL = GetGraph(Form("Correction%s%s", GetEventSelectionName(eventSelectionCorrected).Data(), GetTriggerTypeName(AliAnalysisMuMuFnorm::kMUL).Data()));
203 TGraphErrors* gPU = GetGraph(Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(), GetTriggerTypeName(AliAnalysisMuMuFnorm::kMB).Data()));
205 if ( !gPSCINT || !gPSCMUL || !gPU )
207 AliError("Did not get the relevant graphs. Cannot work");
211 for ( Int_t i = 0; i < gPSCINT->GetN(); ++i )
213 Double_t x,y,yerr,yGlobal,yGlobalErr;
215 gPSCINT->GetPoint(i,x,y);
217 if ( fIsCompactGraphs )
219 x = TString(gPSCINT->GetXaxis()->GetBinLabel(i)).Atoi();
222 yGlobal = gPSCINT->GetY()[i] * gPU->GetY()[i] / gPSCMUL->GetY()[i];
224 yGlobalErr = yGlobal*AliAnalysisMuMuResult::ErrorABC(gPSCINT->GetY()[i],gPSCINT->GetEY()[i],
225 gPSCMUL->GetY()[i],gPSCMUL->GetEY()[i],
226 gPU->GetY()[i],gPU->GetEY()[i]);
228 y = gPSCINT->GetY()[i] / gPSCMUL->GetY()[i];
229 yerr = y * AliAnalysisMuMuResult::ErrorAB(gPSCINT->GetY()[i],gPSCINT->GetEY()[i],
230 gPSCMUL->GetY()[i],gPSCMUL->GetEY()[i]);
233 vxerr.push_back(gPSCINT->GetEX()[i]);
235 vyGlobal.push_back(yGlobal);
236 vyGlobalErr.push_back(yGlobalErr);
239 vyerr.push_back(yerr);
242 TString name(Form("Correction%sRatio",GetEventSelectionName(eventSelectionCorrected).Data()));
243 TString title(Form("%s_MB/%s_%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(fReferenceTriggerType).Data(),
244 GetEventSelectionName(eventSelectionCorrected).Data()));
246 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);
248 title = TString::Format("%s_MB x Fpile-up / %s_%s ",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(fReferenceTriggerType).Data(),GetEventSelectionName(eventSelectionCorrected).Data());
250 CreateAndAddGraph(graphName,title,vx,vxerr,vyGlobal,vyGlobalErr);
253 //_____________________________________________________________________________
254 void AliAnalysisMuMuFnorm::ComputeFnormOffline(Int_t nstep, Bool_t pileUpCorrected, Int_t eventSelectionCorrected)
256 /// Compute MB to CMUL ratio using offline method, either in 1 or 2 steps
258 TString name("FnormOffline");
259 TString title("Computed using offline information");
264 title += " in one step (CINT/CINT&0MUL)";
269 title += " in two steps (CMSL/CMSL&0MUL x CINT/CINT&MSL)";
275 title += " with pile-up correction";
277 if (eventSelectionCorrected==1)
280 title += " with (ps) purity corrections";
282 else if ( eventSelectionCorrected==2 )
285 title += " with (ts) purity corrections";
288 if ( GetGraph(name) )
290 // insure we're computing it only once
296 std::vector<double> vx;
297 std::vector<double> vxerr;
298 std::vector<double> vy;
299 std::vector<double> vyerr;
301 const std::set<int>& runs = RunNumbers();
303 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
305 Int_t runNumber = *it;
307 TString mbTrigger = GetTriggerClassName(kMB,runNumber);
308 TString muonTrigger = GetTriggerClassName(kMSL,runNumber);
309 TString dimuonTrigger = GetTriggerClassName(kMUL,runNumber);
311 if (!mbTrigger.Length())
313 AliError(Form("Cannot get MB trigger for run %d",runNumber));
317 Double_t nofMB = GetSum(mbTrigger.Data(),runNumber,eventSelectionCorrected);
318 Double_t nofMSL(0.0);
319 Double_t nofMSLw0MUL(0.0);
323 nofMSL = GetSum(muonTrigger.Data(),runNumber,eventSelectionCorrected);
324 nofMSLw0MUL = GetSum(Form("%s&0MUL",muonTrigger.Data()),runNumber,eventSelectionCorrected);
327 Double_t nofMBw0MUL = GetSum(Form("%s&0MUL",mbTrigger.Data()),runNumber,eventSelectionCorrected);
328 Double_t nofMBw0MSL = GetSum(Form("%s&0MSL",mbTrigger.Data()),runNumber,eventSelectionCorrected);
330 if ( !nofMBw0MUL ) continue;
331 if ( !nofMBw0MSL && nstep == 2 ) continue;
333 Double_t purityMB(1.0);
334 Double_t purityMBerror(0.0);
336 if ( eventSelectionCorrected > 0 )
338 ComputeEventSelectionGraph(kMB,eventSelectionCorrected);
340 TGraphErrors* gps = GetGraph(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(kMB).Data()));
342 GetValueAndErrorFromGraph(gps,runNumber,purityMB,purityMBerror);
345 Double_t pileUpFactor(1.0);
346 Double_t pileUpFactorError(0.0);
350 ComputePileUpGraph(kMB,eventSelectionCorrected);
352 TGraphErrors* gpu = GetGraph(Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(kMB).Data()));
354 GetValueAndErrorFromGraph(gpu,runNumber,pileUpFactor,pileUpFactorError);
356 nofMB *= pileUpFactor;
359 double value = nofMBw0MUL > 0.0 ? nofMB/nofMBw0MUL : 0.0;
360 double error = value*AliAnalysisMuMuResult::ErrorABC(nofMB,TMath::Sqrt(nofMB),
361 nofMBw0MUL,TMath::Sqrt(nofMBw0MUL),
362 pileUpFactor,pileUpFactorError);
366 value = (nofMB/nofMSLw0MUL)*(nofMSL/nofMBw0MSL);
368 if ( runNumber == 196310 )
370 AliDebug(1,Form("RUN %09d %d-%d-%d value=%e nofMB %e nofMSLw0MUL %e nofMSL %e nofMBw0MSL %e",
371 runNumber,nstep,pileUpCorrected,eventSelectionCorrected,
372 value,nofMB,nofMSLw0MUL,nofMSL,nofMBw0MSL));
375 error = value*AliAnalysisMuMuResult::ErrorABCD(nofMB,TMath::Sqrt(nofMB),
376 nofMSLw0MUL,TMath::Sqrt(nofMSLw0MUL),
377 nofMSL,TMath::Sqrt(nofMSL),
378 nofMBw0MSL,TMath::Sqrt(nofMBw0MSL));
383 vx.push_back(1.0*runNumber);
384 vxerr.push_back(0.5);
386 vyerr.push_back(error);
391 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);
395 //_____________________________________________________________________________
396 void AliAnalysisMuMuFnorm::ComputeFnormScalers(Bool_t pileUpCorrected,
397 Int_t eventSelectionCorrected)
399 /// Compute the MB to CMUL ratio using the scalers method (from OCDB)
401 /// i.e. Fnorm = L0B(MB) x PS(MB) x Fpile-up / ( L0B(REF) x PS(REF) )
403 /// where MB is the minbias trigger
404 /// REF is the fReferenceTrigger
405 /// and PS is the fraction of events selected by the physics selection
407 /// The correction factor (the two PS and one Fpile-up) are
408 /// taken from graphs computed in other methods
411 TString name("FnormScalers");
412 TString title("Computed using OCDB scalers");
417 title += " with pile-up correction";
419 if (eventSelectionCorrected==1)
422 title += " with (ps) purity corrections";
424 if (eventSelectionCorrected==2)
427 title += " with (ts) purity corrections";
430 if ( GetGraph(name) )
432 // insure we're computing it only once
438 // insure we have all the graphs we need to work
439 ComputeTriggerL0B(kMB);
440 ComputeTriggerL0B(fReferenceTriggerType);
442 const std::set<int>& runs = RunNumbers();
444 std::vector<double> vx;
445 std::vector<double> vxerr;
446 std::vector<double> vy;
447 std::vector<double> vyerr;
449 Double_t purityREF(1.0);
450 Double_t purityMB(1.0);
451 Double_t purityREFerror(00);
452 Double_t purityMBerror(0.0);
454 // compute the per run values
455 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
457 Int_t runNumber = *it;
459 TString mbTrigger = GetTriggerClassName(kMB,runNumber);
460 TString refTrigger = GetTriggerClassName(fReferenceTriggerType,runNumber);
462 purityMB=purityREF=1.0;
463 purityMBerror=purityREFerror=0.0;
465 if (eventSelectionCorrected>0)
467 ComputeEventSelectionGraph(kMB,eventSelectionCorrected);
468 ComputeEventSelectionGraph(fReferenceTriggerType,eventSelectionCorrected);
470 TGraphErrors* gpsMB = GetGraph(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(kMB).Data()));
471 TGraphErrors* gpsREF = GetGraph(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(fReferenceTriggerType).Data()));
473 GetValueAndErrorFromGraph(gpsMB,runNumber,purityMB,purityMBerror);
474 GetValueAndErrorFromGraph(gpsREF,runNumber,purityREF,purityREFerror);
479 AliError(Form("Got purity=%e for MB for run %9d",purityMB,runNumber));
483 TGraphErrors* gl0bMB = GetGraph(Form("L0B%s",GetTriggerTypeName(kMB).Data()));
484 TGraphErrors* gl0bREF = GetGraph(Form("L0B%s",GetTriggerTypeName(fReferenceTriggerType).Data()));
486 Double_t L0bMB,L0bMBError;
487 Double_t L0bREF,L0bREFError;
489 GetValueAndErrorFromGraph(gl0bMB,runNumber,L0bMB,L0bMBError);
490 GetValueAndErrorFromGraph(gl0bREF,runNumber,L0bREF,L0bREFError);
492 Double_t pileUpFactor(1.0);
493 Double_t pileUpFactorError(0.0);
497 TGraphErrors* gpu = GetGraph((Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(kMB).Data())));
499 GetValueAndErrorFromGraph(gpu,runNumber,pileUpFactor,pileUpFactorError);
505 ScalerFnorm(value,error,
506 L0bREF,purityREF,purityREFerror,
507 L0bMB,purityMB,purityMBerror,
508 pileUpFactor,pileUpFactorError);
512 vx.push_back(1.0*runNumber);
513 vxerr.push_back(0.5);
515 vyerr.push_back(error);
519 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);
522 //_____________________________________________________________________________
523 void AliAnalysisMuMuFnorm::ComputeGraphRelDif(const char* a, const char* b) const
525 // compute dispersion of b versus a
527 // computed differences graphs are put into the GRAPHS/ directory
528 // computed differences results are put into the HISTOS/ directory
530 TString name(Form("RelDif%svs%s",b,a));
532 if ( GetGraph(name) )
534 // insure we compute it only once
540 TGraphErrors* ga = static_cast<TGraphErrors*>(MC()->GetObject(Form("/GRAPHS/%s",a)));
541 TGraphErrors* gb = static_cast<TGraphErrors*>(MC()->GetObject(Form("/GRAPHS/%s",b)));
545 AliError(Form("Cannot get graph for %s",a));
551 AliError(Form("Cannot get graph for %s",b));
555 if ( ga->GetN() != gb->GetN() )
557 AliError(Form("Cannot work with different number of points in the graphs : %d vs %d",
558 ga->GetN(),gb->GetN()));
562 TString title(Form("%s-%s (RelDif,%%)",b,a));
564 std::vector<double> vx;
565 std::vector<double> vxerr;
566 std::vector<double> vy;
567 std::vector<double> vyerr;
569 for ( Int_t i = 0; i < ga->GetN(); ++i )
571 Double_t xa,xb,ya,yb;
573 ga->GetPoint(i,xa,ya);
574 gb->GetPoint(i,xb,yb);
578 AliError(Form("Incompatible graphs : got xa=%e and xb=%e",xa,xb));
582 Double_t newvalue = 0.0;
584 if ( TMath::Abs(xa) > 1E-12 )
586 newvalue = 100.0*( yb - ya ) / ya;
589 Double_t yerr = newvalue*AliAnalysisMuMuResult::ErrorAB(ya,ga->GetEY()[i],
592 if ( fIsCompactGraphs )
594 xa = TString(ga->GetXaxis()->GetBinLabel(i+1)).Atoi()*1.0;
598 vxerr.push_back(0.5);
599 vy.push_back(newvalue);
600 vyerr.push_back(yerr);
604 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);
606 // FIXME : fill here an histogram from the graph to get the
608 // h->Fill(newvalue,1.0/(yerr*yerr));
609 // MC()->Adopt("/HISTOS/",h);
611 // AliAnalysisMuMuResult* r = GetRunIntegratedResult(*g,"FnormDispersion");
616 // dispersion = new AliAnalysisMuMuResult("FnormDispersion");
618 // dispersion->AdoptSubResult(r);
619 // if ( !TString(g->GetName()).BeginsWith("Fnorm") )
621 // dispersion->Exclude(r->Alias());
626 //_____________________________________________________________________________
627 void AliAnalysisMuMuFnorm::ComputePileUpGraph(ETriggerType tt, Int_t eventSelectionCorrected)
629 /// Compute the per-run graph of pile-up factor
631 TString graphName(Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(tt).Data()));
633 if ( GetGraph(graphName) )
635 // insure we're computing it only once
639 AliDebug(2,graphName);
641 std::vector<double> vx;
642 std::vector<double> vxerr;
643 std::vector<double> vy;
644 std::vector<double> vyerr;
646 const std::set<int>& runs = RunNumbers();
648 AliAnalysisTriggerScalers ts(runs,OCDBPath().Data());
650 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
652 Int_t runNumber = *it;
654 Double_t pileUpFactor(1.0);
655 Double_t pileUpFactorError(0.0);
656 Double_t purity(1.0);
657 Double_t purityError(0.0);
659 TString triggerClassName = GetTriggerClassName(tt,runNumber);
661 if ( triggerClassName.Length()==0 )
663 AliError(Form("Unknown trigger type %d",tt));
667 if (eventSelectionCorrected)
669 GetPurity(triggerClassName.Data(),runNumber,purity,purityError,eventSelectionCorrected);
671 ts.GetPileUpFactor(runNumber,triggerClassName.Data(),purity,pileUpFactor,pileUpFactorError);
673 vx.push_back(runNumber);
674 vxerr.push_back(0.5);
675 vy.push_back(pileUpFactor);
676 vyerr.push_back(pileUpFactorError);
679 TString title(Form("Pile-up correction factor for trigger %s",GetTriggerTypeName(tt).Data()));
681 if (eventSelectionCorrected)
683 title += "( L0BRate corrected by event selection";
684 title += GetEventSelectionName(eventSelectionCorrected);
685 title += " accept fraction)";
688 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
691 //_____________________________________________________________________________
692 void AliAnalysisMuMuFnorm::ComputeEventSelectionGraph(ETriggerType tt, Int_t eventSelectionCorrected)
694 /// Compute the per-run graph of physics selection accept fraction
695 /// for the given trigger
697 TString graphName(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(), GetTriggerTypeName(tt).Data()));
699 if (GetGraph(graphName))
701 // insure we're computing it only once
705 AliDebug(2,graphName);
707 std::vector<double> vx;
708 std::vector<double> vxerr;
709 std::vector<double> vy;
710 std::vector<double> vyerr;
712 const std::set<int>& runs = RunNumbers();
714 AliAnalysisTriggerScalers ts(runs,OCDBPath().Data());
716 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
718 Int_t runNumber = *it;
720 Double_t purity, purityError;
722 TString triggerClassName = GetTriggerClassName(tt,runNumber);
724 if ( triggerClassName.Length()==0 )
726 AliError(Form("Unknown trigger type %d",tt));
730 GetPurity(triggerClassName.Data(),runNumber,purity,purityError,eventSelectionCorrected);
732 vx.push_back(runNumber);
733 vxerr.push_back(0.5);
734 vy.push_back(purity);
735 vyerr.push_back(purityError);
738 TString title(Form("Fraction of events accepted by the event selection %s for trigger %s",GetTriggerTypeName(tt).Data(),
739 GetEventSelectionName(eventSelectionCorrected).Data()));
741 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
745 //_____________________________________________________________________________
746 void AliAnalysisMuMuFnorm::ComputeResultsFromGraphs()
748 // Compute one single value for each graph, by weighting by the fraction
749 // of events in each run
750 // do this for certain groups of graphs
753 groups.SetOwner(kTRUE);
755 groups.Add(new TObjString("Fnorm"));
756 groups.Add(new TObjString("NMBeq"));
757 groups.Add(new TObjString("Correction"));
758 groups.Add(new TObjString("RelDif"));
760 TList* objectList = MC()->CreateListOfObjectNames("/GRAPHS/");
762 TIter nextGroup(&groups);
765 TIter next(objectList);
766 TObjString* str(0x0);
768 while ( ( grp = static_cast<TObjString*>(nextGroup()) ) )
770 TString oname(Form("/RESULTS/%s",grp->String().Data()));
772 if ( MC()->GetObject(oname) )
774 // delete if we have it already so we can replace it
778 AliAnalysisMuMuResult* result = new AliAnalysisMuMuResult(grp->String());
780 MC()->Adopt("/RESULTS/",result);
784 while ( ( str = static_cast<TObjString*>(next()) ) )
786 if ( ! ( str->String().BeginsWith(grp->String() ) ) ) continue;
788 TGraphErrors* g = GetGraph(str->String());
792 AliAnalysisMuMuResult* sub = GetRunIntegratedResult(*g);
796 AliError(Form("Could not get result for graph %s",g->GetName()));
800 result->AdoptSubResult(sub);
808 //_____________________________________________________________________________
809 void AliAnalysisMuMuFnorm::ComputeNofEvents(ETriggerType triggerType,
810 Bool_t pileUpCorrected,
811 Int_t eventSelectionCorrected)
813 /// Compute trigger fractions
815 TString graphName(Form("NofEvent%s%s%s",GetTriggerTypeName(triggerType).Data(),
816 pileUpCorrected ? "PU" : "",
817 GetEventSelectionName(eventSelectionCorrected).Data()));
819 if ( GetGraph(graphName) )
821 // compute it only once
825 ComputeCorrectionFactors(eventSelectionCorrected);
827 TString gpsname(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(triggerType).Data()));
828 TString gpuname(Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(), GetTriggerTypeName(triggerType).Data()));
830 TGraphErrors* gPS = GetGraph(gpsname);
834 AliError(Form("Could not find %s",gpsname.Data()));
838 TGraphErrors* gPU = GetGraph(gpuname);
842 AliError(Form("Could not find %s",gpuname.Data()));
846 AliDebug(2,graphName);
848 std::vector<double> vx;
849 std::vector<double> vxerr;
850 std::vector<double> vy;
851 std::vector<double> vyerr;
853 const std::set<int>& runs = RunNumbers();
857 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
859 Int_t runNumber = *it;
861 TString triggerClassName = GetTriggerClassName(triggerType,runNumber);
863 if ( triggerClassName.Length() )
865 Double_t n = GetSum(triggerClassName,runNumber,0);
867 vx.push_back(runNumber);
868 vxerr.push_back(0.5);
870 assert(runNumber==TMath::Nint(gPU->GetX()[i]));
878 if ( pileUpCorrected )
881 e1 = gPU->GetEY()[i];
884 if ( eventSelectionCorrected > 0 )
887 e2 = gPS->GetEY()[i];
892 AliDebug(2,Form("RUN %09d n %e y1 %e y2 %e y% e",runNumber,n,y1,y2,y));
894 Double_t yerr = y*AliAnalysisMuMuResult::ErrorABC( n, TMath::Sqrt(n),
899 vyerr.push_back(yerr);
905 TString title(Form("Number of event of trigger %s",GetTriggerTypeName(triggerType).Data()));
907 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
910 //_____________________________________________________________________________
911 void AliAnalysisMuMuFnorm::ComputeTriggerFractions(ETriggerType triggerType,
912 Bool_t physicsSelectionCorrected)
914 /// Compute trigger fractions
916 TString graphName(Form("Fractions%s%s",GetTriggerTypeName(triggerType).Data(),physicsSelectionCorrected ? "PS" : ""));
918 if ( GetGraph(graphName) )
920 // compute it only once
924 AliDebug(2,graphName);
926 std::vector<double> vx;
927 std::vector<double> vxerr;
928 std::vector<double> vy;
929 std::vector<double> vyerr;
931 const std::set<int>& runs = RunNumbers();
935 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
937 Int_t runNumber = *it;
939 TString triggerClassName = GetTriggerClassName(triggerType,runNumber);
941 if ( triggerClassName.Length() )
943 n += GetSum(triggerClassName,runNumber,physicsSelectionCorrected);
949 AliWarning(Form("Got zero trigger for %s",GetTriggerTypeName(triggerType).Data()));
953 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
955 Int_t runNumber = *it;
957 TString triggerClassName = GetTriggerClassName(triggerType,runNumber);
959 vx.push_back(runNumber);
960 vxerr.push_back(0.5);
961 Double_t y = GetSum(triggerClassName,runNumber,physicsSelectionCorrected);
963 vyerr.push_back( (y/n) * AliAnalysisMuMuResult::ErrorAB( y,TMath::Sqrt(y),
968 TString title(Form("Fraction of event of trigger %s",GetTriggerTypeName(triggerType).Data()));
970 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
973 //_____________________________________________________________________________
974 void AliAnalysisMuMuFnorm::ComputeTriggerL0B(ETriggerType triggerType)
976 /// Compute trigger L0B
978 std::vector<double> vx;
979 std::vector<double> vxerr;
980 std::vector<double> vy;
981 std::vector<double> vyerr;
983 TString graphName(Form("L0B%s",GetTriggerTypeName(triggerType).Data()));
985 if ( GetGraph(graphName) )
987 // insure we're computing it only once
991 AliDebug(2,graphName);
993 const std::set<int>& runs = RunNumbers();
995 AliAnalysisTriggerScalers ts(runs,OCDBPath().Data());
997 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
999 Int_t runNumber = *it;
1001 TString triggerClassName = GetTriggerClassName(triggerType,runNumber);
1003 AliAnalysisTriggerScalerItem* item = ts.GetTriggerScaler(runNumber,"L0B",triggerClassName);
1004 if (!item) continue;
1006 vx.push_back(runNumber);
1007 vxerr.push_back(0.5);
1009 Double_t y = item->Value();
1013 vyerr.push_back( TMath::Sqrt(y) );
1016 TString title(Form("L0B of trigger %s",GetTriggerTypeName(triggerType).Data()));
1018 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
1021 ////_____________________________________________________________________________
1022 //void AliAnalysisMuMuFnorm::ComputeTSGraph(ETriggerType tt)
1024 // /// Compute the per-run graph of physics selection accept fraction x track
1025 // /// accept fraction for the given trigger
1027 // TString graphName(Form("CorrectionTS%s",GetTriggerTypeName(tt).Data()));
1029 // if (GetGraph(graphName))
1031 // // insure we're computing it only once
1035 // AliDebug(1,graphName);
1037 // std::vector<double> vx;
1038 // std::vector<double> vxerr;
1039 // std::vector<double> vy;
1040 // std::vector<double> vyerr;
1042 // const std::set<int>& runs = RunNumbers();
1044 // AliAnalysisTriggerScalers ts(runs,OCDBPath().Data());
1046 // for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
1048 // Int_t runNumber = *it;
1050 // Double_t purity, purityError;
1052 // TString triggerClassName = GetTriggerClassName(tt,runNumber);
1054 // if ( triggerClassName.Length()==0 )
1056 // AliError(Form("Unknown trigger type %d",tt));
1060 // GetPurity(triggerClassName.Data(),runNumber,purity,purityError,"OFFLINE1");
1062 // vx.push_back(runNumber);
1063 // vxerr.push_back(0.5);
1064 // vy.push_back(purity);
1065 // vyerr.push_back(purityError);
1068 // TString title(Form("Fraction of events accepted by the physics selection x track selection for trigger %s",GetTriggerTypeName(tt).Data()));
1070 // CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
1074 //_____________________________________________________________________________
1075 TGraphErrors* AliAnalysisMuMuFnorm::CreateAndAddGraph(const TString& name,
1076 const TString& title,
1077 const std::vector<double>& vx,
1078 const std::vector<double>& vxerr,
1079 const std::vector<double>& vy,
1080 const std::vector<double>& vyerr) const
1082 /// Creates a graph and adds it to our mergeable collection
1084 TGraphErrors* g = new TGraphErrors(vx.size(),&vx[0],&vy[0],&vxerr[0],&vyerr[0]);
1085 g->SetName(name.Data());
1086 g->SetTitle(title.Data());
1088 if (fIsCompactGraphs)
1090 AliAnalysisMuMuGraphUtil::Compact(*g);
1093 g->GetXaxis()->SetNoExponent();
1094 // g->GetXaxis()->SetTitle("Run number");
1096 TPaveText* text = new TPaveText(0.70,0.70,0.89,0.89,"NDC");
1097 text->SetBorderSize(0);
1098 text->SetFillColor(0);
1099 text->AddText(Form("Mean %e",g->GetMean(2)));
1100 text->AddText(Form("RMS %e",g->GetRMS(2)));
1101 g->GetListOfFunctions()->Add(text);
1103 MC()->Adopt("/GRAPHS/",g);
1107 //_____________________________________________________________________________
1108 AliMergeableCollection* AliAnalysisMuMuFnorm::DetachMC()
1110 // let go the ownership of our mergeable collection
1112 return fMergeableCollection;
1115 //_____________________________________________________________________________
1116 void AliAnalysisMuMuFnorm::DrawWith2Scales(const char* graphName1, const char* graphName2)
1118 TGraphErrors* g1 = static_cast<TGraphErrors*>(GetGraph(graphName1)->Clone());
1119 TGraphErrors* g2 = static_cast<TGraphErrors*>(GetGraph(graphName2)->Clone());
1123 gStyle->SetOptTitle(0);
1125 AliAnalysisMuMuGraphUtil gu;
1127 TCanvas* c = gu.DrawWith2Scales(*g1,*g2);
1130 for ( Int_t i = 0; i < 2; ++i )
1133 gPad->SetLeftMargin(0.15);
1134 gPad->SetRightMargin(0.15);
1139 // TGraphErrors* g = new TGraphErrors(g1->GetN());
1141 // Double_t check(0.0);
1143 // for ( Int_t i = 0; i < g->GetN(); ++i )
1145 // Double_t y = g1->GetY()[i]*g2->GetY()[i];
1147 // check += g2->GetY()[i];
1149 // g->SetPoint(i,g2->GetX()[i],y);
1150 // g->SetPointError(i,g2->GetEX()[i],
1151 // y*AliAnalysisMuMuResult::ErrorAB(g1->GetY()[i],g1->GetEY()[i],
1152 // g2->GetY()[i],g2->GetEY()[i]));
1159 // AliInfo(Form("check: %e g mean %e rms %e",check,g->GetMean(2),g->GetRMS(2)));
1165 TGraphErrors* g = new TGraphErrors(g1->GetN());
1167 for ( Int_t i = 0; i < g->GetN(); ++i )
1169 g->SetPoint(i,g2->GetY()[i],g1->GetY()[i]);
1170 g->SetPointError(i,g2->GetEY()[i],g1->GetEY()[i]);
1177 AliInfo(Form("g mean %e rms %e",g->GetMean(2),g->GetRMS(2)));
1185 //_____________________________________________________________________________
1186 TString AliAnalysisMuMuFnorm::GetEventSelectionName(Int_t eventSelectionCorrected) const
1188 if ( eventSelectionCorrected == 1 )
1192 else if ( eventSelectionCorrected == 2 )
1199 //_____________________________________________________________________________
1200 TGraphErrors* AliAnalysisMuMuFnorm::GetGraph(const char* name) const
1202 // shortcut method to give access to one graph
1204 TObject* o = MC()->GetObject(Form("/GRAPHS/%s",name));
1208 if ( o->IsA() != TGraphErrors::Class() )
1210 AliError(Form("Object %s is not of the expected type",o->GetName()));
1214 return static_cast<TGraphErrors*>(o);
1217 //_____________________________________________________________________________
1218 void AliAnalysisMuMuFnorm::GetPurity(const char* triggerClassName, Int_t runNumber,
1219 Double_t& value, Double_t& error, Int_t eventSelectionCorrected) const
1221 /// Get the physics selection accept fraction for a given trigger
1225 TString runCondition;
1229 runCondition.Form("/run:%d",runNumber);
1232 Double_t nall = fCounterCollection.GetSum(Form("trigger:%s/event:ALL%s",triggerClassName,runCondition.Data()));
1236 if ( eventSelectionCorrected == 1 )
1240 else if ( eventSelectionCorrected == 2 )
1250 Double_t nps = fCounterCollection.GetSum(Form("trigger:%s/event:%s%s",
1251 triggerClassName,ename.Data(),runCondition.Data()));
1253 if ( nall <= 0.0 ) return;
1257 error = AliAnalysisMuMuResult::ErrorAB(nall,TMath::Sqrt(nall),nps,TMath::Sqrt(nps));
1260 //_____________________________________________________________________________
1261 AliAnalysisMuMuResult* AliAnalysisMuMuFnorm::GetResult(const char* name) const
1263 // shortcut method to give access to one result
1265 TObject* o = MC()->GetObject(Form("/RESULTS/%s",name));
1269 if ( o->IsA() != AliAnalysisMuMuResult::Class() )
1271 AliError(Form("Object %s is not of the expected type",o->GetName()));
1275 return static_cast<AliAnalysisMuMuResult*>(o);
1278 //______________________________________________________________________________
1279 AliAnalysisMuMuResult* AliAnalysisMuMuFnorm::GetRunIntegratedResult(const TGraphErrors& g, const char* basename)
1281 /// get one value +- error for this graph (weighting the run-by-run values
1282 /// by the fraction of the number of triggers in that run)
1283 /// also the rms is computed.
1285 Bool_t physicsSelectionCorrected(kFALSE);
1287 if ( TString(g.GetName()).Contains("PS") )
1289 physicsSelectionCorrected=kTRUE;
1292 ComputeTriggerFractions(fReferenceTriggerType,physicsSelectionCorrected);
1294 TString fname(Form("Fractions%s%s",GetTriggerTypeName(fReferenceTriggerType).Data(),physicsSelectionCorrected ? "PS" : ""));
1296 TGraphErrors* gTriggerFractions = GetGraph(fname);
1298 StdoutToAliDebug(2,std::cout << g.GetName() << std::endl; g.Print(););
1300 if (!gTriggerFractions)
1302 AliError(Form("Did not find graph for %s",fname.Data()));
1306 Double_t mean = g.GetY()[0];
1309 Double_t errorOnMean = g.GetEY()[0];
1314 mean = errorOnMean = 0.0;
1319 for ( Int_t i = 0; i < n; ++i )
1321 Double_t y = g.GetY()[i];
1323 Double_t weight = gTriggerFractions->GetY()[i]; // sum of weight should be 1.0
1325 AliDebug(2,Form("%s i %3d y %e weight %e",g.GetName(),i,y,weight));
1330 v2 += weight*weight;
1335 for ( Int_t i = 0; i < n; ++i )
1337 Double_t weight = gTriggerFractions->GetY()[i]; // sum of weight should be 1.0
1338 Double_t y = g.GetY()[i];
1340 d += (y-mean)*(y-mean)*weight;
1343 AliDebug(2,Form("v1=%e v2=%e d=%e",v1,v2,d));
1345 if ( v1 <= 0) return 0x0;
1347 errorOnMean = TMath::Sqrt((1.0/v1)*(1.0/(n-1))*d);
1349 rms = TMath::Sqrt( (v1/(v1*v1-v2))*d );
1352 AliAnalysisMuMuResult* result = new AliAnalysisMuMuResult(g.GetName(),g.GetTitle());
1354 result->Set(basename,mean,errorOnMean,rms);
1356 if ( TString(g.GetName()) == "FnormScalersPUPS" )
1358 AliDebug(1,Form("mean %e errorOnMean %e rms %e",mean,errorOnMean,rms));
1359 StdoutToAliDebug(1,result->Print("full"));
1365 //_____________________________________________________________________________
1366 Double_t AliAnalysisMuMuFnorm::GetSum(const char* triggerClassName,
1368 Int_t eventSelectionCorrected) const
1370 TString condition(Form("trigger:%s/run:%d",triggerClassName,runNumber));
1372 if (eventSelectionCorrected==1)
1374 condition += "/event:PSALL";
1376 else if ( eventSelectionCorrected == 2 )
1378 condition += "/event:OFFLINE1";
1382 condition += "/event:ALL";
1385 Double_t n = fCounterCollection.GetSum(condition.Data());
1389 AliError(Form("Got no count for %s for run %d (physicsSelected:%d)",triggerClassName,runNumber,eventSelectionCorrected));
1396 //_____________________________________________________________________________
1397 TString AliAnalysisMuMuFnorm::GetTriggerClassName(ETriggerType tt, Int_t runNumber) const
1399 // get the triggerclass to for a given trigger type and run number
1403 return MBTriggerClassName(runNumber);
1405 else if ( tt == kMUL )
1407 return MULTriggerClassName(runNumber);
1409 else if ( tt == kMSL)
1411 return MSLTriggerClassName(runNumber);
1413 else if ( tt == kMSH)
1415 return MSHTriggerClassName(runNumber);
1420 //_____________________________________________________________________________
1421 TString AliAnalysisMuMuFnorm::GetTriggerTypeName(ETriggerType tt) const
1423 // get the name of the trigger type
1428 else if ( tt == kMUL )
1432 else if ( tt == kMSL)
1436 else if ( tt == kMSH)
1443 //_____________________________________________________________________________
1444 void AliAnalysisMuMuFnorm::GetValueAndErrorFromGraph(TGraphErrors* graph,
1447 Double_t& error) const
1449 /// get (value,error) corresponding to run=runNumber.
1450 /// Works both for compact and non-compact graphs
1452 value = TMath::Limits<Double_t>::Max();
1457 TAxis* axis = graph->GetXaxis();
1459 for ( Int_t i = 0; i < graph->GetN(); ++i )
1461 Int_t rbin = TMath::Nint(graph->GetX()[i]);
1462 Int_t rlabel = TString(axis->GetBinLabel(i+1)).Atoi();
1463 if ( rbin == runNumber || rlabel == runNumber )
1465 value = graph->GetY()[i];
1466 error = graph->GetEY()[i];
1471 //_____________________________________________________________________________
1472 AliMergeableCollection* AliAnalysisMuMuFnorm::MC() const
1474 // get our mergeable collection
1475 if (!fMergeableCollection)
1477 fMergeableCollection = new AliMergeableCollection("Fnorm",Form("MB to %s trigger normalization results",GetTriggerTypeName(fReferenceTriggerType).Data()));
1479 return fMergeableCollection;
1482 //_____________________________________________________________________________
1483 TString AliAnalysisMuMuFnorm::MBTriggerClassName(Int_t runNumber) const
1485 /// FIXME : find a better way ?
1487 if ( TriggerClassnameTest("CINT7-B-NOPF-ALLNOTRD",runNumber) )
1489 return "CINT7-B-NOPF-ALLNOTRD";
1494 //_____________________________________________________________________________
1495 TString AliAnalysisMuMuFnorm::MSHTriggerClassName(Int_t runNumber) const
1497 /// FIXME : find a better way ?
1499 if ( TriggerClassnameTest("CMSH7-B-NOPF-ALLNOTRD",runNumber) )
1501 return "CMSH7-B-NOPF-ALLNOTRD";
1503 else if ( TriggerClassnameTest("CMSH7-B-NOPF-MUON",runNumber) )
1505 return "CMSH7-B-NOPF-MUON";
1510 //_____________________________________________________________________________
1511 TString AliAnalysisMuMuFnorm::MSLTriggerClassName(Int_t runNumber) const
1513 /// FIXME : find a better way ?
1515 if ( TriggerClassnameTest("CMSL7-B-NOPF-MUON",runNumber) )
1517 return "CMSL7-B-NOPF-MUON";
1520 // if ( TriggerClassnameTest("CMSL7-B-NOPF-ALLNOTRD",runNumber) )
1522 // return "CMSL7-B-NOPF-ALLNOTRD";
1527 //_____________________________________________________________________________
1528 void AliAnalysisMuMuFnorm::MultiplyGraphs(const char* g1name, const char* g2name, const char* name)
1530 /// Make a new graph = g1*g2
1531 std::vector<double> vx;
1532 std::vector<double> vy;
1533 std::vector<double> vxerr;
1534 std::vector<double> vyerr;
1536 TGraphErrors* g1 = GetGraph(g1name);
1537 TGraphErrors* g2 = GetGraph(g2name);
1541 AliError(Form("Could not get graph %s",g1name));
1547 AliError(Form("Could not get graph %s",g2name));
1551 if ( g1->GetN() != g2->GetN() )
1553 AliError(Form("Could not multiply incompatible graphs %d pts vs %d pts",g1->GetN(),g2->GetN()));
1557 for ( Int_t i = 0; i < g1->GetN(); ++i )
1559 if ( g1->GetX()[i] != g2->GetX()[i] )
1561 AliError(Form("Incompatible bin %d : %e vs %e",i,g1->GetX()[i],g2->GetX()[i]));
1565 vx.push_back(g1->GetX()[i]);
1566 vxerr.push_back(g1->GetEX()[i]);
1568 Double_t y = g1->GetY()[i]*g2->GetY()[i];
1569 Double_t yerr = y*AliAnalysisMuMuResult::ErrorAB( g1->GetY()[i], g1->GetEY()[i],
1570 g2->GetY()[i], g2->GetEY()[i]);
1573 vyerr.push_back(yerr);
1576 TString gname(name);
1578 if ( gname.Length() == 0 )
1580 gname = g1->GetName();
1582 gname += g2->GetName();
1585 TString title(Form("Product of %s by %s",g1->GetName(),g2->GetName()));
1587 CreateAndAddGraph(gname,title,vx,vxerr,vy,vyerr);
1590 //_____________________________________________________________________________
1591 TString AliAnalysisMuMuFnorm::MULTriggerClassName(Int_t runNumber) const
1593 /// FIXME : find a better way ?
1595 if ( TriggerClassnameTest("CMUL7-B-NOPF-ALLNOTRD",runNumber) )
1597 return "CMUL7-B-NOPF-ALLNOTRD";
1599 else if ( TriggerClassnameTest("CMUL7-B-NOPF-MUON",runNumber) )
1601 return "CMUL7-B-NOPF-MUON";
1607 //_____________________________________________________________________________
1608 void AliAnalysisMuMuFnorm::Print(Option_t* opt) const
1610 if ( fMergeableCollection )
1612 fMergeableCollection->Print(opt);
1616 //_____________________________________________________________________________
1617 std::set<int> AliAnalysisMuMuFnorm::RunNumbers() const
1619 // Extract the run numbers from our counter collection
1621 std::set<int> runset;
1623 TString sruns = fCounterCollection.GetKeyWords("run");
1624 TObjArray* runs = sruns.Tokenize(",");
1629 while ( ( s = static_cast<TObjString*>(next())) )
1631 runset.insert(s->String().Atoi());
1638 //_____________________________________________________________________________
1639 void AliAnalysisMuMuFnorm::ScalerFnorm(Double_t& value, Double_t& error,
1640 Double_t L0bREF, Double_t purityREF, Double_t purityREFerror,
1641 Double_t L0bMB, Double_t purityMB, Double_t purityMBerror,
1642 Double_t pileUpFactor, Double_t pileUpFactorError)
1644 /// Compute the MB to CMUL ratio and its associated error
1646 value = error = 0.0;
1648 value = L0bREF*purityREF;
1652 value = L0bMB*purityMB*pileUpFactor/value;
1654 error = value*AliAnalysisMuMuResult::ErrorABCDE(L0bREF,TMath::Sqrt(L0bREF),
1655 purityREF,purityREFerror,
1656 L0bMB,TMath::Sqrt(L0bMB),
1657 purityMB,purityMBerror,
1658 pileUpFactor,pileUpFactorError);
1661 //_____________________________________________________________________________
1662 void AliAnalysisMuMuFnorm::ShowFnorm(const TObjArray& a) const
1664 /// Print and plot Fnorm values
1668 while ( ( g = static_cast<TGraphErrors*>(next()) ) )
1670 g->SetTitle(Form("Fnorm %s",g->GetTitle()));
1672 new TCanvas(Form("c%s",g->GetName()));
1674 if (fIsCompactGraphs)
1676 AliAnalysisMuMuGraphUtil::Compact(*g);
1680 g->GetXaxis()->SetNoExponent();
1687 for ( Int_t i = 0; i < g->GetN(); ++i )
1690 Double_t e = ( y != 0.0 ? g->GetEY()[i]/y : 0.0);
1696 yerr = TMath::Sqrt(yerr)*y;
1698 AliInfo(Form("%30s graph %e +- %e (%5.2f %%) RMS %e",g->GetName(),
1699 y,yerr,yerr*100/y,g->GetRMS(2)));
1704 //_____________________________________________________________________________
1705 Bool_t AliAnalysisMuMuFnorm::TriggerClassnameTest(const char* triggerClassName, Int_t runNumber) const
1707 /// Check if we have counts for that trigger,run combination
1709 TString runs = fCounterCollection.GetKeyWords("run");
1711 if ( !runs.Contains(Form("%d",runNumber)) ) return kFALSE;
1713 TString triggers = fCounterCollection.GetKeyWords("trigger");
1715 if (!triggers.Contains(triggerClassName)) return kFALSE;
1717 Double_t n = fCounterCollection.GetSum(Form("trigger:%s/run:%d",triggerClassName,runNumber));
1722 //_____________________________________________________________________________
1724 AliAnalysisMuMuFnorm::WeightedMeanGraphs(const char* patternOrList, const char* graphName)
1726 /// Sum the graphs which name matches pattern
1727 /// Sum is made using a weighted mean (each element is weighted by the inverse
1728 /// of its error squared)
1730 TString spattern(patternOrList);
1731 TObjArray* slist(0x0);
1733 if ( spattern.CountChar(',') )
1735 // it's not a pattern but a list...
1736 slist = spattern.Tokenize(",");
1740 TList* objectList = MC()->CreateListOfObjectNames("/GRAPHS/");
1741 TIter next(objectList);
1742 TObjString* str(0x0);
1744 selected.SetOwner(kFALSE);
1746 while ( ( str = static_cast<TObjString*>(next()) ) )
1748 TGraphErrors* g = GetGraph(str->String());
1752 TString name(g->GetName());
1754 if ( spattern.Length() >0 && !name.Contains(spattern.Data()) ) continue;
1756 if ( slist && !slist->FindObject(name)) continue;
1758 AliDebug(2,Form("Selected for sum : %s",name.Data()));
1766 if (selected.GetLast()<0) return;
1768 std::vector<double> vx;
1769 std::vector<double> vy;
1770 std::vector<double> vxerr;
1771 std::vector<double> vyerr;
1773 Int_t npts = static_cast<TGraphErrors*>(selected.First())->GetN();
1775 for ( Int_t ipoint = 0; ipoint < npts; ++ipoint )
1777 Double_t x,xref,xerr;
1779 Double_t sume2(0.0);
1781 for ( Int_t igraph = 0; igraph <= selected.GetLast(); ++igraph )
1783 TGraphErrors* g = static_cast<TGraphErrors*>(selected.At(igraph));
1785 if ( g->GetN() != npts )
1787 AliError(Form("Graph %s does not have the expected %d points",g->GetName(),npts));
1792 if ( fIsCompactGraphs )
1794 runNumber = TString(g->GetXaxis()->GetBinLabel(ipoint+1)).Atoi()*1.0;
1798 runNumber = g->GetX()[ipoint];
1803 xref = g->GetX()[ipoint];
1805 xerr = g->GetEX()[ipoint];
1809 if ( xref != g->GetX()[ipoint] )
1811 AliError(Form("Cannot sum graphs with different axis : get %e and expected %e : %s vs %s",xref,x,selected.At(0)->GetName(),g->GetName()));
1816 Double_t e2 = g->GetEY()[ipoint]*g->GetEY()[ipoint];
1820 sum += g->GetY()[ipoint]/e2;
1828 vxerr.push_back(xerr);
1829 vy.push_back(sum/sume2);
1830 vyerr.push_back(TMath::Sqrt(1/sume2));
1834 Int_t n = selected.GetEntries();
1836 TString name(graphName);
1837 TString title(Form("Weighted mean from %d individual graphs",n));
1839 if ( strlen(graphName) == 0)
1841 name = TString::Format("WeightMeanFnorm%s",patternOrList);
1842 name.ReplaceAll(",","_");
1843 title = TString::Format("WeightMeanFnorm%s from %d individual graphs",patternOrList,n);
1846 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);