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 REF 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),
66 fIsCompactGraphs(compactGraphs),
67 fReferenceTriggerType(refTriggerType)
74 //_____________________________________________________________________________
75 AliAnalysisMuMuFnorm::~AliAnalysisMuMuFnorm()
80 delete fMergeableCollection;
84 //_____________________________________________________________________________
85 void AliAnalysisMuMuFnorm::ComputeFnorm()
87 /// Compute the REF to CINT ratio(s)
89 /// Using offline method
90 /// - in one go CINT/REF
91 /// - in two steps CINT/CMSL and CMSL/REF
93 /// Using scaler method
94 /// - bare scaler values
95 /// - scaler values corrected for pile-up
96 /// - scaler values corrected for pile-up and physics selection
98 const ETriggerType triggerTypes[] = { kMB, kMUL, kMSL, kMSH };
99 const Bool_t trueFalse[] = { kTRUE, kFALSE };
101 for ( Int_t i = 0; i < 4; ++i )
103 for ( Int_t pileup = 0; pileup < 2; ++pileup )
105 for ( Int_t ps = 0; ps < 2; ++ps )
107 ComputeNofEvents(triggerTypes[i],trueFalse[pileup],ps);
112 ComputeFnormOffline(1,kFALSE,0);
113 ComputeFnormOffline(1,kFALSE,1);
114 ComputeFnormOffline(1,kTRUE,1);
116 ComputeFnormOffline(2,kFALSE,0);
117 ComputeFnormOffline(2,kFALSE,1);
118 ComputeFnormOffline(2,kTRUE,1);
120 // ComputeFnormOffline(2,kFALSE,2);
121 // ComputeFnormOffline(2,kTRUE,2);
123 ComputeFnormScalers(kFALSE,0);
124 ComputeFnormScalers(kTRUE,0);
125 ComputeFnormScalers(kTRUE,1);
126 // ComputeFnormScalers(kTRUE,2);
128 WeightedMeanGraphs("Offline");
129 WeightedMeanGraphs("Scalers");
130 WeightedMeanGraphs("FnormOffline2PUPS,FnormOffline1PUPS","FnormOffline12PUPS");
132 WeightedMeanGraphs("FnormOffline2PUPS,FnormScalersPUPS","FnormBest2");
134 ComputeGraphRelDif("FnormOffline2PUPS","FnormScalersPUPS");
136 ComputeGraphRelDif("FnormOffline2PUPS","FnormOffline2");
137 ComputeGraphRelDif("FnormOffline2PUPS","FnormOffline2PS");
139 ComputeGraphRelDif("CorrectionPSMB","CorrectionPSREF");
141 // for ( Int_t i = 0; i < 4; ++i )
143 TString triggerEvents;
145 // triggerEvents.Form("NofEvent%sPUPS",GetTriggerTypeName(triggerTypes[i]).Data());
146 triggerEvents.Form("NofEvent%sPUPS",GetTriggerTypeName(fReferenceTriggerType).Data());
148 MultiplyGraphs(triggerEvents.Data(),"FnormBest2","NMBeqBest2");
150 MultiplyGraphs(triggerEvents.Data(),"FnormOffline2PUPS","NMBeqOffline2PUPS");
151 MultiplyGraphs(triggerEvents.Data(),"FnormScalersPUPS","NMBeqScalersPUPS");
154 // MultiplyGraphs(Form("NofEvent%sPUTS",GetTriggerTypeName(fReferenceTriggerType).Data()),"FnormOffline2PUTS","NMBeqOffline2PUTS");
155 // MultiplyGraphs(Form("NofEvent%sPUTS",GetTriggerTypeName(fReferenceTriggerType).Data()),"FnormOffline2TS","NMBeqOffline2TS");
157 ComputeResultsFromGraphs();
159 AliAnalysisMuMuResult* result = GetResult("Fnorm");
162 result->Exclude("*");
163 result->Include("FnormBest2");
167 //_____________________________________________________________________________
168 void AliAnalysisMuMuFnorm::ComputeCorrectionFactors(Int_t eventSelectionCorrected)
170 /// Compute individual graphs for the correction factors (PS_REF, PS_CINT,
171 /// F_pile-up,PS_CINT/PS_REF) used in the computation of (some) Fnorm factors
174 TString graphName(Form("CorrectionGlobal%s",GetEventSelectionName(eventSelectionCorrected).Data()));;
176 if ( GetGraph(graphName) )
178 // insure we compute it only once
184 std::vector<double> vx;
185 std::vector<double> vxerr;
186 std::vector<double> vy;
187 std::vector<double> vyerr;
189 std::vector<double> vyGlobal;
190 std::vector<double> vyGlobalErr;
192 const ETriggerType triggerTypes[] = { kMB, kMUL, kMSL, kMSH };
194 for ( Int_t i = 0; i < 4; ++i )
196 ComputeEventSelectionGraph(triggerTypes[i],eventSelectionCorrected);
197 ComputePileUpGraph(triggerTypes[i],eventSelectionCorrected);
200 TGraphErrors* gPSCINT = GetGraph(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(AliAnalysisMuMuFnorm::kMB).Data()));
202 TGraphErrors* gPSREF = GetGraph(Form("Correction%s%s", GetEventSelectionName(eventSelectionCorrected).Data(), GetTriggerTypeName(fReferenceTriggerType).Data()));
204 TGraphErrors* gPU = GetGraph(Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(), GetTriggerTypeName(AliAnalysisMuMuFnorm::kMB).Data()));
206 if ( !gPSCINT || !gPSREF || !gPU )
208 AliError("Did not get the relevant graphs. Cannot work");
212 for ( Int_t i = 0; i < gPSCINT->GetN(); ++i )
214 Double_t x,y,yerr,yGlobal,yGlobalErr;
216 gPSCINT->GetPoint(i,x,y);
218 if ( fIsCompactGraphs )
220 x = TString(gPSCINT->GetXaxis()->GetBinLabel(i)).Atoi();
223 yGlobal = gPSCINT->GetY()[i] * gPU->GetY()[i] / gPSREF->GetY()[i];
225 yGlobalErr = yGlobal*AliAnalysisMuMuResult::ErrorABC(gPSCINT->GetY()[i],gPSCINT->GetEY()[i],
226 gPSREF->GetY()[i],gPSREF->GetEY()[i],
227 gPU->GetY()[i],gPU->GetEY()[i]);
229 y = gPSCINT->GetY()[i] / gPSREF->GetY()[i];
230 yerr = y * AliAnalysisMuMuResult::ErrorAB(gPSCINT->GetY()[i],gPSCINT->GetEY()[i],
231 gPSREF->GetY()[i],gPSREF->GetEY()[i]);
234 vxerr.push_back(gPSCINT->GetEX()[i]);
236 vyGlobal.push_back(yGlobal);
237 vyGlobalErr.push_back(yGlobalErr);
240 vyerr.push_back(yerr);
243 TString name(Form("Correction%sRatio",GetEventSelectionName(eventSelectionCorrected).Data()));
244 TString title(Form("%s_MB/%s_%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(fReferenceTriggerType).Data(),
245 GetEventSelectionName(eventSelectionCorrected).Data()));
247 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);
249 title = TString::Format("%s_MB x Fpile-up / %s_%s ",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(fReferenceTriggerType).Data(),GetEventSelectionName(eventSelectionCorrected).Data());
251 CreateAndAddGraph(graphName,title,vx,vxerr,vyGlobal,vyGlobalErr);
254 //_____________________________________________________________________________
255 void AliAnalysisMuMuFnorm::ComputeFnormOffline(Int_t nstep, Bool_t pileUpCorrected, Int_t eventSelectionCorrected)
257 /// Compute MB to REF ratio using offline method, either in 1 or 2 steps
259 TString name("FnormOffline");
260 TString title("Computed using offline information");
261 TString refInput = Form("0%s",GetTriggerTypeName(fReferenceTriggerType).Data());
266 title += Form(" in one step (CINT/CINT&%s)",refInput.Data());
271 title += Form(" in two steps (CMSL/CMSL&%s x CINT/CINT&0MSL)",refInput.Data());
277 title += " with pile-up correction";
279 if (eventSelectionCorrected==1)
282 title += " with (ps) purity corrections";
284 else if ( eventSelectionCorrected==2 )
287 title += " with (ts) purity corrections";
290 if ( GetGraph(name) )
292 // insure we're computing it only once
298 std::vector<double> vx;
299 std::vector<double> vxerr;
300 std::vector<double> vy;
301 std::vector<double> vyerr;
303 const std::set<int>& runs = RunNumbers();
305 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
307 Int_t runNumber = *it;
309 TString mbTrigger = GetTriggerClassName(kMB,runNumber);
310 TString muonTrigger = GetTriggerClassName(kMSL,runNumber);
311 // TString refTrigger = GetTriggerClassName(fReferenceTriggerType,runNumber);
313 if (!mbTrigger.Length())
315 AliError(Form("Cannot get MB trigger for run %d",runNumber));
319 Double_t nofMB = GetSum(mbTrigger.Data(),runNumber,eventSelectionCorrected);
320 Double_t nofMSL(0.0);
321 Double_t nofMSLw0REF(0.0);
325 nofMSL = GetSum(muonTrigger.Data(),runNumber,eventSelectionCorrected);
326 TString counterName = muonTrigger;
327 if ( fReferenceTriggerType != kMSL ) counterName += Form("&%s",refInput.Data());
328 nofMSLw0REF = GetSum(counterName,runNumber,eventSelectionCorrected);
331 Double_t nofMBw0REF = GetSum(Form("%s&%s",mbTrigger.Data(),refInput.Data()),runNumber,eventSelectionCorrected);
332 Double_t nofMBw0MSL = GetSum(Form("%s&0MSL",mbTrigger.Data()),runNumber,eventSelectionCorrected);
334 if ( !nofMBw0REF ) continue;
335 if ( !nofMBw0MSL && nstep == 2 ) continue;
337 Double_t purityMB(1.0);
338 Double_t purityMBerror(0.0);
340 if ( eventSelectionCorrected > 0 )
342 ComputeEventSelectionGraph(kMB,eventSelectionCorrected);
344 TGraphErrors* gps = GetGraph(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(kMB).Data()));
346 GetValueAndErrorFromGraph(gps,runNumber,purityMB,purityMBerror);
349 Double_t pileUpFactor(1.0);
350 Double_t pileUpFactorError(0.0);
354 ComputePileUpGraph(kMB,eventSelectionCorrected);
356 TGraphErrors* gpu = GetGraph(Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(kMB).Data()));
358 GetValueAndErrorFromGraph(gpu,runNumber,pileUpFactor,pileUpFactorError);
360 nofMB *= pileUpFactor;
363 double value = nofMBw0REF > 0.0 ? nofMB/nofMBw0REF : 0.0;
364 double error = value*AliAnalysisMuMuResult::ErrorABC(nofMB,TMath::Sqrt(nofMB),
365 nofMBw0REF,TMath::Sqrt(nofMBw0REF),
366 pileUpFactor,pileUpFactorError);
370 value = (nofMB/nofMSLw0REF)*(nofMSL/nofMBw0MSL);
372 if ( runNumber == 196310 )
374 AliDebug(1,Form("RUN %09d %d-%d-%d value=%e nofMB %e nofMSLw%s %e nofMSL %e nofMBw0MSL %e",
375 runNumber,nstep,pileUpCorrected,eventSelectionCorrected,
376 value,nofMB,refInput.Data(),nofMSLw0REF,nofMSL,nofMBw0MSL));
379 error = value*AliAnalysisMuMuResult::ErrorABCD(nofMB,TMath::Sqrt(nofMB),
380 nofMSLw0REF,TMath::Sqrt(nofMSLw0REF),
381 nofMSL,TMath::Sqrt(nofMSL),
382 nofMBw0MSL,TMath::Sqrt(nofMBw0MSL));
387 vx.push_back(1.0*runNumber);
388 vxerr.push_back(0.5);
390 vyerr.push_back(error);
395 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);
399 //_____________________________________________________________________________
400 void AliAnalysisMuMuFnorm::ComputeFnormScalers(Bool_t pileUpCorrected,
401 Int_t eventSelectionCorrected)
403 /// Compute the MB to REF ratio using the scalers method (from OCDB)
405 /// i.e. Fnorm = L0B(MB) x PS(MB) x Fpile-up / ( L0B(REF) x PS(REF) )
407 /// where MB is the minbias trigger
408 /// REF is the fReferenceTrigger
409 /// and PS is the fraction of events selected by the physics selection
411 /// The correction factor (the two PS and one Fpile-up) are
412 /// taken from graphs computed in other methods
415 TString name("FnormScalers");
416 TString title("Computed using OCDB scalers");
421 title += " with pile-up correction";
423 if (eventSelectionCorrected==1)
426 title += " with (ps) purity corrections";
428 if (eventSelectionCorrected==2)
431 title += " with (ts) purity corrections";
434 if ( GetGraph(name) )
436 // insure we're computing it only once
442 // insure we have all the graphs we need to work
443 ComputeTriggerL0B(kMB);
444 ComputeTriggerL0B(fReferenceTriggerType);
446 const std::set<int>& runs = RunNumbers();
448 std::vector<double> vx;
449 std::vector<double> vxerr;
450 std::vector<double> vy;
451 std::vector<double> vyerr;
453 Double_t purityREF(1.0);
454 Double_t purityMB(1.0);
455 Double_t purityREFerror(00);
456 Double_t purityMBerror(0.0);
458 // compute the per run values
459 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
461 Int_t runNumber = *it;
463 TString mbTrigger = GetTriggerClassName(kMB,runNumber);
464 // TString refTrigger = GetTriggerClassName(fReferenceTriggerType,runNumber);
466 purityMB=purityREF=1.0;
467 purityMBerror=purityREFerror=0.0;
469 if (eventSelectionCorrected>0)
471 ComputeEventSelectionGraph(kMB,eventSelectionCorrected);
472 ComputeEventSelectionGraph(fReferenceTriggerType,eventSelectionCorrected);
474 TGraphErrors* gpsMB = GetGraph(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(kMB).Data()));
475 TGraphErrors* gpsREF = GetGraph(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(fReferenceTriggerType).Data()));
477 GetValueAndErrorFromGraph(gpsMB,runNumber,purityMB,purityMBerror);
478 GetValueAndErrorFromGraph(gpsREF,runNumber,purityREF,purityREFerror);
483 AliError(Form("Got purity=%e for MB for run %9d",purityMB,runNumber));
487 TGraphErrors* gl0bMB = GetGraph(Form("L0B%s",GetTriggerTypeName(kMB).Data()));
488 TGraphErrors* gl0bREF = GetGraph(Form("L0B%s",GetTriggerTypeName(fReferenceTriggerType).Data()));
490 Double_t L0bMB,L0bMBError;
491 Double_t L0bREF,L0bREFError;
493 GetValueAndErrorFromGraph(gl0bMB,runNumber,L0bMB,L0bMBError);
494 GetValueAndErrorFromGraph(gl0bREF,runNumber,L0bREF,L0bREFError);
496 Double_t pileUpFactor(1.0);
497 Double_t pileUpFactorError(0.0);
501 TGraphErrors* gpu = GetGraph((Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(kMB).Data())));
503 GetValueAndErrorFromGraph(gpu,runNumber,pileUpFactor,pileUpFactorError);
509 ScalerFnorm(value,error,
510 L0bREF,purityREF,purityREFerror,
511 L0bMB,purityMB,purityMBerror,
512 pileUpFactor,pileUpFactorError);
516 vx.push_back(1.0*runNumber);
517 vxerr.push_back(0.5);
519 vyerr.push_back(error);
523 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);
526 //_____________________________________________________________________________
527 void AliAnalysisMuMuFnorm::ComputeGraphRelDif(const char* a, const char* b) const
529 // compute dispersion of b versus a
531 // computed differences graphs are put into the GRAPHS/ directory
532 // computed differences results are put into the HISTOS/ directory
534 TString name(Form("RelDif%svs%s",b,a));
536 if ( GetGraph(name) )
538 // insure we compute it only once
544 TGraphErrors* ga = static_cast<TGraphErrors*>(MC()->GetObject(Form("/GRAPHS/%s",a)));
545 TGraphErrors* gb = static_cast<TGraphErrors*>(MC()->GetObject(Form("/GRAPHS/%s",b)));
549 AliError(Form("Cannot get graph for %s",a));
555 AliError(Form("Cannot get graph for %s",b));
559 if ( ga->GetN() != gb->GetN() )
561 AliError(Form("Cannot work with different number of points in the graphs : %d vs %d",
562 ga->GetN(),gb->GetN()));
566 TString title(Form("%s-%s (RelDif,%%)",b,a));
568 std::vector<double> vx;
569 std::vector<double> vxerr;
570 std::vector<double> vy;
571 std::vector<double> vyerr;
573 for ( Int_t i = 0; i < ga->GetN(); ++i )
575 Double_t xa,xb,ya,yb;
577 ga->GetPoint(i,xa,ya);
578 gb->GetPoint(i,xb,yb);
582 AliError(Form("Incompatible graphs : got xa=%e and xb=%e",xa,xb));
586 Double_t newvalue = 0.0;
588 if ( TMath::Abs(xa) > 1E-12 )
590 newvalue = 100.0*( yb - ya ) / ya;
593 Double_t yerr = newvalue*AliAnalysisMuMuResult::ErrorAB(ya,ga->GetEY()[i],
596 if ( fIsCompactGraphs )
598 xa = TString(ga->GetXaxis()->GetBinLabel(i+1)).Atoi()*1.0;
602 vxerr.push_back(0.5);
603 vy.push_back(newvalue);
604 vyerr.push_back(yerr);
608 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);
610 // FIXME : fill here an histogram from the graph to get the
612 // h->Fill(newvalue,1.0/(yerr*yerr));
613 // MC()->Adopt("/HISTOS/",h);
615 // AliAnalysisMuMuResult* r = GetRunIntegratedResult(*g,"FnormDispersion");
620 // dispersion = new AliAnalysisMuMuResult("FnormDispersion");
622 // dispersion->AdoptSubResult(r);
623 // if ( !TString(g->GetName()).BeginsWith("Fnorm") )
625 // dispersion->Exclude(r->Alias());
630 //_____________________________________________________________________________
631 void AliAnalysisMuMuFnorm::ComputePileUpGraph(ETriggerType tt, Int_t eventSelectionCorrected)
633 /// Compute the per-run graph of pile-up factor
635 TString graphName(Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(tt).Data()));
637 if ( GetGraph(graphName) )
639 // insure we're computing it only once
643 AliDebug(2,graphName);
645 std::vector<double> vx;
646 std::vector<double> vxerr;
647 std::vector<double> vy;
648 std::vector<double> vyerr;
650 const std::set<int>& runs = RunNumbers();
652 AliAnalysisTriggerScalers ts(runs,OCDBPath().Data());
654 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
656 Int_t runNumber = *it;
658 Double_t pileUpFactor(1.0);
659 Double_t pileUpFactorError(0.0);
660 Double_t purity(1.0);
661 Double_t purityError(0.0);
663 TString triggerClassName = GetTriggerClassName(tt,runNumber);
665 if ( triggerClassName.Length()==0 )
667 AliError(Form("Unknown trigger type %d",tt));
671 if (eventSelectionCorrected)
673 GetPurity(triggerClassName.Data(),runNumber,purity,purityError,eventSelectionCorrected);
675 ts.GetPileUpFactor(runNumber,triggerClassName.Data(),purity,pileUpFactor,pileUpFactorError);
677 vx.push_back(runNumber);
678 vxerr.push_back(0.5);
679 vy.push_back(pileUpFactor);
680 vyerr.push_back(pileUpFactorError);
683 TString title(Form("Pile-up correction factor for trigger %s",GetTriggerTypeName(tt).Data()));
685 if (eventSelectionCorrected)
687 title += "( L0BRate corrected by event selection";
688 title += GetEventSelectionName(eventSelectionCorrected);
689 title += " accept fraction)";
692 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
695 //_____________________________________________________________________________
696 void AliAnalysisMuMuFnorm::ComputeEventSelectionGraph(ETriggerType tt, Int_t eventSelectionCorrected)
698 /// Compute the per-run graph of physics selection accept fraction
699 /// for the given trigger
701 TString graphName(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(), GetTriggerTypeName(tt).Data()));
703 if (GetGraph(graphName))
705 // insure we're computing it only once
709 AliDebug(2,graphName);
711 std::vector<double> vx;
712 std::vector<double> vxerr;
713 std::vector<double> vy;
714 std::vector<double> vyerr;
716 const std::set<int>& runs = RunNumbers();
718 AliAnalysisTriggerScalers ts(runs,OCDBPath().Data());
720 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
722 Int_t runNumber = *it;
724 Double_t purity, purityError;
726 TString triggerClassName = GetTriggerClassName(tt,runNumber);
728 if ( triggerClassName.Length()==0 )
730 AliError(Form("Unknown trigger type %d",tt));
734 GetPurity(triggerClassName.Data(),runNumber,purity,purityError,eventSelectionCorrected);
736 vx.push_back(runNumber);
737 vxerr.push_back(0.5);
738 vy.push_back(purity);
739 vyerr.push_back(purityError);
742 TString title(Form("Fraction of events accepted by the event selection %s for trigger %s",GetTriggerTypeName(tt).Data(),
743 GetEventSelectionName(eventSelectionCorrected).Data()));
745 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
749 //_____________________________________________________________________________
750 void AliAnalysisMuMuFnorm::ComputeResultsFromGraphs()
752 // Compute one single value for each graph, by weighting by the fraction
753 // of events in each run
754 // do this for certain groups of graphs
757 groups.SetOwner(kTRUE);
759 groups.Add(new TObjString("Fnorm"));
760 groups.Add(new TObjString("NMBeq"));
761 groups.Add(new TObjString("Correction"));
762 groups.Add(new TObjString("RelDif"));
764 TList* objectList = MC()->CreateListOfObjectNames("/GRAPHS/");
766 TIter nextGroup(&groups);
769 TIter next(objectList);
770 TObjString* str(0x0);
772 while ( ( grp = static_cast<TObjString*>(nextGroup()) ) )
774 TString oname(Form("/RESULTS/%s",grp->String().Data()));
776 if ( MC()->GetObject(oname) )
778 // delete if we have it already so we can replace it
782 AliAnalysisMuMuResult* result = new AliAnalysisMuMuResult(grp->String());
784 MC()->Adopt("/RESULTS/",result);
788 while ( ( str = static_cast<TObjString*>(next()) ) )
790 if ( ! ( str->String().BeginsWith(grp->String() ) ) ) continue;
792 TGraphErrors* g = GetGraph(str->String());
796 AliAnalysisMuMuResult* sub = GetRunIntegratedResult(*g);
800 AliError(Form("Could not get result for graph %s",g->GetName()));
804 result->AdoptSubResult(sub);
812 //_____________________________________________________________________________
813 void AliAnalysisMuMuFnorm::ComputeNofEvents(ETriggerType triggerType,
814 Bool_t pileUpCorrected,
815 Int_t eventSelectionCorrected)
817 /// Compute trigger fractions
819 TString graphName(Form("NofEvent%s%s%s",GetTriggerTypeName(triggerType).Data(),
820 pileUpCorrected ? "PU" : "",
821 GetEventSelectionName(eventSelectionCorrected).Data()));
823 if ( GetGraph(graphName) )
825 // compute it only once
829 ComputeCorrectionFactors(eventSelectionCorrected);
831 TString gpsname(Form("Correction%s%s",GetEventSelectionName(eventSelectionCorrected).Data(),GetTriggerTypeName(triggerType).Data()));
832 TString gpuname(Form("CorrectionPU%s%s",GetEventSelectionName(eventSelectionCorrected).Data(), GetTriggerTypeName(triggerType).Data()));
834 TGraphErrors* gPS = GetGraph(gpsname);
838 AliError(Form("Could not find %s",gpsname.Data()));
842 TGraphErrors* gPU = GetGraph(gpuname);
846 AliError(Form("Could not find %s",gpuname.Data()));
850 AliDebug(2,graphName);
852 std::vector<double> vx;
853 std::vector<double> vxerr;
854 std::vector<double> vy;
855 std::vector<double> vyerr;
857 const std::set<int>& runs = RunNumbers();
861 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
863 Int_t runNumber = *it;
865 TString triggerClassName = GetTriggerClassName(triggerType,runNumber);
867 if ( triggerClassName.Length() )
869 Double_t n = GetSum(triggerClassName,runNumber,0);
871 vx.push_back(runNumber);
872 vxerr.push_back(0.5);
874 assert(runNumber==TMath::Nint(gPU->GetX()[i]));
882 if ( pileUpCorrected )
885 e1 = gPU->GetEY()[i];
888 if ( eventSelectionCorrected > 0 )
891 e2 = gPS->GetEY()[i];
896 AliDebug(2,Form("RUN %09d n %e y1 %e y2 %e y% e",runNumber,n,y1,y2,y));
898 Double_t yerr = y*AliAnalysisMuMuResult::ErrorABC( n, TMath::Sqrt(n),
903 vyerr.push_back(yerr);
909 TString title(Form("Number of event of trigger %s",GetTriggerTypeName(triggerType).Data()));
911 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
914 //_____________________________________________________________________________
915 void AliAnalysisMuMuFnorm::ComputeTriggerFractions(ETriggerType triggerType,
916 Bool_t physicsSelectionCorrected)
918 /// Compute trigger fractions
920 TString graphName(Form("Fractions%s%s",GetTriggerTypeName(triggerType).Data(),physicsSelectionCorrected ? "PS" : ""));
922 if ( GetGraph(graphName) )
924 // compute it only once
928 AliDebug(2,graphName);
930 std::vector<double> vx;
931 std::vector<double> vxerr;
932 std::vector<double> vy;
933 std::vector<double> vyerr;
935 const std::set<int>& runs = RunNumbers();
939 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
941 Int_t runNumber = *it;
943 TString triggerClassName = GetTriggerClassName(triggerType,runNumber);
945 if ( triggerClassName.Length() )
947 n += GetSum(triggerClassName,runNumber,physicsSelectionCorrected);
953 AliWarning(Form("Got zero trigger for %s",GetTriggerTypeName(triggerType).Data()));
957 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
959 Int_t runNumber = *it;
961 TString triggerClassName = GetTriggerClassName(triggerType,runNumber);
963 vx.push_back(runNumber);
964 vxerr.push_back(0.5);
965 Double_t y = GetSum(triggerClassName,runNumber,physicsSelectionCorrected);
967 vyerr.push_back( (y/n) * AliAnalysisMuMuResult::ErrorAB( y,TMath::Sqrt(y),
972 TString title(Form("Fraction of event of trigger %s",GetTriggerTypeName(triggerType).Data()));
974 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
977 //_____________________________________________________________________________
978 void AliAnalysisMuMuFnorm::ComputeTriggerL0B(ETriggerType triggerType)
980 /// Compute trigger L0B
982 std::vector<double> vx;
983 std::vector<double> vxerr;
984 std::vector<double> vy;
985 std::vector<double> vyerr;
987 TString graphName(Form("L0B%s",GetTriggerTypeName(triggerType).Data()));
989 if ( GetGraph(graphName) )
991 // insure we're computing it only once
995 AliDebug(2,graphName);
997 const std::set<int>& runs = RunNumbers();
999 AliAnalysisTriggerScalers ts(runs,OCDBPath().Data());
1001 for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
1003 Int_t runNumber = *it;
1005 TString triggerClassName = GetTriggerClassName(triggerType,runNumber);
1007 AliAnalysisTriggerScalerItem* item = ts.GetTriggerScaler(runNumber,"L0B",triggerClassName);
1008 if (!item) continue;
1010 vx.push_back(runNumber);
1011 vxerr.push_back(0.5);
1013 Double_t y = item->Value();
1017 vyerr.push_back( TMath::Sqrt(y) );
1020 TString title(Form("L0B of trigger %s",GetTriggerTypeName(triggerType).Data()));
1022 CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
1025 ////_____________________________________________________________________________
1026 //void AliAnalysisMuMuFnorm::ComputeTSGraph(ETriggerType tt)
1028 // /// Compute the per-run graph of physics selection accept fraction x track
1029 // /// accept fraction for the given trigger
1031 // TString graphName(Form("CorrectionTS%s",GetTriggerTypeName(tt).Data()));
1033 // if (GetGraph(graphName))
1035 // // insure we're computing it only once
1039 // AliDebug(1,graphName);
1041 // std::vector<double> vx;
1042 // std::vector<double> vxerr;
1043 // std::vector<double> vy;
1044 // std::vector<double> vyerr;
1046 // const std::set<int>& runs = RunNumbers();
1048 // AliAnalysisTriggerScalers ts(runs,OCDBPath().Data());
1050 // for ( std::set<int>::const_iterator it = runs.begin(); it != runs.end(); ++it )
1052 // Int_t runNumber = *it;
1054 // Double_t purity, purityError;
1056 // TString triggerClassName = GetTriggerClassName(tt,runNumber);
1058 // if ( triggerClassName.Length()==0 )
1060 // AliError(Form("Unknown trigger type %d",tt));
1064 // GetPurity(triggerClassName.Data(),runNumber,purity,purityError,"OFFLINE1");
1066 // vx.push_back(runNumber);
1067 // vxerr.push_back(0.5);
1068 // vy.push_back(purity);
1069 // vyerr.push_back(purityError);
1072 // TString title(Form("Fraction of events accepted by the physics selection x track selection for trigger %s",GetTriggerTypeName(tt).Data()));
1074 // CreateAndAddGraph(graphName,title,vx,vxerr,vy,vyerr);
1078 //_____________________________________________________________________________
1079 TGraphErrors* AliAnalysisMuMuFnorm::CreateAndAddGraph(const TString& name,
1080 const TString& title,
1081 const std::vector<double>& vx,
1082 const std::vector<double>& vxerr,
1083 const std::vector<double>& vy,
1084 const std::vector<double>& vyerr) const
1086 /// Creates a graph and adds it to our mergeable collection
1088 TGraphErrors* g = new TGraphErrors(vx.size(),&vx[0],&vy[0],&vxerr[0],&vyerr[0]);
1089 g->SetName(name.Data());
1090 g->SetTitle(title.Data());
1092 if (fIsCompactGraphs)
1094 AliAnalysisMuMuGraphUtil::Compact(*g);
1097 g->GetXaxis()->SetNoExponent();
1098 // g->GetXaxis()->SetTitle("Run number");
1100 TPaveText* text = new TPaveText(0.70,0.70,0.89,0.89,"NDC");
1101 text->SetBorderSize(0);
1102 text->SetFillColor(0);
1103 text->AddText(Form("Mean %e",g->GetMean(2)));
1104 text->AddText(Form("RMS %e",g->GetRMS(2)));
1105 g->GetListOfFunctions()->Add(text);
1107 MC()->Adopt("/GRAPHS/",g);
1111 //_____________________________________________________________________________
1112 AliMergeableCollection* AliAnalysisMuMuFnorm::DetachMC()
1114 // let go the ownership of our mergeable collection
1116 return fMergeableCollection;
1119 //_____________________________________________________________________________
1120 void AliAnalysisMuMuFnorm::DrawWith2Scales(const char* graphName1, const char* graphName2)
1122 TGraphErrors* g1 = static_cast<TGraphErrors*>(GetGraph(graphName1)->Clone());
1123 TGraphErrors* g2 = static_cast<TGraphErrors*>(GetGraph(graphName2)->Clone());
1127 gStyle->SetOptTitle(0);
1129 AliAnalysisMuMuGraphUtil gu;
1131 TCanvas* c = gu.DrawWith2Scales(*g1,*g2);
1134 for ( Int_t i = 0; i < 2; ++i )
1137 gPad->SetLeftMargin(0.15);
1138 gPad->SetRightMargin(0.15);
1143 // TGraphErrors* g = new TGraphErrors(g1->GetN());
1145 // Double_t check(0.0);
1147 // for ( Int_t i = 0; i < g->GetN(); ++i )
1149 // Double_t y = g1->GetY()[i]*g2->GetY()[i];
1151 // check += g2->GetY()[i];
1153 // g->SetPoint(i,g2->GetX()[i],y);
1154 // g->SetPointError(i,g2->GetEX()[i],
1155 // y*AliAnalysisMuMuResult::ErrorAB(g1->GetY()[i],g1->GetEY()[i],
1156 // g2->GetY()[i],g2->GetEY()[i]));
1163 // AliInfo(Form("check: %e g mean %e rms %e",check,g->GetMean(2),g->GetRMS(2)));
1169 TGraphErrors* g = new TGraphErrors(g1->GetN());
1171 for ( Int_t i = 0; i < g->GetN(); ++i )
1173 g->SetPoint(i,g2->GetY()[i],g1->GetY()[i]);
1174 g->SetPointError(i,g2->GetEY()[i],g1->GetEY()[i]);
1181 AliInfo(Form("g mean %e rms %e",g->GetMean(2),g->GetRMS(2)));
1189 //_____________________________________________________________________________
1190 TString AliAnalysisMuMuFnorm::GetEventSelectionName(Int_t eventSelectionCorrected) const
1192 if ( eventSelectionCorrected == 1 )
1196 else if ( eventSelectionCorrected == 2 )
1203 //_____________________________________________________________________________
1204 TGraphErrors* AliAnalysisMuMuFnorm::GetGraph(const char* name) const
1206 // shortcut method to give access to one graph
1208 TObject* o = MC()->GetObject(Form("/GRAPHS/%s",name));
1212 if ( o->IsA() != TGraphErrors::Class() )
1214 AliError(Form("Object %s is not of the expected type",o->GetName()));
1218 return static_cast<TGraphErrors*>(o);
1221 //_____________________________________________________________________________
1222 void AliAnalysisMuMuFnorm::GetPurity(const char* triggerClassName, Int_t runNumber,
1223 Double_t& value, Double_t& error, Int_t eventSelectionCorrected) const
1225 /// Get the physics selection accept fraction for a given trigger
1229 TString runCondition;
1233 runCondition.Form("/run:%d",runNumber);
1236 Double_t nall = fCounterCollection.GetSum(Form("trigger:%s/event:ALL%s",triggerClassName,runCondition.Data()));
1240 if ( eventSelectionCorrected == 1 )
1244 else if ( eventSelectionCorrected == 2 )
1254 Double_t nps = fCounterCollection.GetSum(Form("trigger:%s/event:%s%s",
1255 triggerClassName,ename.Data(),runCondition.Data()));
1257 if ( nall <= 0.0 ) return;
1261 error = AliAnalysisMuMuResult::ErrorAB(nall,TMath::Sqrt(nall),nps,TMath::Sqrt(nps));
1264 //_____________________________________________________________________________
1265 AliAnalysisMuMuResult* AliAnalysisMuMuFnorm::GetResult(const char* name) const
1267 // shortcut method to give access to one result
1269 TObject* o = MC()->GetObject(Form("/RESULTS/%s",name));
1273 if ( o->IsA() != AliAnalysisMuMuResult::Class() )
1275 AliError(Form("Object %s is not of the expected type",o->GetName()));
1279 return static_cast<AliAnalysisMuMuResult*>(o);
1282 //______________________________________________________________________________
1283 AliAnalysisMuMuResult* AliAnalysisMuMuFnorm::GetRunIntegratedResult(const TGraphErrors& g, const char* basename)
1285 /// get one value +- error for this graph (weighting the run-by-run values
1286 /// by the fraction of the number of triggers in that run)
1287 /// also the rms is computed.
1289 Bool_t physicsSelectionCorrected(kFALSE);
1291 if ( TString(g.GetName()).Contains("PS") )
1293 physicsSelectionCorrected=kTRUE;
1296 ComputeTriggerFractions(fReferenceTriggerType,physicsSelectionCorrected);
1298 TString fname(Form("Fractions%s%s",GetTriggerTypeName(fReferenceTriggerType).Data(),physicsSelectionCorrected ? "PS" : ""));
1300 TGraphErrors* gTriggerFractions = GetGraph(fname);
1302 StdoutToAliDebug(2,std::cout << g.GetName() << std::endl; g.Print(););
1304 if (!gTriggerFractions)
1306 AliError(Form("Did not find graph for %s",fname.Data()));
1310 Double_t mean = g.GetY()[0];
1313 Double_t errorOnMean = g.GetEY()[0];
1318 mean = errorOnMean = 0.0;
1323 for ( Int_t i = 0; i < n; ++i )
1325 Double_t y = g.GetY()[i];
1327 Double_t weight = gTriggerFractions->GetY()[i]; // sum of weight should be 1.0
1329 AliDebug(2,Form("%s i %3d y %e weight %e",g.GetName(),i,y,weight));
1334 v2 += weight*weight;
1339 for ( Int_t i = 0; i < n; ++i )
1341 Double_t weight = gTriggerFractions->GetY()[i]; // sum of weight should be 1.0
1342 Double_t y = g.GetY()[i];
1344 d += (y-mean)*(y-mean)*weight;
1347 AliDebug(2,Form("v1=%e v2=%e d=%e",v1,v2,d));
1349 if ( v1 <= 0) return 0x0;
1351 errorOnMean = TMath::Sqrt((1.0/v1)*(1.0/(n-1))*d);
1353 rms = TMath::Sqrt( (v1/(v1*v1-v2))*d );
1356 AliAnalysisMuMuResult* result = new AliAnalysisMuMuResult(g.GetName(),g.GetTitle());
1358 result->Set(basename,mean,errorOnMean,rms);
1360 if ( TString(g.GetName()) == "FnormScalersPUPS" )
1362 AliDebug(1,Form("mean %e errorOnMean %e rms %e",mean,errorOnMean,rms));
1363 StdoutToAliDebug(1,result->Print("full"));
1369 //_____________________________________________________________________________
1370 Double_t AliAnalysisMuMuFnorm::GetSum(const char* triggerClassName,
1372 Int_t eventSelectionCorrected) const
1374 TString condition(Form("trigger:%s/run:%d",triggerClassName,runNumber));
1376 if (eventSelectionCorrected==1)
1378 condition += "/event:PSALL";
1380 else if ( eventSelectionCorrected == 2 )
1382 condition += "/event:OFFLINE1";
1386 condition += "/event:ALL";
1389 Double_t n = fCounterCollection.GetSum(condition.Data());
1393 AliError(Form("Got no count for %s for run %d (physicsSelected:%d)",triggerClassName,runNumber,eventSelectionCorrected));
1400 //_____________________________________________________________________________
1401 TString AliAnalysisMuMuFnorm::GetTriggerClassName(ETriggerType tt, Int_t runNumber) const
1403 // get the triggerclass to for a given trigger type and run number
1407 return MBTriggerClassName(runNumber);
1409 else if ( tt == kMUL )
1411 return MULTriggerClassName(runNumber);
1413 else if ( tt == kMSL)
1415 return MSLTriggerClassName(runNumber);
1417 else if ( tt == kMSH)
1419 return MSHTriggerClassName(runNumber);
1424 //_____________________________________________________________________________
1425 TString AliAnalysisMuMuFnorm::GetTriggerTypeName(ETriggerType tt) const
1427 // get the name of the trigger type
1432 else if ( tt == kMUL )
1436 else if ( tt == kMSL)
1440 else if ( tt == kMSH)
1447 //_____________________________________________________________________________
1448 void AliAnalysisMuMuFnorm::GetValueAndErrorFromGraph(TGraphErrors* graph,
1451 Double_t& error) const
1453 /// get (value,error) corresponding to run=runNumber.
1454 /// Works both for compact and non-compact graphs
1456 value = TMath::Limits<Double_t>::Max();
1461 TAxis* axis = graph->GetXaxis();
1463 for ( Int_t i = 0; i < graph->GetN(); ++i )
1465 Int_t rbin = TMath::Nint(graph->GetX()[i]);
1466 Int_t rlabel = TString(axis->GetBinLabel(i+1)).Atoi();
1467 if ( rbin == runNumber || rlabel == runNumber )
1469 value = graph->GetY()[i];
1470 error = graph->GetEY()[i];
1475 //_____________________________________________________________________________
1476 AliMergeableCollection* AliAnalysisMuMuFnorm::MC() const
1478 // get our mergeable collection
1479 if (!fMergeableCollection)
1481 fMergeableCollection = new AliMergeableCollection("Fnorm",Form("MB to %s trigger normalization results",GetTriggerTypeName(fReferenceTriggerType).Data()));
1483 return fMergeableCollection;
1486 //_____________________________________________________________________________
1487 TString AliAnalysisMuMuFnorm::MBTriggerClassName(Int_t runNumber) const
1489 /// FIXME : find a better way ?
1491 if ( TriggerClassnameTest("CINT7-B-NOPF-ALLNOTRD",runNumber) )
1493 return "CINT7-B-NOPF-ALLNOTRD";
1498 //_____________________________________________________________________________
1499 TString AliAnalysisMuMuFnorm::MSHTriggerClassName(Int_t runNumber) const
1501 /// FIXME : find a better way ?
1503 if ( TriggerClassnameTest("CMSH7-B-NOPF-ALLNOTRD",runNumber) )
1505 return "CMSH7-B-NOPF-ALLNOTRD";
1507 else if ( TriggerClassnameTest("CMSH7-B-NOPF-MUON",runNumber) )
1509 return "CMSH7-B-NOPF-MUON";
1514 //_____________________________________________________________________________
1515 TString AliAnalysisMuMuFnorm::MSLTriggerClassName(Int_t runNumber) const
1517 /// FIXME : find a better way ?
1519 if ( TriggerClassnameTest("CMSL7-B-NOPF-MUON",runNumber) )
1521 return "CMSL7-B-NOPF-MUON";
1524 // if ( TriggerClassnameTest("CMSL7-B-NOPF-ALLNOTRD",runNumber) )
1526 // return "CMSL7-B-NOPF-ALLNOTRD";
1531 //_____________________________________________________________________________
1532 void AliAnalysisMuMuFnorm::MultiplyGraphs(const char* g1name, const char* g2name, const char* name)
1534 /// Make a new graph = g1*g2
1535 std::vector<double> vx;
1536 std::vector<double> vy;
1537 std::vector<double> vxerr;
1538 std::vector<double> vyerr;
1540 TGraphErrors* g1 = GetGraph(g1name);
1541 TGraphErrors* g2 = GetGraph(g2name);
1545 AliError(Form("Could not get graph %s",g1name));
1551 AliError(Form("Could not get graph %s",g2name));
1555 if ( g1->GetN() != g2->GetN() )
1557 AliError(Form("Could not multiply incompatible graphs %d pts vs %d pts",g1->GetN(),g2->GetN()));
1561 for ( Int_t i = 0; i < g1->GetN(); ++i )
1563 if ( g1->GetX()[i] != g2->GetX()[i] )
1565 AliError(Form("Incompatible bin %d : %e vs %e",i,g1->GetX()[i],g2->GetX()[i]));
1569 vx.push_back(g1->GetX()[i]);
1570 vxerr.push_back(g1->GetEX()[i]);
1572 Double_t y = g1->GetY()[i]*g2->GetY()[i];
1573 Double_t yerr = y*AliAnalysisMuMuResult::ErrorAB( g1->GetY()[i], g1->GetEY()[i],
1574 g2->GetY()[i], g2->GetEY()[i]);
1577 vyerr.push_back(yerr);
1580 TString gname(name);
1582 if ( gname.Length() == 0 )
1584 gname = g1->GetName();
1586 gname += g2->GetName();
1589 TString title(Form("Product of %s by %s",g1->GetName(),g2->GetName()));
1591 CreateAndAddGraph(gname,title,vx,vxerr,vy,vyerr);
1594 //_____________________________________________________________________________
1595 TString AliAnalysisMuMuFnorm::MULTriggerClassName(Int_t runNumber) const
1597 /// FIXME : find a better way ?
1599 if ( TriggerClassnameTest("CMUL7-B-NOPF-ALLNOTRD",runNumber) )
1601 return "CMUL7-B-NOPF-ALLNOTRD";
1603 else if ( TriggerClassnameTest("CMUL7-B-NOPF-MUON",runNumber) )
1605 return "CMUL7-B-NOPF-MUON";
1611 //_____________________________________________________________________________
1612 void AliAnalysisMuMuFnorm::Print(Option_t* opt) const
1614 if ( fMergeableCollection )
1616 fMergeableCollection->Print(opt);
1620 //_____________________________________________________________________________
1621 std::set<int> AliAnalysisMuMuFnorm::RunNumbers() const
1623 // Extract the run numbers from our counter collection
1625 std::set<int> runset;
1627 TString sruns = fCounterCollection.GetKeyWords("run");
1628 TObjArray* runs = sruns.Tokenize(",");
1633 while ( ( s = static_cast<TObjString*>(next())) )
1635 runset.insert(s->String().Atoi());
1642 //_____________________________________________________________________________
1643 void AliAnalysisMuMuFnorm::ScalerFnorm(Double_t& value, Double_t& error,
1644 Double_t L0bREF, Double_t purityREF, Double_t purityREFerror,
1645 Double_t L0bMB, Double_t purityMB, Double_t purityMBerror,
1646 Double_t pileUpFactor, Double_t pileUpFactorError)
1648 /// Compute the MB to REF ratio and its associated error
1650 value = error = 0.0;
1652 value = L0bREF*purityREF;
1656 value = L0bMB*purityMB*pileUpFactor/value;
1658 error = value*AliAnalysisMuMuResult::ErrorABCDE(L0bREF,TMath::Sqrt(L0bREF),
1659 purityREF,purityREFerror,
1660 L0bMB,TMath::Sqrt(L0bMB),
1661 purityMB,purityMBerror,
1662 pileUpFactor,pileUpFactorError);
1665 //_____________________________________________________________________________
1666 void AliAnalysisMuMuFnorm::ShowFnorm(const TObjArray& a) const
1668 /// Print and plot Fnorm values
1672 while ( ( g = static_cast<TGraphErrors*>(next()) ) )
1674 g->SetTitle(Form("Fnorm %s",g->GetTitle()));
1676 new TCanvas(Form("c%s",g->GetName()));
1678 if (fIsCompactGraphs)
1680 AliAnalysisMuMuGraphUtil::Compact(*g);
1684 g->GetXaxis()->SetNoExponent();
1691 for ( Int_t i = 0; i < g->GetN(); ++i )
1694 Double_t e = ( y != 0.0 ? g->GetEY()[i]/y : 0.0);
1700 yerr = TMath::Sqrt(yerr)*y;
1702 AliInfo(Form("%30s graph %e +- %e (%5.2f %%) RMS %e",g->GetName(),
1703 y,yerr,yerr*100/y,g->GetRMS(2)));
1708 //_____________________________________________________________________________
1709 Bool_t AliAnalysisMuMuFnorm::TriggerClassnameTest(const char* triggerClassName, Int_t runNumber) const
1711 /// Check if we have counts for that trigger,run combination
1713 TString runs = fCounterCollection.GetKeyWords("run");
1715 if ( !runs.Contains(Form("%d",runNumber)) ) return kFALSE;
1717 TString triggers = fCounterCollection.GetKeyWords("trigger");
1719 if (!triggers.Contains(triggerClassName)) return kFALSE;
1721 Double_t n = fCounterCollection.GetSum(Form("trigger:%s/run:%d",triggerClassName,runNumber));
1726 //_____________________________________________________________________________
1728 AliAnalysisMuMuFnorm::WeightedMeanGraphs(const char* patternOrList, const char* graphName)
1730 /// Sum the graphs which name matches pattern
1731 /// Sum is made using a weighted mean (each element is weighted by the inverse
1732 /// of its error squared)
1734 TString spattern(patternOrList);
1735 TObjArray* slist(0x0);
1737 if ( spattern.CountChar(',') )
1739 // it's not a pattern but a list...
1740 slist = spattern.Tokenize(",");
1744 TList* objectList = MC()->CreateListOfObjectNames("/GRAPHS/");
1745 TIter next(objectList);
1746 TObjString* str(0x0);
1748 selected.SetOwner(kFALSE);
1750 while ( ( str = static_cast<TObjString*>(next()) ) )
1752 TGraphErrors* g = GetGraph(str->String());
1756 TString name(g->GetName());
1758 if ( spattern.Length() >0 && !name.Contains(spattern.Data()) ) continue;
1760 if ( slist && !slist->FindObject(name)) continue;
1762 AliDebug(2,Form("Selected for sum : %s",name.Data()));
1770 if (selected.GetLast()<0) return;
1772 std::vector<double> vx;
1773 std::vector<double> vy;
1774 std::vector<double> vxerr;
1775 std::vector<double> vyerr;
1777 Int_t npts = static_cast<TGraphErrors*>(selected.First())->GetN();
1779 for ( Int_t ipoint = 0; ipoint < npts; ++ipoint )
1781 Double_t x(0.0),xref(0.0),xerr(0.0);
1783 Double_t sume2(0.0);
1785 for ( Int_t igraph = 0; igraph <= selected.GetLast(); ++igraph )
1787 TGraphErrors* g = static_cast<TGraphErrors*>(selected.At(igraph));
1789 if ( g->GetN() != npts )
1791 AliError(Form("Graph %s does not have the expected %d points",g->GetName(),npts));
1796 if ( fIsCompactGraphs )
1798 runNumber = TString(g->GetXaxis()->GetBinLabel(ipoint+1)).Atoi()*1.0;
1802 runNumber = g->GetX()[ipoint];
1807 xref = g->GetX()[ipoint];
1809 xerr = g->GetEX()[ipoint];
1813 if ( xref != g->GetX()[ipoint] )
1815 AliError(Form("Cannot sum graphs with different axis : get %e and expected %e : %s vs %s",xref,x,selected.At(0)->GetName(),g->GetName()));
1820 Double_t e2 = g->GetEY()[ipoint]*g->GetEY()[ipoint];
1824 sum += g->GetY()[ipoint]/e2;
1832 vxerr.push_back(xerr);
1833 vy.push_back(sum/sume2);
1834 vyerr.push_back(TMath::Sqrt(1/sume2));
1838 Int_t n = selected.GetEntries();
1840 TString name(graphName);
1841 TString title(Form("Weighted mean from %d individual graphs",n));
1843 if ( strlen(graphName) == 0)
1845 name = TString::Format("WeightMeanFnorm%s",patternOrList);
1846 name.ReplaceAll(",","_");
1847 title = TString::Format("WeightMeanFnorm%s from %d individual graphs",patternOrList,n);
1850 CreateAndAddGraph(name,title,vx,vxerr,vy,vyerr);