muon/AliAnalysisNonMuonTrackCuts.cxx
muon/AliAnalysisNonPrimaryVertices.cxx
muon/AliAnalysisTaskAOD2MuonAOD.cxx
+ muon/AliAnalysisTaskMuMu.cxx
+ muon/AliAnalysisMuMuBase.cxx
+ muon/AliAnalysisMuMuGlobal.cxx
+ muon/AliAnalysisMuMuCutRegistry.cxx
+ muon/AliAnalysisMuMuCutElement.cxx
+ muon/AliAnalysisMuMuEventCutter.cxx
+ muon/AliAnalysisMuMuCutCombination.cxx
+ muon/AliAnalysisMuMuSingle.cxx
+ muon/AliAnalysisMuMuMinv.cxx
+ muon/AliAnalysisMuMuNch.cxx
)
string ( REPLACE ".cxx" ".h" HDRS "${SRCS}" )
set ( DHDR PWGmuonLinkDef.h)
-set ( EINCLUDE PWG/muon ANALYSIS STEER/AOD STEER/ESD STEER/STEERBase)
+set ( EINCLUDE RooUnfold/src PWG/muon ANALYSIS STEER/AOD STEER/ESD STEER/STEERBase)
if( ALICE_TARGET STREQUAL "win32gcc")
set ( PACKSOFLAGS ${SOFLAGS} )
#pragma link C++ class AliHistogramCollectionIterator+;
#pragma link C++ class AliAnalysisTaskMuonCollisionMultiplicity+;
#pragma link C++ class AliCFMuonResUpsilon+;
-#pragma link C++ class AliAnalysisTaskMuMu+;
-#pragma link C++ class AliAnalysisTaskMuMu::PairCut+;
#pragma link C++ class AliMuonEventCuts+;
#pragma link C++ class AliMuonTrackCuts+;
#pragma link C++ class AliMuonPairCuts+;
#pragma link C++ class AliAnalysisMuonUtility+;
#pragma link C++ class AliUtilityMuonAncestor+;
#pragma link C++ class AliOADBMuonTrackCutsParam+;
-#pragma link C++ class AliAnalysisMuMuBinning+;
-#pragma link C++ class AliAnalysisMuMuBinning::Range+;
#pragma link C++ class AliAnalysisTaskAOD2MuonAOD+;
#pragma link C++ class AliAnalysisNonMuonTrackCuts+;
#pragma link C++ class AliAnalysisNonPrimaryVertices+;
+#pragma link C++ class AliAnalysisTaskMuMu+;
+#pragma link C++ class AliAnalysisMuMuBinning+;
+#pragma link C++ class AliAnalysisMuMuBinning::Range+;
+#pragma link C++ class AliAnalysisMuMuBase+;
+#pragma link C++ class AliAnalysisMuMuGlobal+;
+#pragma link C++ class AliAnalysisMuMuCutRegistry+;
+#pragma link C++ class AliAnalysisMuMuCutElement+;
+#pragma link C++ class AliAnalysisMuMuCutElementBar+;
+#pragma link C++ class AliAnalysisMuMuCutCombination+;
+#pragma link C++ class AliAnalysisMuMuEventCutter+;
+#pragma link C++ class AliAnalysisMuMuSingle+;
+#pragma link C++ class AliAnalysisMuMuMinv+;
+#pragma link C++ class AliAnalysisMuMuNch+;
+//#pragma link C++ class AliAnalysisMuMuMeanPt+;
+
#endif
///
-/// Configure a task to get invariant mass spectrum of dimuons
+/// Configuration example of a task to get invariant mass spectrum of dimuons
///
-/// author: L. Aphecetche (Subatech) (laurent.aphecetche - at - subatech.in2p3.fr)
+/// \author: L. Aphecetche (Subatech) (laurent.aphecetche - at - subatech.in2p3.fr)
///
AliAnalysisTask* AddTaskMuMu(const char* outputname,
- TList* triggerClassesToConsider,
- const char* beamYear,
- TArrayF* centralities,
- Bool_t simulations)
+ TList* triggerClassesToConsider,
+ const char* beamYear,
+ Bool_t simulations)
{
AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
if (!mgr) {
// Configure analysis
//===========================================================================
-
- AliAnalysisTaskMuMu* task;
-
+
if (simulations && triggerClassesToConsider )
{
- triggerClassesToConsider->Add(new TObjString("CMULLO-B-NOPF-MUON"));
- triggerClassesToConsider->Add(new TObjString("CMSNGL-B-NOPF-MUON"));
- triggerClassesToConsider->Add(new TObjString("ANY"));
+// triggerClassesToConsider->Add(new TObjString("CMULLO-B-NOPF-MUON"));
+// triggerClassesToConsider->Add(new TObjString("CMSNGL-B-NOPF-MUON"));
+ triggerClassesToConsider->Add(new TObjString("ANY"));
+
+// triggerClassesToConsider->Add(new TObjString("MB1"));
+// triggerClassesToConsider->Add(new TObjString("C0T0A"));
+
+ // triggerClassesToConsider->Add(new TObjString("MULow"));
+// triggerClassesToConsider->Add(new TObjString("V0L"));
+// triggerClassesToConsider->Add(new TObjString("V0R"));
+//
+// for dpmjet simulations (at least) we have the following "triggers" :
+// C0T0A,C0T0C,MB1,MBBG1,V0L,V0R,MULow,EMPTY,MBBG3,MULL,MULU,MUHigh
}
+
+ AliAnalysisTaskMuMu* task = new AliAnalysisTaskMuMu;
- if ( triggerClassesToConsider )
- {
- task = new AliAnalysisTaskMuMu((inputDataType=="ESD"),triggerClassesToConsider,beamYear,centralities);
- }
- else
- {
- task = new AliAnalysisTaskMuMu((inputDataType=="ESD"),beamYear,centralities);
- }
+ AliAnalysisMuMuEventCutter* eventCutter = new AliAnalysisMuMuEventCutter(triggerClassesToConsider);
- task->AddEventCut("ALL",AliAnalysisTaskMuMu::kEventAll);
+ AliAnalysisMuMuCutRegistry* cr = task->CutRegistry();
+
+ AliAnalysisMuMuCutElement* eventTrue = cr->AddEventCut(*eventCutter,"IsTrue","const AliVEvent&","");
-if (!simulations)
- {
- task->AddEventCut("PSALL",AliAnalysisTaskMuMu::kEventAll | AliAnalysisTaskMuMu::kEventPS);
-// task->AddEventCut("OFFLINE1",AliAnalysisTaskMuMu::kEventAll | AliAnalysisTaskMuMu::kEventPS | AliAnalysisTaskMuMu::kEventOFFLINEMUL1);
-// task->AddEventCut("REJECTED",AliAnalysisTaskMuMu::kEventAll | AliAnalysisTaskMuMu::kEventREJECTED);
- }
-
-// task->AddEventCut("PSALLNOTZEROPILEUP",AliAnalysisTaskMuMu::kEventAll | AliAnalysisTaskMuMu::kEventPS | AliAnalysisTaskMuMu::kEventNOTZEROPILEUP);
-
-// task->AddEventCut("PSALLMUL1", AliAnalysisTaskMuMu::kEventAll | AliAnalysisTaskMuMu::kEventPS | AliAnalysisTaskMuMu::kEventOFFLINEMUL1);
-
-// task->AddEventCut("PSALLMUL2", AliAnalysisTaskMuMu::kEventAll | AliAnalysisTaskMuMu::kEventPS | AliAnalysisTaskMuMu::kEventOFFLINEMUL2);
-
-// task->AddSingleCut("MATCHLOWRABSDCA",
-// AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs|AliAnalysisTaskMuMu::kDCA);
-//
- task->AddSingleCut("MATCHLOWRABS",
- AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs);
-
- task->AddSingleCut("MATCHLOWRABSETA",
- AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs);
-
- task->AddSingleCut("MATCHLOWRABSETADCA",
- AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs|AliAnalysisTaskMuMu::kEta|AliAnalysisTaskMuMu::kDCA);
-
-
-// task->AddPairCut("ALL",AliAnalysisTaskMuMu::kAll);
-
- task->AddPairCut("MATCHLOWRABSBOTH",
- AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs,
- AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs);
-
- task->AddPairCut("MATCHLOWRABSETABOTH",
- AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs|AliAnalysisTaskMuMu::kEta,
- AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs|AliAnalysisTaskMuMu::kEta);
-
- task->AddPairCut("MATCHLOWRABSETADCABOTH",
- AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs|AliAnalysisTaskMuMu::kEta|AliAnalysisTaskMuMu::kDCA,
- AliAnalysisTaskMuMu::kAll|AliAnalysisTaskMuMu::kMatchedLow|AliAnalysisTaskMuMu::kRabs|AliAnalysisTaskMuMu::kEta|AliAnalysisTaskMuMu::kDCA);
-
-// igor binning
-
-task->AddBin("psi","pt", 0.0, 0.5,"IGOR");
-task->AddBin("psi","pt", 0.5, 1.0,"IGOR");
-task->AddBin("psi","pt", 1.0, 1.5,"IGOR");
-task->AddBin("psi","pt", 1.5, 2.0,"IGOR");
-task->AddBin("psi","pt", 2.0, 2.5,"IGOR");
-task->AddBin("psi","pt", 2.5, 3.0,"IGOR");
-task->AddBin("psi","pt", 3.0, 3.5,"IGOR");
-task->AddBin("psi","pt", 3.5, 4.0,"IGOR");
-task->AddBin("psi","pt", 4.0, 4.5,"IGOR");
-task->AddBin("psi","pt", 4.5, 5.0,"IGOR");
-task->AddBin("psi","pt", 5.0, 6.0,"IGOR");
-task->AddBin("psi","pt", 6.0, 7.0,"IGOR");
-task->AddBin("psi","pt", 7.0, 8.0,"IGOR");
-task->AddBin("psi","pt", 8.0, 9.0,"IGOR");
-task->AddBin("psi","pt", 9.0,11.0,"IGOR");
-task->AddBin("psi","pt",11.0,13.0,"IGOR");
-task->AddBin("psi","pt",13.0,15.0,"IGOR");
-
-// roberta binning
-task->AddBin("psi","pt",0.0,1.0,"ROBERTA");
-task->AddBin("psi","pt",1.0,2.0,"ROBERTA");
-task->AddBin("psi","pt",2.0,3.0,"ROBERTA");
-task->AddBin("psi","pt",3.0,4.0,"ROBERTA");
-task->AddBin("psi","pt",4.0,5.0,"ROBERTA");
-task->AddBin("psi","pt",5.0,6.0,"ROBERTA");
-task->AddBin("psi","pt",6.0,8.0,"ROBERTA");
-
-/*
-
- for ( Int_t i = 0; i < 10; ++i )
+ AliAnalysisMuMuCutElement* ps = eventTrue;
+
+ if (!simulations)
{
- Double_t xmin = i*1.0;
-
- task->AddBin("psi","pt",xmin,xmin+1.0);
+ ps = cr->AddEventCut(*eventCutter,"IsPhysicsSelected","const AliInputEventHandler&","");
}
- for ( Int_t i = 0; i < 5; ++i )
- {
- Double_t xmin = 10+i*2.0;
-
- task->AddBin("psi","pt",xmin,xmin+2.0);
- }
+ AliAnalysisMuMuCutElement* triggerSelection = cr->AddTriggerClassCut(*eventCutter,"SelectTriggerClass","const TString&,TString&,UInt_t,UInt_t,UInt_t","");
- for ( Int_t i = 0; i < 6; ++i )
+ cr->AddCutCombination(triggerSelection);
+
+// AliAnalysisMuMuCutElement* cutVDM = cr->AddEventCut(*eventCutter,"IsPhysicsSelectedVDM","const AliVEvent&","");
+//
+// AliAnalysisMuMuCutElement* cutTZEROPileUp = cr->AddEventCut(*eventCutter,"IsTZEROPileUp","const AliVEvent&","");
+//
+// AliAnalysisMuMuCutElement* notTZEROPileUp = cr->Not(*cutTZEROPileUp);
+
+ cr->AddCutCombination(ps);
+
+ task->SetBeamYear(beamYear);
+
+ AliAnalysisMuMuGlobal* globalAnalysis = 0x0;//new AliAnalysisMuMuGlobal;
+
+ AliAnalysisMuMuSingle* singleAnalysis = new AliAnalysisMuMuSingle;
+
+ AliAnalysisMuMuMinv* minvAnalysis = new AliAnalysisMuMuMinv;
+
+// TFile f("$HOME/Downloads/ResponseMatrix_QASPDZPSALL_ANY.root");
+// TH2* h = static_cast<TH2*>(f.Get("ResponseMatrix"));
+
+ AliAnalysisMuMuNch* nchAnalysis = new AliAnalysisMuMuNch; // (0x0,-2,2,-40,40);
+
+// AliAnalysisMuMuNch(TH2* spdCorrection=0x0,
+// Int_t nbinsEta=10, Double_t etaMin=-0.5, Double_t etaMax=0.5,
+// Int_t nbinsZ=320, Double_t zmin=-40, Double_t zmax=40);
+
+
+ if ( globalAnalysis )
{
- Double_t xmin = -4+i*0.25;
+ AliAnalysisMuMuCutElement* triggerAll = cr->AddTriggerClassCut(*globalAnalysis,"SelectAnyTriggerClass","const TString&,TString&","");
+
+ cr->AddCutCombination(triggerAll);
- task->AddBin("psi","y",xmin,xmin+0.25);
+ task->AdoptSubAnalysis(globalAnalysis);
}
-
- Int_t nphiSteps = 18;
- for ( Int_t i = 0; i < nphiSteps; ++i )
+ if ( nchAnalysis )
{
- Double_t xstep = 2*TMath::Pi()/nphiSteps;
- Double_t xmin = -TMath::Pi() + i*xstep;
+// AliAnalysisMuMuCutElement* trketa2 = cr->AddEventCut(*nchAnalysis,"HasAtLeastNTrackletsInEtaRange","const AliVEvent&,Int_t, Double_t& , Double_t& ","1,-2.0,2.0");
+// AliAnalysisMuMuCutElement* trketa1 = cr->AddEventCut(*nchAnalysis,"HasAtLeastNTrackletsInEtaRange","const AliVEvent&,Int_t, Double_t& , Double_t& ","1,-1.0,1.0");
+// AliAnalysisMuMuCutElement* trk5eta1 = cr->AddEventCut(*nchAnalysis,"HasAtLeastNTrackletsInEtaRange","const AliVEvent&,Int_t, Double_t& , Double_t& ","5,-1.0,1.0");
+//
+// cr->AddCutCombination(ps,trketa1);
+// cr->AddCutCombination(ps,trk5eta1);
+// cr->AddCutCombination(ps,trketa2);
+
+ AliAnalysisMuMuCutElement* cutZ18= cr->AddEventCut(*eventCutter,"IsAbsZBelowValue","const AliVEvent&,Double_t","18");
+
+ AliAnalysisMuMuCutElement* cutZ10 = cr->AddEventCut(*eventCutter,"IsAbsZBelowValue","const AliVEvent&,Double_t","10");
- task->AddBin("psi","phi",xmin,xmin+xstep);
+ cr->AddCutCombination(ps,cutZ18);
+ cr->AddCutCombination(ps,cutZ10);
+
+ task->AdoptSubAnalysis(nchAnalysis);
}
- */
-
- Double_t ymin(-4.0);
- Double_t ymax(-3.43);
+ if ( singleAnalysis )
+ {
+ AliAnalysisMuMuCutElement* trackTrue = cr->AddTrackCut(*cr,"AlwaysTrue","const AliVParticle&","");
+ AliAnalysisMuMuCutElement* rabs = cr->AddTrackCut(*singleAnalysis,"IsRabsOK","const AliVParticle&","");
+ AliAnalysisMuMuCutElement* eta = cr->AddTrackCut(*singleAnalysis,"IsEtaInRange","const AliVParticle&,Double_t&,Double_t&","-4.0,-2.5");
+
+ cr->AddCutCombination(trackTrue);
- Double_t ymin(-4.0);
- Double_t ymax(-3.43);
+ cr->AddCutCombination(rabs);
+
+ cr->AddCutCombination(eta);
+
+ cr->AddCutCombination(rabs,eta);
- task->AddBin("psi","y",-4,-2.5,"ILAB");
+ task->AdoptSubAnalysis(singleAnalysis);
+
+ if ( minvAnalysis )
+ {
+ AliAnalysisMuMuCutElement* pairTrue = cr->AddTrackPairCut(*cr,"AlwaysTrue","const AliVParticle&, const AliVParticle&","");
+
+ AliAnalysisMuMuCutElement* pairy = cr->AddTrackPairCut(*minvAnalysis,"IsRapidityInRange","const AliVParticle&,const AliVParticle&,Double_t&,Double_t&","-4,-2.5");
- task->AddBin("psi","y",ymin,ymax,"ICOMMON");
+ cr->AddCutCombination(rabs,eta,pairy);
- for ( Int_t i = 0; i < 6; ++i )
- {
- Double_t y = -4+i*0.25;
-
- task->AddBin("psi","y",y,y+0.25,"6PACK");
- }
+ cr->AddCutCombination(rabs,pairy);
-/*
- for ( Int_t i = 0; i < 20; ++i )
- {
- Double_t xmin = i*0.25;
-
- task->AddBin("psi","y vs pt",xmin,xmin+0.25,ymin,ymax);
+ cr->AddCutCombination(pairy);
+
+ cr->AddCutCombination(pairTrue);
+
+ task->AdoptSubAnalysis(minvAnalysis);
+ }
}
+
+ /// below are the kind of configurations that can be performed :
+ /// - adding cuts (at event, track or pair level)
+ /// - adding bins (in pt, y, centrality, etc...) for minv (and meanpt)
- for ( Int_t i = 0; i < 4; ++i )
+ AliAnalysisMuMuBinning* binning = task->Binning();
+
+ if (minvAnalysis)
{
- Double_t xmin = 5+i*1.0;
+ binning->AddBin("psi","pt");
+
+ // pt binning
+
+ binning->AddBin("psi","pt", 0.0, 1.0,"IGOR");
+ binning->AddBin("psi","pt", 1.0, 2.0,"IGOR");
+ binning->AddBin("psi","pt", 2.0, 3.0,"IGOR");
+ binning->AddBin("psi","pt", 3.0, 4.0,"IGOR");
+ binning->AddBin("psi","pt", 4.0, 5.0,"IGOR");
+ binning->AddBin("psi","pt", 5.0, 6.0,"IGOR");
+ binning->AddBin("psi","pt", 6.0, 7.0,"IGOR");
+ binning->AddBin("psi","pt", 7.0, 9.0,"IGOR");
+ binning->AddBin("psi","pt", 9.0,11.0,"IGOR");
+ binning->AddBin("psi","pt",11.0,15.0,"IGOR");
+ binning->AddBin("psi","pt",15.0,25.0,"IGOR");
+
+ // y binning
- task->AddBin("psi","y vs pt",xmin,xmin+1.0,ymin,ymax);
+ binning->AddBin("psi","y",-4,-2.5,"ILAB");
+
+ for ( Int_t i = 0; i < 6; ++i )
+ {
+ Double_t y = -4+i*0.25;
+
+ binning->AddBin("psi","y",y,y+0.25,"6PACK");
+ }
+
+ // nch binning
+ if (nchAnalysis)
+ {
+ binning->AddBin("psi","nch",0.0,30.0,"JAVI"); // 0 - 29
+ binning->AddBin("psi","nch",29.0,42.0,"JAVI"); // 30 - 41
+ binning->AddBin("psi","nch",41.0,56.0,"JAVI"); // 42 - 55
+ binning->AddBin("psi","nch",55.0,72.0,"JAVI"); // 56 - 72
+ binning->AddBin("psi","nch",72.0,301.0,"JAVI"); // 73 - 300
+ }
}
+
+ // v0 centrality binning
+
+ binning->AddBin("centrality","v0a");
+// binning->AddBin("centrality","v0a",0,5);
+// binning->AddBin("centrality","v0a",5,10);
+// binning->AddBin("centrality","v0a",10,20);
+// binning->AddBin("centrality","v0a",20,40);
+// binning->AddBin("centrality","v0a",40,60);
+// binning->AddBin("centrality","v0a",60,80);
+// binning->AddBin("centrality","v0a",80,100);
-*/
-/*
- task->CreateMesh("psi","pt","y");
-*/
-
+ // disable some histograms if we don't want them
task->DisableHistograms("^V02D");
task->DisableHistograms("^dca");
task->DisableHistograms("^Chi12");
task->DisableHistograms("^Rabs12");
-
+
+ // add the configured task to the analysis manager
mgr->AddTask(task);
- static int n(0);
-
- ++n;
-
- if ( n > 1 ) containerName += Form("%d",n);
-
// Create containers for input/output
AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();
AliAnalysisDataContainer *coutputHC =
- mgr->CreateContainer("HC",AliMergeableCollection::Class(),AliAnalysisManager::kOutputContainer,outputname);
+ mgr->CreateContainer("OC",AliMergeableCollection::Class(),AliAnalysisManager::kOutputContainer,outputname);
AliAnalysisDataContainer *coutputCC =
mgr->CreateContainer("CC",AliCounterCollection::Class(),AliAnalysisManager::kOutputContainer,outputname);
--- /dev/null
+#include "AliAnalysisMuMuBase.h"
+
+/**
+ *
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuBase
+ *
+ * Defines the interface of a sub-analysis to be steered by AliAnalysisTaskMuMu
+ *
+ * Daugther class has to implement one method :
+ *
+ * - \ref DefineHistogramCollection
+ *
+ * It may implement one or several of the FillHistosForXXX methods :
+ *
+ * - \ref FillHistosForEvent to fill histograms for one event
+ * - \ref FillHistosForMCEvent to fill histograms for one MC event
+ * - \ref FillHistosForTrack to fill histograms for one track
+ * - \ref FillHistosForPair to fill histograms for one muon track pair
+ *
+ * More rarely it may also implement :
+ *
+ * - \ref SetRun to do some changes when run number changes
+ * - \ref Terminate to finalize before ending
+ * - \ref SetEvent to e.g. append information to VEvent
+ *
+ * Daugther class can use the following methods :
+ *
+ * - \ref HasMC to know if MC information is available in the analyzed data
+ * - \ref Event to access the current event
+ * - \ref MCEvent to access to current MC event (if available)
+ *
+ * A few trivial cut methods (\ref AlwaysTrue and \ref AlwaysFalse) are defined as well and
+ * can be used to register some control cut combinations (see \ref AliAnalysisMuMuCutCombination)
+ *
+ */
+
+#include "AliMergeableCollection.h"
+#include "AliCounterCollection.h"
+#include "TList.h"
+#include "TObjString.h"
+#include "TMath.h"
+#include "TObjArray.h"
+#include "AliLog.h"
+#include "AliAnalysisMuMuBinning.h"
+#include "TH1F.h"
+#include "TH2F.h"
+#include "TProfile.h"
+#include "TRegexp.h"
+#include "AliVEvent.h"
+#include "AliAODEvent.h"
+#include "AliESDEvent.h"
+#include "AliLog.h"
+#include "AliAnalysisMuMuCutCombination.h"
+#include "AliAnalysisMuMuCutRegistry.h"
+
+ClassImp(AliAnalysisMuMuBase)
+
+namespace
+{
+ const char* MCINPUTPREFIX = "MCINPUT";
+};
+
+//_____________________________________________________________________________
+AliAnalysisMuMuBase::AliAnalysisMuMuBase()
+:
+TObject(),
+fEventCounters(0x0),
+fHistogramCollection(0x0),
+fBinning(0x0),
+fCutRegistry(0x0),
+fEvent(0x0),
+fMCEvent(0x0),
+fHistogramToDisable(0x0),
+fHasMC(kFALSE)
+{
+ /// default ctor
+}
+
+//_____________________________________________________________________________
+void
+AliAnalysisMuMuBase::CreateEventHistos(UInt_t dataType,
+ const char* what,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy, Double_t ymin, Double_t ymax) const
+{
+ /** Append histograms at the event level. Depending on dataType the created histograms
+ * are for real data only, MC data only, or both
+ */
+
+ if ( IsHistogramDisabled(hname) ) return;
+
+ TObjArray pathNames;
+ pathNames.SetOwner(kTRUE);
+
+ if ( dataType & kHistoForData )
+ {
+ pathNames.Add(new TObjString(Form("/%s",what)));
+ }
+ if ( ( dataType & kHistoForMCInput ) && HasMC() )
+ {
+ pathNames.Add(new TObjString(Form("/%s/%s",MCINPUTPREFIX,what)));
+ }
+
+ CreateHistos(pathNames,hname,htitle,nbinsx,xmin,xmax,nbinsy,ymin,ymax);
+}
+
+//_____________________________________________________________________________
+void
+AliAnalysisMuMuBase::CreateEventHistos(UInt_t dataType,
+ const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy, Double_t ymin, Double_t ymax) const
+{
+ /** Append histograms at the event level. Depending on dataType the created histograms
+ * are for real data only, MC data only, or both
+ */
+
+ if ( IsHistogramDisabled(hname) ) return;
+
+ TObjArray pathNames;
+ pathNames.SetOwner(kTRUE);
+
+ if ( dataType & kHistoForData )
+ {
+ pathNames.Add(new TObjString(Form("/%s/%s/%s",eventSelection,triggerClassName,centrality)));
+ }
+ if ( ( dataType & kHistoForMCInput ) && HasMC() )
+ {
+ pathNames.Add(new TObjString(Form("/%s/%s/%s/%s",MCINPUTPREFIX,eventSelection,triggerClassName,centrality)));
+ }
+
+ CreateHistos(pathNames,hname,htitle,nbinsx,xmin,xmax,nbinsy,ymin,ymax);
+}
+
+//_____________________________________________________________________________
+void
+AliAnalysisMuMuBase::CreateHistos(const TObjArray& paths,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy, Double_t ymin, Double_t ymax) const
+{
+ /// Create multiple copies of histogram hname, one per path
+
+ if ( IsHistogramDisabled(hname) ) return;
+
+ StdoutToAliDebug(1,paths.Print(););
+
+ TIter next(&paths);
+ TObjString* pathName;
+
+ while ( ( pathName = static_cast<TObjString*>(next()) ) )
+ {
+ TH1* h(0x0);
+
+ if ( nbinsy > 0 )
+ {
+ AliDebug(1,Form("Created TH2F %s/%s",pathName->String().Data(),hname));
+ h = new TH2F(hname,htitle,nbinsx,xmin,xmax,nbinsy,ymin,ymax);
+ }
+ else if ( nbinsy == 0 )
+ {
+ AliDebug(1,Form("Created TProfile %s/%s",pathName->String().Data(),hname));
+ h = new TProfile(hname,htitle,nbinsx,xmin,xmax,ymin,ymax);
+ h->Sumw2();
+ }
+ else
+ {
+ AliDebug(1,Form("Created TH1F %s/%s",pathName->String().Data(),hname));
+ h = new TH1F(hname,htitle,nbinsx,xmin,xmax);
+
+ if ( nbinsy < -1 )
+ {
+ h->Sumw2();
+ }
+ }
+
+ HistogramCollection()->Adopt(pathName->String().Data(),h);
+ }
+
+ StdoutToAliDebug(1,HistogramCollection()->Print("*"););
+}
+
+//_____________________________________________________________________________
+void
+AliAnalysisMuMuBase::CreateTrackHistos(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy, Double_t ymin, Double_t ymax) const
+{
+ /// Create n copies of an histogram (with name=hname, title=htitle, etc..)
+ /// where n = # of track cut combinations defined
+ /// see also CreateHistos
+
+
+ if ( IsHistogramDisabled(hname) ) return;
+
+ TObjArray pathNames;
+ pathNames.SetOwner(kTRUE);
+
+ TIter nextCutCombination(CutRegistry()->GetCutCombinations(AliAnalysisMuMuCutElement::kTrack));
+ AliAnalysisMuMuCutCombination* cutCombination;
+
+ while ( ( cutCombination = static_cast<AliAnalysisMuMuCutCombination*>(nextCutCombination())) )
+ {
+ pathNames.Add(new TObjString(Form("/%s/%s/%s/%s",eventSelection,triggerClassName,centrality,cutCombination->GetName())));
+ }
+
+ CreateHistos(pathNames,hname,htitle,nbinsx,xmin,xmax,nbinsy,ymin,ymax);
+}
+
+//_____________________________________________________________________________
+void
+AliAnalysisMuMuBase::CreatePairHistos(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy, Double_t ymin, Double_t ymax) const
+{
+ /// Create n copies of an histogram (with name=hname, title=htitle, etc..)
+ /// where n = # of track *pair* cut combinations defined
+ /// see also CreateHistos
+
+
+ if ( IsHistogramDisabled(hname) ) return;
+
+ TObjArray pathNames;
+ pathNames.SetOwner(kTRUE);
+
+ TIter nextCutCombination(CutRegistry()->GetCutCombinations(AliAnalysisMuMuCutElement::kTrackPair));
+ AliAnalysisMuMuCutCombination* cutCombination;
+
+ while ( ( cutCombination = static_cast<AliAnalysisMuMuCutCombination*>(nextCutCombination())) )
+ {
+ pathNames.Add(new TObjString(Form("/%s/%s/%s/%s",eventSelection,triggerClassName,centrality,cutCombination->GetName())));
+ }
+
+ CreateHistos(pathNames,hname,htitle,nbinsx,xmin,xmax,nbinsy,ymin,ymax);
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuBase::DisableHistograms(const char* pattern)
+{
+ /// Disable the histogramming of all the histograms matching the pattern
+
+ TString spattern(pattern);
+ if (spattern=="*")
+ {
+ delete fHistogramToDisable;
+ fHistogramToDisable = 0x0;
+ }
+
+ if (!fHistogramToDisable)
+ {
+ fHistogramToDisable = new TList;
+ fHistogramToDisable->SetOwner(kTRUE);
+ }
+
+ fHistogramToDisable->Add(new TObjString(spattern));
+}
+
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuBase::GetNbins(Double_t xmin, Double_t xmax, Double_t xstep)
+{
+ /// Compute number of bins to get a given step between each values in the xmin,xmax range
+ if ( TMath::AreEqualRel(xstep,0.0,1E-9) ) return 1;
+
+ return TMath::Nint(TMath::Abs((xmax-xmin)/xstep));
+}
+
+//_____________________________________________________________________________
+TH1* AliAnalysisMuMuBase::Histo(const char* eventSelection, const char* triggerClassName, const char* histoname)
+{
+ /// Get one histo back
+ return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s",eventSelection,triggerClassName,histoname)) : 0x0;
+}
+
+//_____________________________________________________________________________
+TH1* AliAnalysisMuMuBase::Histo(const char* eventSelection, const char* histoname)
+{
+ /// Get one histo back
+ return fHistogramCollection ? fHistogramCollection->Histo(eventSelection,histoname) : 0x0;
+}
+
+//_____________________________________________________________________________
+TH1* AliAnalysisMuMuBase::Histo(const char* eventSelection,
+ const char* triggerClassName,
+ const char* cent,
+ const char* histoname)
+{
+ /// Get one histo back
+ return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s",eventSelection,triggerClassName,cent),histoname) : 0x0;
+}
+
+//_____________________________________________________________________________
+TH1* AliAnalysisMuMuBase::Histo(const char* eventSelection,
+ const char* triggerClassName,
+ const char* cent,
+ const char* what,
+ const char* histoname)
+{
+ /// Get one histo back
+
+ return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s/%s",eventSelection,triggerClassName,cent,what),histoname) : 0x0;
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuBase::Init(AliCounterCollection& cc,
+ AliMergeableCollection& hc,
+ const AliAnalysisMuMuBinning& binning,
+ const AliAnalysisMuMuCutRegistry& registry)
+{
+ /// Set the internal references
+ fEventCounters = &cc;
+ fHistogramCollection = &hc;
+ fBinning = &binning;
+ fCutRegistry = ®istry;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuBase::IsHistogramDisabled(const char* hname) const
+{
+ /// Whether or not a given histogram (identified by its name)
+ /// is disabled or not
+
+ if ( !fHistogramToDisable )
+ {
+ return kFALSE;
+ }
+ TString shname(hname);
+ TIter next(fHistogramToDisable);
+ TObjString* str(0x0);
+
+ while ( ( str = static_cast<TObjString*>(next()) ) )
+ {
+ if ( shname.Contains(TRegexp(str->String()) ) )
+ {
+ return kTRUE;
+ }
+ }
+ return kFALSE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuBase::IsHistogrammingDisabled() const
+{
+ /// Whether or not *all* histograms are disabled
+
+ if ( fHistogramToDisable && fHistogramToDisable->GetEntries()==1 )
+ {
+ TObjString* r = static_cast<TObjString*>(fHistogramToDisable->First());
+ if ( r->String() == "*" )
+ {
+ return kTRUE;
+ }
+ }
+ return kFALSE;
+}
+
+//_____________________________________________________________________________
+TH1* AliAnalysisMuMuBase::MCHisto(const char* eventSelection, const char* triggerClassName, const char* histoname)
+{
+ /// Get one histo back
+ return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s/%s",MCINPUTPREFIX,eventSelection,triggerClassName,histoname)) : 0x0;
+}
+
+//_____________________________________________________________________________
+TH1* AliAnalysisMuMuBase::MCHisto(const char* eventSelection, const char* histoname)
+{
+ /// Get one histo back
+ return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s",MCINPUTPREFIX,eventSelection,histoname)) : 0x0;
+}
+
+//_____________________________________________________________________________
+TH1* AliAnalysisMuMuBase::MCHisto(const char* eventSelection,
+ const char* triggerClassName,
+ const char* cent,
+ const char* histoname)
+{
+ /// Get one histo back
+ return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s/%s",MCINPUTPREFIX,eventSelection,triggerClassName,cent),histoname) : 0x0;
+}
+
+//_____________________________________________________________________________
+TH1* AliAnalysisMuMuBase::MCHisto(const char* eventSelection,
+ const char* triggerClassName,
+ const char* cent,
+ const char* what,
+ const char* histoname)
+{
+ /// Get one histo back
+
+ return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s/%s/%s",MCINPUTPREFIX,eventSelection,triggerClassName,cent,what),histoname) : 0x0;
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuBase::SetEvent(AliVEvent* event, AliMCEvent* mcEvent)
+{
+ /// Set pointers to event (and mcEvent)
+ /// This is the place where a sub analysis might (if really needed)
+ /// append things to the event. Please DO NOT alter the original content,
+ /// only add to it. Unless of course you want to shoot yourself in the
+ /// foot...
+
+ fEvent = event;
+ fMCEvent = mcEvent;
+}
+
--- /dev/null
+#ifndef ALIANALYSISMUMUBASE_H
+#define ALIANALYSISMUMUBASE_H
+
+/**
+ *
+ * \class AliAnalysisMuMuBase
+ *
+ * \brief Base class of the sub-analysis for AliAnalysisTaskMuMu
+ *
+ * \author L. Aphecetche (Subatech)
+ */
+
+#include "TObject.h"
+#include "TString.h"
+
+class AliCounterCollection;
+class AliAnalysisMuMuBinning;
+class AliMergeableCollection;
+class AliVParticle;
+class AliVEvent;
+class AliMCEvent;
+class TH1;
+class AliInputEventHandler;
+class AliAnalysisMuMuCutRegistry;
+
+class AliAnalysisMuMuBase : public TObject
+{
+public:
+
+ AliAnalysisMuMuBase();
+ virtual ~AliAnalysisMuMuBase() {}
+
+ /** Define the histograms needed for the path starting at eventSelection/triggerClassName/centrality.
+ * This method has to ensure the histogram creation is performed only once !
+ */
+ virtual void DefineHistogramCollection(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality) = 0;
+
+ /** Fill histograms for one event */
+ virtual void FillHistosForEvent(const char* /*eventSelection*/,const char* /*triggerClassName*/,const char* /*centrality*/) {}
+
+ /** Fill histograms for one MC event */
+ virtual void FillHistosForMCEvent(const char* /*eventSelection*/,const char* /*triggerClassName*/,const char* /*centrality*/) {}
+
+ /** Fill histograms for one track */
+ virtual void FillHistosForTrack(const char* /*eventSelection*/,const char* /*triggerClassName*/,const char* /*centrality*/,
+ const char* /*trackCutName*/,
+ const AliVParticle& /*part*/) {}
+
+ /** Fill histograms for one track pair */
+ virtual void FillHistosForPair(const char* /*eventSelection*/,const char* /*triggerClassName*/,const char* /*centrality*/,
+ const char* /*pairCutName*/,
+ const AliVParticle& /*part1*/,
+ const AliVParticle& /*part2*/) {}
+
+ virtual void Init(AliCounterCollection& cc,
+ AliMergeableCollection& hc,
+ const AliAnalysisMuMuBinning& binning,
+ const AliAnalysisMuMuCutRegistry& cutRegister);
+
+ virtual void SetEvent(AliVEvent* event, AliMCEvent* mcEvent=0x0);
+
+ virtual Bool_t IsHistogramDisabled(const char* hname) const;
+
+ virtual Bool_t IsHistogrammingDisabled() const;
+
+ virtual void DisableHistograms(const char* pattern="*");
+
+ AliVEvent* Event() const { return fEvent; }
+
+ AliMCEvent* MCEvent() const { return fMCEvent; }
+
+ /// Called at each new run
+ void SetRun(const AliInputEventHandler* /*eventHandler*/) {}
+
+ void Terminate(Option_t* /*opt*/="") {}
+
+ enum EDataType
+ {
+ kHistoForMCInput = (1<<0),
+ kHistoForData = (1<<1)
+ };
+
+ void SetMC() { fHasMC = kTRUE; }
+
+ Bool_t HasMC() const { return fHasMC; }
+
+ Bool_t AlwaysTrue(const AliVEvent& /*event*/) const { return kTRUE; }
+ Bool_t AlwaysTrue(const AliVParticle& /*particle*/) const { return kTRUE; }
+ Bool_t AlwaysTrue(const AliVParticle& /*particle*/, const AliVParticle& /*particle*/) const { return kTRUE; }
+ void NameOfAlwaysTrue(TString& name) const { name = "ALL"; }
+
+ Bool_t AlwaysFalse(const AliVEvent& /*event*/) const { return kFALSE; }
+ Bool_t AlwaysFalse(const AliVParticle& /*particle*/) const { return kFALSE; }
+ Bool_t AlwaysFalse(const AliVParticle& /*particle*/, const AliVParticle& /*particle*/) const { return kFALSE; }
+ void NameOfAlwaysFalse(TString& name) const { name = "NONE"; }
+
+protected:
+
+ void CreateHistos(const TObjArray& paths,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy=-1, Double_t ymin=0.0, Double_t ymax=0.0) const;
+
+ void CreateEventHistos(UInt_t dataType,
+ const char* what,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy=-1, Double_t ymin=0.0, Double_t ymax=0.0) const;
+
+ void CreateEventHistos(UInt_t dataType,
+ const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy=-1, Double_t ymin=0.0, Double_t ymax=0.0) const;
+
+
+ void CreateTrackHistos(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy=-1, Double_t ymin=0.0, Double_t ymax=0.0) const;
+
+ void CreatePairHistos(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy=-1, Double_t ymin=0.0, Double_t ymax=0.0) const;
+
+ TH1* Histo(const char* eventSelection, const char* histoname);
+ TH1* Histo(const char* eventSelection, const char* triggerClassName, const char* histoname);
+ TH1* Histo(const char* eventSelection, const char* triggerClassName, const char* cent, const char* histoname);
+ TH1* Histo(const char* eventSelection, const char* triggerClassName, const char* cent,
+ const char* what, const char* histoname);
+
+ TH1* MCHisto(const char* eventSelection, const char* histoname);
+ TH1* MCHisto(const char* eventSelection, const char* triggerClassName, const char* histoname);
+ TH1* MCHisto(const char* eventSelection, const char* triggerClassName, const char* cent, const char* histoname);
+ TH1* MCHisto(const char* eventSelection, const char* triggerClassName, const char* cent,
+ const char* what, const char* histoname);
+
+ Int_t GetNbins(Double_t xmin, Double_t xmax, Double_t xstep);
+
+ AliCounterCollection* CounterCollection() const { return fEventCounters; }
+ AliMergeableCollection* HistogramCollection() const { return fHistogramCollection; }
+ const AliAnalysisMuMuBinning* Binning() const { return fBinning; }
+ const AliAnalysisMuMuCutRegistry* CutRegistry() const { return fCutRegistry; }
+
+private:
+
+ AliCounterCollection* fEventCounters; //! event counters
+ AliMergeableCollection* fHistogramCollection; //! collection of histograms
+ const AliAnalysisMuMuBinning* fBinning; //! binning for particles
+ const AliAnalysisMuMuCutRegistry* fCutRegistry; //! registry of cut combinations
+ AliVEvent* fEvent; //! current event
+ AliMCEvent* fMCEvent; //! current MC event
+ TList* fHistogramToDisable; // list of regexp of histo name to disable
+ Bool_t fHasMC; // whether or not we're dealing with MC data
+
+ ClassDef(AliAnalysisMuMuBase,1) // base class for a companion class to AliAnalysisMuMu
+};
+
+#endif
+
void AliAnalysisMuMuBinning::AddBin(const AliAnalysisMuMuBinning::Range& bin)
{
/// add one bin
- AddBin(bin.Particle().Data(),bin.Type().Data(),
+ AddBin(bin.What().Data(),bin.Quantity().Data(),
bin.Xmin(),bin.Xmax(),
bin.Ymin(),bin.Ymax(),bin.Flavour());
}
//______________________________________________________________________________
-void AliAnalysisMuMuBinning::AddBin(const char* particle, const char* type,
+void AliAnalysisMuMuBinning::AddBin(const char* what, const char* quantity,
Double_t xmin, Double_t xmax,
Double_t ymin, Double_t ymax,
const char* flavour)
{
/// Add a bin
- /// Note that particle and type are not case sensitive.
+ /// Note that what and Quantity are not case sensitive.
if (!fBins)
{
fBins = new TMap;
fBins->SetOwnerKeyValue(kTRUE,kTRUE);
}
- TString sparticle(particle);
- sparticle.ToUpper();
+ TString swhat(what);
+ swhat.ToUpper();
- TString stype(type);
- stype.ToUpper();
+ TString sQuantity(quantity);
+ sQuantity.ToUpper();
- TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(sparticle.Data()));
+ TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(swhat.Data()));
if (!b)
{
b = new TObjArray;
b->SetOwner(kTRUE);
- fBins->Add(new TObjString(sparticle),b);
+ fBins->Add(new TObjString(swhat),b);
}
- Range* r = new Range(sparticle.Data(),stype.Data(),xmin,xmax,ymin,ymax,flavour);
+ Range* r = new Range(swhat.Data(),sQuantity.Data(),xmin,xmax,ymin,ymax,flavour);
if ( b->FindObject(r) )
{
- AliDebug(1,"Trying to add an already existing bin. Not doing it.");
+ AliDebug(1,Form("Trying to add an already existing bin : %s. Not doing it.",r->AsString().Data()));
delete r;
}
else
{
b->Add(r);
- TString btype(Form("%s-%s",sparticle.Data(),stype.Data()));
+ TString bQuantity(Form("%s-%s",swhat.Data(),sQuantity.Data()));
TString name(GetName());
- if ( !name.Contains(btype) )
+ if ( !name.Contains(bQuantity) )
{
if (name.Length()>0)
{
name += " ";
}
- name += btype;
+ name += bQuantity;
SetName(name);
}
}
TObjArray* a = new TObjArray;
a->SetOwner(kTRUE);
- TIter nextParticle(fBins);
- TObjString* particle;
+ TIter nextwhat(fBins);
+ TObjString* what;
- while ( ( particle = static_cast<TObjString*>(nextParticle()) ) )
+ while ( ( what = static_cast<TObjString*>(nextwhat()) ) )
{
- TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(particle->String().Data()));
+ TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(what->String().Data()));
TIter next(b);
Range* r;
}
//______________________________________________________________________________
-TObjArray* AliAnalysisMuMuBinning::CreateBinObjArray(const char* particle) const
+TObjArray* AliAnalysisMuMuBinning::CreateBinObjArray(const char* what) const
{
- /// Get the list of bins for a given particle
+ /// Get the list of bins for a given what
/// The returned array must be deleted by the user
if (!fBins) return 0x0;
TObjArray* a = new TObjArray;
a->SetOwner(kTRUE);
- TString sparticle(particle);
- sparticle.ToUpper();
+ TString swhat(what);
+ swhat.ToUpper();
- TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(sparticle.Data()));
+ TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(swhat.Data()));
if (!b) return 0x0;
TIter next(b);
//______________________________________________________________________________
-TObjArray* AliAnalysisMuMuBinning::CreateBinObjArray(const char* particle, const char* type, const char* flavour) const
+TObjArray* AliAnalysisMuMuBinning::CreateBinObjArray(const char* what, const char* quantity, const char* flavour) const
{
- /// Get the list of bins for a given particle and given type
+ /// Get the list of bins for a given what and given Quantity
/// The returned array must be deleted by the user
- /// Type can be a single type or several types separated by comma
+ /// Quantity can be a single Quantity or several Quantitys separated by comma
TObjArray* a = new TObjArray;
a->SetOwner(kTRUE);
- TString sparticle(particle);
- sparticle.ToUpper();
+ TString swhat(what);
+ swhat.ToUpper();
- TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(sparticle.Data()));
+ TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(swhat.Data()));
if (!b) return 0x0;
TIter next(b);
Range* r;
- TString stype(type);
- stype.ToUpper();
+ TString sQuantity(quantity);
+ sQuantity.ToUpper();
TString sflavour(flavour);
- TObjArray* types = stype.Tokenize(",");
- TObjString* onetype;
- TIter nextType(types);
+ TObjArray* Quantitys = sQuantity.Tokenize(",");
+ TObjString* oneQuantity;
+ TIter nextQuantity(Quantitys);
while ( ( r = static_cast<Range*>(next()) ) )
{
- nextType.Reset();
- while ( ( onetype = static_cast<TObjString*>(nextType()) ) )
+ nextQuantity.Reset();
+ while ( ( oneQuantity = static_cast<TObjString*>(nextQuantity()) ) )
{
- if ( r->Type() == onetype->String() &&
+ if ( r->Quantity() == oneQuantity->String() &&
( ( sflavour.Length() > 0 && r->Flavour() == sflavour.Data() ) || sflavour.Length()==0 ) )
{
a->Add(r->Clone());
a = 0x0;
}
- delete types;
+ delete Quantitys;
return a;
}
//______________________________________________________________________________
-void AliAnalysisMuMuBinning::CreateMesh(const char* particle,
- const char* type1, const char* type2,
+void AliAnalysisMuMuBinning::CreateMesh(const char* what,
+ const char* quantity1, const char* quantity2,
const char* flavour,
Bool_t remove12)
{
- /// Create 2D bins from existing 1d ones of type1 and type2
- TObjArray* a1 = CreateBinObjArray(particle,type1,flavour);
+ /// Create 2D bins from existing 1d ones of Quantity1 and Quantity2
+ TObjArray* a1 = CreateBinObjArray(what,quantity1,flavour);
if (!a1)
{
- AliError(Form("No bin for type %s. Done nothing.",type1));
+ AliError(Form("No bin for Quantity %s. Done nothing.",quantity1));
return;
}
- TObjArray* a2 = CreateBinObjArray(particle,type2,flavour);
+ TObjArray* a2 = CreateBinObjArray(what,quantity2,flavour);
if (!a2)
{
- AliError(Form("No bin for type %s. Done nothing.",type2));
+ AliError(Form("No bin for Quantity %s. Done nothing.",quantity2));
return;
}
- TString meshType(Form("%s VS %s - %s",type1,type2,flavour));
+ TString meshQuantity(Form("%s VS %s - %s",quantity1,quantity2,flavour));
for ( Int_t i1 = 0; i1 <= a1->GetLast(); ++i1 )
{
{
Range* r2 = static_cast<Range*>(a2->At(i2));
- AddBin(particle,meshType,r2->Xmin(),r2->Xmax(),r1->Xmin(),r1->Xmax(),Form("%s VS %s",r1->Flavour().Data(),r2->Flavour().Data()));
+ AddBin(what,meshQuantity,r2->Xmin(),r2->Xmax(),r1->Xmin(),r1->Xmax(),Form("%s VS %s",r1->Flavour().Data(),r2->Flavour().Data()));
}
}
if ( remove12 )
{
- TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(particle));
+ TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(what));
TIter next(b);
Range* r;
- TString stype1(type1);
- TString stype2(type2);
+ TString sQuantity1(quantity1);
+ TString sQuantity2(quantity2);
- stype1.ToUpper();
- stype2.ToUpper();
+ sQuantity1.ToUpper();
+ sQuantity2.ToUpper();
while ( ( r = static_cast<Range*>(next())) )
{
- if ( r->Type() == type1 ||
- r->Type() == type2 )
+ if ( r->Quantity() == quantity1 ||
+ r->Quantity() == quantity2 )
{
b->Remove(r);
}
}
//______________________________________________________________________________
-TObjArray* AliAnalysisMuMuBinning::CreateParticleArray() const
+TObjArray* AliAnalysisMuMuBinning::CreateWhatArray() const
{
- /// Create a TObjString array with the names of the particle we're holding results for
+ /// Create a TObjString array with the names of the what we're holding results for
/// Returned array must be delete by user
- TObjArray* particleArray(0x0);
+ TObjArray* whatArray(0x0);
- TIter nextParticle(fBins);
- TObjString* particle;
+ TIter nextwhat(fBins);
+ TObjString* what;
- while ( ( particle = static_cast<TObjString*>(nextParticle()) ) )
+ while ( ( what = static_cast<TObjString*>(nextwhat()) ) )
{
- if (!particleArray)
+ if (!whatArray)
{
- particleArray = new TObjArray;
- particleArray->SetOwner(kTRUE);
+ whatArray = new TObjArray;
+ whatArray->SetOwner(kTRUE);
}
- particleArray->Add(new TObjString(*particle));
+ whatArray->Add(new TObjString(*what));
}
- return particleArray;
+ return whatArray;
}
//______________________________________________________________________________
-TObjArray* AliAnalysisMuMuBinning::CreateTypeArray() const
+TObjArray* AliAnalysisMuMuBinning::CreateQuantityArray() const
{
- /// Create a TObjString array with the names of the binning types
+ /// Create a TObjString array with the names of the binning Quantitys
/// Returned array must be delete by user
- TObjArray* typeArray(0x0);
+ TObjArray* QuantityArray(0x0);
- TIter nextParticle(fBins);
- TObjString* particle;
+ TIter nextwhat(fBins);
+ TObjString* what;
- while ( ( particle = static_cast<TObjString*>(nextParticle()) ) )
+ while ( ( what = static_cast<TObjString*>(nextwhat()) ) )
{
- TObjArray* particles = static_cast<TObjArray*>(fBins->GetValue(particle->String()));
+ TObjArray* whats = static_cast<TObjArray*>(fBins->GetValue(what->String()));
- TIter next(particles);
+ TIter next(whats);
Range* r;
while ( ( r = static_cast<Range*>(next())) )
{
- if (!typeArray)
+ if (!QuantityArray)
{
- typeArray = new TObjArray;
- typeArray->SetOwner(kTRUE);
+ QuantityArray = new TObjArray;
+ QuantityArray->SetOwner(kTRUE);
}
- if ( !typeArray->FindObject(r->Type()) )
+ if ( !QuantityArray->FindObject(r->Quantity()) )
{
- typeArray->Add(new TObjString(r->Type()));
+ QuantityArray->Add(new TObjString(r->Quantity()));
}
}
}
- return typeArray;
+ return QuantityArray;
}
//______________________________________________________________________________
//______________________________________________________________________________
AliAnalysisMuMuBinning*
-AliAnalysisMuMuBinning::Project(const char* particle, const char* type, const char* flavour) const
+AliAnalysisMuMuBinning::Project(const char* what, const char* quantity, const char* flavour) const
{
- /// Create a sub-binning object with only the bins pertaining to (particle,type)
+ /// Create a sub-binning object with only the bins pertaining to (what,Quantity)
- TObjArray* bins = CreateBinObjArray(particle,type,flavour);
+ TObjArray* bins = CreateBinObjArray(what,quantity,flavour);
if (!bins) return 0x0;
AliAnalysisMuMuBinning* p = new AliAnalysisMuMuBinning;
TIter next(bins);
AliAnalysisMuMuBinning::Range* bin;
- TString stype(type);
- stype.ToUpper();
+ TString sQuantity(quantity);
+ sQuantity.ToUpper();
while ( ( bin = static_cast<AliAnalysisMuMuBinning::Range*>(next())) )
{
- assert (bin->Type()==stype && bin->Flavour()==flavour);
+ if (bin->Quantity()!=sQuantity || bin->Flavour()!=flavour)
{
- p->AddBin(particle,bin->Type(),bin->Xmin(),bin->Xmax(),bin->Ymin(),bin->Ymax(),bin->Flavour().Data());
+ AliDebug(1,Form("sQuantity=%s flavour=%s bin=%s => skip",sQuantity.Data(),flavour,bin->AsString().Data()));
+ continue;
+ }
+ {
+ p->AddBin(what,bin->Quantity(),bin->Xmin(),bin->Xmax(),bin->Ymin(),bin->Ymax(),bin->Flavour().Data());
}
}
return;
}
- TIter nextParticle(fBins);
+ TIter nextwhat(fBins);
TObjString* str;
- while ( ( str = static_cast<TObjString*>(nextParticle()) ) )
+ while ( ( str = static_cast<TObjString*>(nextwhat()) ) )
{
- std::cout << "Particle : " << str->String().Data() << std::endl;
+ std::cout << "what : " << str->String().Data() << std::endl;
TObjArray* b = static_cast<TObjArray*>(fBins->GetValue(str->String()));
TIter next(b);
Range* r(0x0);
//______________________________________________________________________________
//______________________________________________________________________________
-AliAnalysisMuMuBinning::Range::Range(const char* particle, const char* type,
+AliAnalysisMuMuBinning::Range::Range(const char* what, const char* quantity,
Double_t xmin, Double_t xmax,
Double_t ymin, Double_t ymax,
const char* flavour)
-: TObject(), fParticle(particle), fType(type),
+: TObject(), fWhat(what), fQuantity(quantity),
fXmin(xmin), fXmax(xmax), fYmin(ymin), fYmax(ymax),
fFlavour(flavour)
{
/// ctor
- fParticle.ToUpper();
- fType.ToUpper();
+ fWhat.ToUpper();
+ fQuantity.ToUpper();
}
//______________________________________________________________________________
{
/// Return a string representation of this range
- if ( IsNullObject()) return "";
+ if ( IsIntegrated()) return Quantity().Data();
TString s;
if ( fFlavour.Length() > 0 )
{
- s.Form("%s_%s_%05.2f_%05.2f",Type().Data(),Flavour().Data(),Xmin(),Xmax());
+ s.Form("%s_%s_%05.2f_%05.2f",Quantity().Data(),Flavour().Data(),Xmin(),Xmax());
}
else
{
- s.Form("%s_%05.2f_%05.2f",Type().Data(),Xmin(),Xmax());
+ s.Form("%s_%05.2f_%05.2f",Quantity().Data(),Xmin(),Xmax());
}
if (Is2D())
// than obj, 0 if objects are equal and 1 if this is larger than obj.
const Range* other = static_cast<const Range*>(obj);
- int s = strcmp(Particle().Data(),other->Particle().Data());
+ int s = strcmp(What().Data(),other->What().Data());
if ( s ) return s;
- s = strcmp(Type().Data(),other->Type().Data());
+ s = strcmp(Quantity().Data(),other->Quantity().Data());
if (s) return s;
if (s) return s;
- if ( IsNullObject() ) return 0;
+// if ( IsIntegrated() && other->IsIntegrated() ) return 0;
if ( Xmin() < other->Xmin() )
{
{
return 1;
}
- }
+ }
}
}
return 0;
/// If Range is 1D, returns true if x is in range
/// If Range is 2D, returns true if (x,y) is in range
- if ( IsNullObject() )
+ if ( IsIntegrated() )
{
return kTRUE;
}
{
if ( Is2D() )
{
- return ( x > Xmin() && x < Xmax() && y > Ymin() && y < Ymax());
+ return ( x >= Xmin() && x < Xmax() && y >= Ymin() && y < Ymax());
}
else
{
- return ( x > Xmin() && x < Xmax() );
+ return ( x >= Xmin() && x < Xmax() );
}
}
}
//______________________________________________________________________________
-Bool_t AliAnalysisMuMuBinning::Range::IsNullObject() const
+Bool_t AliAnalysisMuMuBinning::Range::IsIntegrated() const
{
- /// Whether we're a null object or not
+ /// Whether we're a null object (aka integrated) or not
return
Xmin() >= TMath::Limits<Double_t>::Max() &&
Ymin() >= TMath::Limits<Double_t>::Max() &&
{
/// Output to stdout
- if (IsNullObject())
+ if (IsIntegrated())
{
- std::cout << Form("%s : %s : NullObject",Particle().Data(),Type().Data()) << std::endl;
+ std::cout << Form("%s : %s : INTEGRATED",What().Data(),Quantity().Data()) << std::endl;
return;
}
- std::cout << Form("%s : %s : %5.2f : %5.2f",Particle().Data(),Type().Data(),Xmin(),Xmax());
+ std::cout << Form("%s : %s : %5.2f : %5.2f",What().Data(),Quantity().Data(),Xmin(),Xmax());
if (Is2D())
{
void AddBin(const AliAnalysisMuMuBinning::Range& bin);
- void AddBin(const char* particle, const char* type,
+ void AddBin(const char* what, const char* quantity,
Double_t xmin=TMath::Limits<Double_t>::Max(),
Double_t xmax=TMath::Limits<Double_t>::Max(),
- Double_t ymin=TMath::Limits<Double_t>::Max(),
- Double_t ymax=TMath::Limits<Double_t>::Max(),
+ const char* flavour="")
+ { AddBin(what,quantity,xmin,xmax,TMath::Limits<Double_t>::Max(),TMath::Limits<Double_t>::Max(),flavour); }
+
+ void AddBin(const char* what, const char* quantity,
+ Double_t xmin,
+ Double_t xmax,
+ Double_t ymin,
+ Double_t ymax,
const char* flavour="");
- TObjArray* CreateParticleArray() const;
+ TObjArray* CreateWhatArray() const;
- TObjArray* CreateTypeArray() const;
+ TObjArray* CreateQuantityArray() const;
Double_t* CreateBinArray() const;
TObjArray* CreateBinObjArray() const;
- TObjArray* CreateBinObjArray(const char* particle) const;
- TObjArray* CreateBinObjArray(const char* particle, const char* type, const char* flavour) const;
+ TObjArray* CreateBinObjArray(const char* what) const;
+ TObjArray* CreateBinObjArray(const char* what, const char* quantity, const char* flavour) const;
- AliAnalysisMuMuBinning* Project(const char* particle, const char* type, const char* flavour="") const;
+ AliAnalysisMuMuBinning* Project(const char* what, const char* quantity, const char* flavour="") const;
virtual void Print(Option_t* opt="") const;
- void CreateMesh(const char* particle, const char* type1, const char* type2, const char* flavour="", Bool_t remove12=kFALSE);
+ void CreateMesh(const char* what, const char* quantity1, const char* quantity2, const char* flavour="", Bool_t remove12=kFALSE);
Long64_t Merge(TCollection* list);
public:
- Range(const char* particle="",const char* type="",
+ Range(const char* what="",const char* quantity="",
Double_t xmin=TMath::Limits<Double_t>::Max(),
Double_t xmax=TMath::Limits<Double_t>::Max(),
Double_t ymin=TMath::Limits<Double_t>::Max(),
bool operator!=(const Range& other) const { return !(*this==other); }
- Bool_t IsNullObject() const;
-
- TString Type() const { return fType; }
- TString Particle() const { return fParticle; }
+ Bool_t IsIntegrated() const;
+
+ TString Quantity() const { return fQuantity; }
+ TString What() const { return fWhat; }
Double_t Xmin() const { return fXmin; }
Double_t Xmax() const { return fXmax; }
Double_t Ymin() const { return fYmin; }
Bool_t Is2D() const { return fYmax > fYmin; }
- const char* GetName() const { return Type().Data(); }
+ const char* GetName() const { return What().Data(); }
TString AsString() const;
TString Flavour() const { return fFlavour; }
private:
- TString fParticle; // particle
- TString fType; // binning type (e.g. pt, y, phi)
+ TString fWhat; // what this range is about (e.g. J/psi particle, event, etc...)
+ TString fQuantity; // binning type (e.g. pt, y, phi)
Double_t fXmin; // x-min of the range
Double_t fXmax; // x-max of the range
Double_t fYmin; // x-min of the range
Double_t fYmax; // x-max of the range
TString fFlavour; // flavour (if any) this range, e.g. coarse, fine, etc...
- ClassDef(AliAnalysisMuMuBinning::Range,2)
+ ClassDef(AliAnalysisMuMuBinning::Range,3)
};
private:
- TMap* fBins; // list of bins (particle -> list of bins) = (TObjString -> TObjArray)
+ TMap* fBins; // list of bins (what -> list of bins) = (TObjString -> TObjArray)
- ClassDef(AliAnalysisMuMuBinning,1) // custom binning for MuMu analysis
+ ClassDef(AliAnalysisMuMuBinning,2) // custom binning for MuMu analysis
};
#endif
--- /dev/null
+#include "AliAnalysisMuMuCutCombination.h"
+
+/**
+ *
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuCutCombination
+ *
+ * A cut combination is the real cut class that is used in the sub-analysis. It is composed
+ * of one or several AliAnalysisMuMuCutElement.
+ *
+ * Unlike the cut elements, it can be of several types at the same time (i.e. it can
+ * be an event cutter and a track cutter for instance). The work is done in the
+ * Pass method(s).
+ *
+ */
+
+#include "AliAnalysisMuMuCutElement.h"
+#include "TList.h"
+#include "Riostream.h"
+#include "AliInputEventHandler.h"
+#include "AliLog.h"
+
+ClassImp(AliAnalysisMuMuCutCombination)
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutCombination::AliAnalysisMuMuCutCombination()
+: TObject(), fCuts(0x0), fName(""),
+fIsEventCutter(kFALSE), fIsEventHandlerCutter(kFALSE),
+fIsTrackCutter(kFALSE), fIsTrackPairCutter(kFALSE),
+fIsTriggerClassCutter(kFALSE)
+{
+ /// Default ctor.
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutCombination::~AliAnalysisMuMuCutCombination()
+{
+ /// Dtor
+ delete fCuts;
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuCutCombination::Add(AliAnalysisMuMuCutElement* ce)
+{
+ /** Add a cut element to this combination, if the cut is not void and
+ * not already part of the combination
+ */
+
+ if (!ce || !ce->IsValid()) return;
+
+ if (!fCuts)
+ {
+ fCuts = new TObjArray;
+ fCuts->SetOwner(kFALSE);
+ fIsEventCutter = ce->IsEventCutter();
+ fIsEventHandlerCutter = ce->IsEventHandlerCutter();
+ fIsTrackCutter = ce->IsTrackCutter();
+ fIsTrackPairCutter = ce->IsTrackPairCutter();
+ fIsTriggerClassCutter = ce->IsTriggerClassCutter();
+ }
+
+ if (!fCuts->FindObject(ce))
+ {
+ fCuts->Add(ce);
+ fName += ce->GetName();
+
+ fIsEventCutter = fIsEventCutter || ce->IsEventCutter();
+ fIsEventHandlerCutter = fIsEventHandlerCutter || ce->IsEventHandlerCutter();
+ fIsTrackCutter = fIsTrackCutter || ce->IsTrackCutter();
+ fIsTrackPairCutter = fIsTrackPairCutter || ce->IsTrackPairCutter();
+ fIsTriggerClassCutter = fIsTriggerClassCutter || ce->IsTriggerClassCutter();
+
+ }
+
+ // update the name
+
+ if ( IsTrackPairCutter() )
+ {
+ if ( fName[0] == 's' )
+ {
+ fName[0] = 'p';
+ }
+ else if ( fName[0] == 'p')
+ {
+ // already ok
+ }
+ else
+ {
+ TString tmp = fName;
+ fName = "p";
+ fName += tmp;
+ }
+ }
+ else if ( IsTrackCutter() )
+ {
+ if ( fName[0] == 's')
+ {
+ // already ok
+ }
+ else
+ {
+ TString tmp = fName;
+ fName = "s";
+ fName += tmp;
+ }
+ }
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutCombination::IsEqual(const TObject* obj) const
+{
+ /// Whether or not we are the same cut combination as obj
+
+ if ( obj->IsA() != AliAnalysisMuMuCutCombination::Class() )
+ {
+ return kFALSE;
+ }
+
+ const AliAnalysisMuMuCutCombination* other = static_cast<const AliAnalysisMuMuCutCombination*>(obj);
+
+ if ( IsEventCutter() != other->IsEventCutter() ) return kFALSE;
+ if ( IsTrackCutter() != other->IsTrackCutter() ) return kFALSE;
+ if ( IsTrackPairCutter() != other->IsTrackPairCutter() ) return kFALSE;
+ if ( IsTriggerClassCutter() != other->IsTriggerClassCutter() ) return kFALSE;
+
+ if ( fCuts && !other->fCuts ) return kFALSE;
+ if ( !fCuts && other->fCuts ) return kFALSE;
+
+ if ( fCuts->GetEntries() != other->fCuts->GetEntries() ) return kFALSE;
+
+ // ok, looks similar so far, now have compute the set of cuts in common
+ // (whatever the order) to see if they really are the same combination or not
+
+ Int_t n1in2(0);
+ Int_t n2in1(0);
+
+ for ( Int_t i = 0; i <= fCuts->GetLast(); ++i )
+ {
+ AliAnalysisMuMuCutElement* thisCuti = static_cast<AliAnalysisMuMuCutElement*>(fCuts->At(i));
+
+ if ( other->fCuts->FindObject(thisCuti) )
+ {
+ ++n1in2;
+ }
+ }
+
+ for ( Int_t i = 0; i <= fCuts->GetLast(); ++i )
+ {
+ AliAnalysisMuMuCutElement* otherCuti = static_cast<AliAnalysisMuMuCutElement*>(other->fCuts->At(i));
+
+ if ( fCuts->FindObject(otherCuti) )
+ {
+ ++n2in1;
+ }
+ }
+
+ return (n1in2==n2in1 && n1in2==fCuts->GetLast()+1);
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutCombination::Pass(const AliInputEventHandler& eventHandler) const
+{
+ /// Whether or not the event handler is passing the cut
+
+ if (!fCuts) return kFALSE;
+ TIter next(fCuts);
+ AliAnalysisMuMuCutElement* ce;
+
+ const AliVEvent* event = eventHandler.GetEvent();
+
+ Bool_t passEvent(kTRUE);
+ Bool_t passEventHandler(kTRUE);
+
+ while ( ( ce = static_cast<AliAnalysisMuMuCutElement*>(next()) ) )
+ {
+ if ( ce->IsEventCutter() && !ce->Pass(*event) )
+ {
+ passEvent = kFALSE;
+ }
+
+ if ( ce->IsEventHandlerCutter() && !ce->Pass(eventHandler) )
+ {
+ passEventHandler = kFALSE;
+ }
+ }
+
+ if ( IsEventCutter() && IsEventHandlerCutter() )
+ {
+ return passEvent && passEventHandler;
+ }
+
+ if ( IsEventHandlerCutter() )
+ {
+ return passEventHandler;
+ }
+
+ if ( IsEventCutter() )
+ {
+ return passEvent;
+ }
+
+ return kFALSE;
+}
+
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutCombination::Pass(const AliVParticle& particle) const
+{
+ /// Whether or not the particle is passing the cut
+
+ if (!fCuts) return kFALSE;
+ TIter next(fCuts);
+ AliAnalysisMuMuCutElement* ce;
+
+ while ( ( ce = static_cast<AliAnalysisMuMuCutElement*>(next()) ) )
+ {
+ if (ce->IsTrackCutter() && !ce->Pass(particle))
+ {
+ return kFALSE;
+ }
+ }
+
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutCombination::Pass(const AliVParticle& p1, const AliVParticle& p2) const
+{
+ /// Whether or not the particle pair is passing the cut
+
+ if (!fCuts) return kFALSE;
+ TIter next(fCuts);
+ AliAnalysisMuMuCutElement* ce;
+
+ while ( ( ce = static_cast<AliAnalysisMuMuCutElement*>(next()) ) )
+ {
+ if (ce->IsTrackPairCutter() && !ce->Pass(p1,p2))
+ {
+ return kFALSE;
+ }
+ }
+
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutCombination::Pass(const TString& firedTriggerClasses,
+ TString& acceptedTriggerClasses,
+ UInt_t L0, UInt_t L1, UInt_t L2) const
+{
+ /** Whether or not the firedTriggerClasses pass the cut.
+ * \param firedTriggerClasses (input) list of fired trigger classes (separated by space)
+ * \param acceptedTriggerClasses (output) list of accepted classes
+ * \param L0 (input, optional) level 0 trigger mask
+ * \param L1 (input, optional) level 1 trigger mask
+ * \param L2 (input, optional) level 2 trigger mask
+ */
+
+ if (!fCuts) return kFALSE;
+ TIter next(fCuts);
+ AliAnalysisMuMuCutElement* ce;
+ Bool_t rv(kFALSE);
+
+ // contrary to the other cut types, here we make a full loop on all
+ // the cuts, as we need to give each cut a chance to update the acceptedTriggerClasses
+ // string
+
+ acceptedTriggerClasses = "";
+
+ while ( ( ce = static_cast<AliAnalysisMuMuCutElement*>(next()) ) )
+ {
+ TString tmp;
+
+ if (ce->IsTriggerClassCutter() && ce->Pass(firedTriggerClasses,tmp,L0,L1,L2))
+ {
+ acceptedTriggerClasses += tmp;
+ acceptedTriggerClasses += " ";
+ rv = kTRUE;
+ }
+ }
+
+ return rv;
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuCutCombination::Print(Option_t* space) const
+{
+ /// Printout of the cut combination
+ std::cout << Form("%s(%p) [",GetName(),this);
+ if ( IsEventCutter() ) std::cout << " E";
+ if ( IsEventHandlerCutter() ) std::cout << " EH";
+ if ( IsTrackCutter() ) std::cout << " T";
+ if ( IsTrackPairCutter() ) std::cout << " TP";
+ if ( IsTriggerClassCutter() ) std::cout << " TC";
+ std::cout << " ]" << std::endl;
+
+ TIter next(fCuts);
+ AliAnalysisMuMuCutElement* ce;
+
+ while ( ( ce = static_cast<AliAnalysisMuMuCutElement*>(next()) ) )
+ {
+ std::cout << space;
+ ce->Print();
+ }
+}
+
--- /dev/null
+#ifndef ALIANALYSISMUMUCUTCOMBINATION_H
+#define ALIANALYSISMUMUCUTCOMBINATION_H
+
+/**
+ *
+ * \class AliAnalysisMuMuCutCombination
+ *
+ * \brief Defines a cut by combining several cut elements
+ *
+ * \author L. Aphecetche (Subatech)
+ */
+
+#include "TObject.h"
+#include "TString.h"
+
+class AliAnalysisMuMuCutElement;
+class AliVEvent;
+class AliInputEventHandler;
+class AliVParticle;
+
+class AliAnalysisMuMuCutCombination : public TObject
+{
+public:
+ AliAnalysisMuMuCutCombination();
+ virtual ~AliAnalysisMuMuCutCombination();
+
+ void Add(AliAnalysisMuMuCutElement* ce);
+
+ Bool_t Pass(const AliInputEventHandler& eventHandler) const;
+
+ Bool_t Pass(const AliVParticle& particle) const;
+
+ Bool_t Pass(const AliVParticle& p1, const AliVParticle& p2) const;
+
+ Bool_t Pass(const TString& firedTriggerClasses, TString& acceptedTriggerClasses,
+ UInt_t L0, UInt_t L1, UInt_t L2) const;
+
+ const char* GetName() const { return fName.Data(); }
+
+ Bool_t IsEventCutter() const { return fIsEventCutter; }
+ Bool_t IsEventHandlerCutter() const { return fIsEventHandlerCutter; }
+ Bool_t IsTrackCutter() const { return fIsTrackCutter; }
+ Bool_t IsTrackPairCutter() const { return fIsTrackPairCutter; }
+ Bool_t IsTriggerClassCutter() const { return fIsTriggerClassCutter; }
+
+ void Print(Option_t* opt="") const;
+
+ Bool_t IsEqual(const TObject* obj) const;
+
+private:
+ /// not implemented on purpose
+ AliAnalysisMuMuCutCombination(const AliAnalysisMuMuCutCombination& rhs);
+ /// not implemented on purpose
+ AliAnalysisMuMuCutCombination& operator=(const AliAnalysisMuMuCutCombination& rhs);
+
+private:
+ TObjArray* fCuts; // array of cut elements that form this cut combination
+ TString fName; // name of the combination
+ Bool_t fIsEventCutter; // whether or not the combination cuts on event
+ Bool_t fIsEventHandlerCutter; // whether or not the combination cuts on event handler
+ Bool_t fIsTrackCutter; // whether or not the combination cuts on track
+ Bool_t fIsTrackPairCutter; // whether or not the combination cuts on track pairs
+ Bool_t fIsTriggerClassCutter; // whether or not the combination cuts on trigger class
+
+ ClassDef(AliAnalysisMuMuCutCombination,1) // combination of 1 or more individual cuts
+};
+
+#endif
+
--- /dev/null
+#include "AliAnalysisMuMuCutElement.h"
+
+/**
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuCutElement
+ *
+ * An AliAnalysisMuMuCutElement is an interface/proxy to another method (see ctor)
+ *
+ * A cut has a type (event cut, track cut, etc..., see ECutType and the IsXXX methods),
+ * a name, and offers a Pass method. A cut can be of one type only.
+ * Generally a real cut is made of several cut elements,
+ * see \ref AliAnalysisMuMuCutCombination
+ *
+ * \author L. Aphecetche (Subatech)
+ */
+
+#include "TMethodCall.h"
+#include "AliLog.h"
+#include "Riostream.h"
+#include "AliVParticle.h"
+
+ClassImp(AliAnalysisMuMuCutElement)
+ClassImp(AliAnalysisMuMuCutElementBar)
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement::AliAnalysisMuMuCutElement()
+: TObject(), fName(""), fIsEventCutter(kFALSE), fIsEventHandlerCutter(kFALSE),
+fIsTrackCutter(kFALSE), fIsTrackPairCutter(kFALSE), fIsTriggerClassCutter(kFALSE),
+fCutObject(0x0), fCutMethodName(""), fCutMethodPrototype(""),
+fDefaultParameters(""), fNofParams(0), fCutMethod(0x0), fCallParams()
+{
+ /// Default ctor, leading to an invalid cut object
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement::AliAnalysisMuMuCutElement(ECutType expectedType,
+ TObject& cutObject,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters)
+: TObject(), fName(""), fIsEventCutter(kFALSE), fIsEventHandlerCutter(kFALSE),
+fIsTrackCutter(kFALSE), fIsTrackPairCutter(kFALSE), fIsTriggerClassCutter(kFALSE),
+fCutObject(&cutObject), fCutMethodName(cutMethodName),
+fCutMethodPrototype(cutMethodPrototype),fDefaultParameters(defaultParameters),
+fNofParams(0), fCutMethod(0x0), fCallParams()
+{
+ /**
+ * Construct a cut, which is a proxy to another method of (most probably) another object
+ *
+ * \param expectedType the type of cut which is expected (this cut will be invalidated if
+ * the actual method does not comply with this type)
+ * \param cutObject the object which has the cut method
+ * \param cutMethodName the name of the method of cutObject that should do the cut work
+ * \param cutMethodPrototype the prototype (i.e. list of arguments) of cutMethod
+ * \param defaultParameters values of the default parameters (if any) of the cutMethod
+ *
+ * See the \ref Init method for details.
+ */
+
+ Init(expectedType);
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement::~AliAnalysisMuMuCutElement()
+{
+ /// Dtor
+ delete fCutMethod;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutElement::CallCutMethod(Long_t p) const
+{
+ /// Call the cut method with one parameter
+ if (!fCutMethod)
+ {
+ Init();
+ if (!fCutMethod) return kFALSE;
+ }
+
+ fCallParams[0] = p;
+
+ fCutMethod->SetParamPtrs(&fCallParams[0]);
+ Long_t result;
+ fCutMethod->Execute(fCutObject,result);
+
+ return (result!=0);
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutElement::CallCutMethod(Long_t p1, Long_t p2) const
+{
+ /// Call the cut method with two parameters
+
+ if (!fCutMethod)
+ {
+ Init();
+ if (!fCutMethod) return kFALSE;
+ }
+
+ fCallParams[0] = p1;
+ fCallParams[1] = p2;
+
+ fCutMethod->SetParamPtrs(&fCallParams[0]);
+ Long_t result;
+ fCutMethod->Execute(fCutObject,result);
+
+ return (result!=0);
+}
+
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuCutElement::CountOccurences(const TString& prototype, const char* search) const
+{
+ /// Count the number of times "search" is found in prototype
+
+ TObjArray* a = prototype.Tokenize(",");
+ TObjString* str;
+ TIter next(a);
+
+ Int_t n(0);
+
+ while ( ( str = static_cast<TObjString*>(next()) ) )
+ {
+ if ( str->String().Contains(search) )
+ {
+ ++n;
+ }
+ }
+ delete a;
+ return n;
+}
+
+//_____________________________________________________________________________
+const char* AliAnalysisMuMuCutElement::CutTypeName(ECutType type)
+{
+ /// Convert the enum into a string
+
+ if ( type == kEvent )
+ {
+ return "Event";
+ }
+ if ( type == kTrack )
+ {
+ return "Track";
+ }
+ if ( type == kTrackPair )
+ {
+ return "TrackPair";
+ }
+ if ( type == kTriggerClass )
+ {
+ return "TriggerClass";
+ }
+ return "Any";
+}
+
+//_____________________________________________________________________________
+const char* AliAnalysisMuMuCutElement::GetCallMethodName() const
+{
+ /// Return the cut method name
+ return ( fCutMethod ? fCutMethod->GetMethodName() : "");
+}
+
+//_____________________________________________________________________________
+const char* AliAnalysisMuMuCutElement::GetCallMethodProto() const
+{
+ /// Return the cut method prototype
+ return ( fCutMethod ? fCutMethod->GetProto() : "");
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuCutElement::Init(ECutType expectedType) const
+{
+ /** Build the non-persistent members (TMethodCalls)
+ *
+ * Each cut method XXXX must have
+ * a companion method, called NameOfXXXX(TString& nameOfCut) which fills the nameOfCut
+ * string with the name of cut (using the default parameter values if need be to distinguish
+ * different cuts using the same method).
+ * The cut method we're proxy-ing can not be of any kind. We basically only recognize the
+ * following prototypes (more or less based on the Pass() method prototypes). The checks
+ * performed below to ensure that are far from being bullet-proof though... You've been
+ * warned !
+ *
+ * For event cutters (3 or them instead of just one because of the, imo,
+ * improper event/eventhandler interfaces we currently have in AliRoot)
+ *
+ * Bool_t XXXX(const AliVEvent&, ...)
+ * Bool_t XXXX(const AliVEventHandler&, ...)
+ * Bool_t XXXX(const AliInputEventHandler&, ...)
+ *
+ * For track cutters :
+ *
+ * Bool_t XXXX(const AliVParticle&, ...)
+ *
+ * For track pairs cutters :
+ *
+ * Bool_t XXXX(const AliVParticle&, const AliVParticle&, ...)
+ *
+ * For trigger class cutters :
+ *
+ * Bool_t XXXX(const TString& firedTriggerClasses, TString& acceptedTriggerClasses)
+ *
+ * where ... stands for optional arguments (different from VEvent VParticle, etc...),
+ * which can have default values
+ *
+ * Note that Root reflexion does not allow (yet?) to check for constness of the arguments,
+ * so AliVEvent& and const AliVEvent& will be the same.
+ *
+ *
+ */
+
+ TString scutMethodPrototype(fCutMethodPrototype);
+
+ // some basic checks first
+
+ TObjArray* tmp = fCutMethodPrototype.Tokenize(",");
+ fNofParams = tmp->GetEntries();
+ delete tmp;
+
+ Int_t nVEvent = CountOccurences(fCutMethodPrototype,"AliVEvent");
+ Int_t nVEventHandler = CountOccurences(fCutMethodPrototype,"AliVEventHandler");
+ Int_t nInputHandler = CountOccurences(fCutMethodPrototype,"AliInputEventHandler");
+ Int_t nparticles = CountOccurences(fCutMethodPrototype,"AliVParticle");
+ Int_t nstrings = CountOccurences(fCutMethodPrototype,"TString");
+
+ if ( expectedType == kEvent && ( nVEvent == 0 && nVEventHandler == 0 && nInputHandler == 0 ) )
+ {
+ AliError(Form("Cut not of the expected %s type : did not find required prototype arguments AliVEvent, AliVEventHandler or AliInputEventHandler",CutTypeName(kEvent)));
+ return;
+ }
+
+ if ( expectedType == kTrack && ( nparticles != 1 ) )
+ {
+ AliError(Form("Cut not of the expected %s type : did not find the required prototype argument AliVParticle (one and only one required)",CutTypeName(kTrack)));
+ return;
+ }
+
+ if ( expectedType == kTrackPair && ( nparticles != 2 ) )
+ {
+ AliError(Form("Cut not of the expected %s type : did not find the required prototype arguments AliVParticle (2 of them required)",CutTypeName(kTrackPair)));
+ return;
+ }
+
+ if ( expectedType == kTriggerClass && ( nstrings != 2 ) )
+ {
+ AliError(Form("Cut not of the expected %stype : did not find the required prototype arguments TString& (2 of them required)",CutTypeName(kTriggerClass)));
+ return;
+ }
+
+ // OK, at least the prototype seems to match what we require. Let's continue...
+
+ scutMethodPrototype.ReplaceAll(" ","");
+
+ fCutMethod = new TMethodCall;
+
+ fCutMethod->InitWithPrototype(fCutObject->IsA(),fCutMethodName.Data(),scutMethodPrototype.Data());
+
+ if (!fCutMethod->IsValid())
+ {
+ AliError(Form("Could not find method %s(%s) in class %s",fCutMethodName.Data(),
+ scutMethodPrototype.Data(),fCutObject->ClassName()));
+ delete fCutMethod;
+ fCutMethod=0x0;
+ return;
+ }
+
+ TMethodCall nameOfMethod;
+
+ TString prototype("TString&");
+
+ Int_t nMainPar = 0;
+
+ if ( scutMethodPrototype.Contains("AliVEvent") )
+ {
+ fIsEventCutter=kTRUE;
+ ++nMainPar;
+ }
+ if ( scutMethodPrototype.Contains("AliInputEventHandler") )
+ {
+ fIsEventHandlerCutter=kTRUE;
+ ++nMainPar;
+ }
+
+ if ( nMainPar > 1 )
+ {
+ AliError(Form("Got an invalid prototype %s (more than one main parameter)",scutMethodPrototype.Data()));
+ delete fCutMethod;
+ fCutMethod=0x0;
+ return;
+ }
+
+ if ( nparticles == 1 )
+ {
+ fIsTrackCutter=kTRUE;
+ }
+ else if ( nparticles == 2 )
+ {
+ fIsTrackPairCutter=kTRUE;
+ }
+ else if ( nstrings == 2 )
+ {
+ fIsTriggerClassCutter = kTRUE;
+ }
+
+ nMainPar += nparticles;
+ nMainPar += nstrings;
+
+ if ( nMainPar > 2 )
+ {
+ AliError(Form("Got an invalid prototype %s (more than two main parameters)",scutMethodPrototype.Data()));
+ delete fCutMethod;
+ fCutMethod=0x0;
+ return;
+ }
+
+ if ( nMainPar == 0 )
+ {
+ AliError(Form("Got an invalid prototype %s (no main parameter found)",scutMethodPrototype.Data()));
+ delete fCutMethod;
+ fCutMethod=0x0;
+ return;
+ }
+
+ if ( !fIsTriggerClassCutter )
+ {
+ scutMethodPrototype.ReplaceAll("const AliVEvent&","");
+ scutMethodPrototype.ReplaceAll("const AliVParticle&","");
+ scutMethodPrototype.ReplaceAll("const AliInputEventHandler&","");
+
+ prototype += scutMethodPrototype;
+
+ nameOfMethod.InitWithPrototype(fCutObject->IsA(),Form("NameOf%s",fCutMethodName.Data()),prototype);
+
+ if (!nameOfMethod.IsValid())
+ {
+ AliError(Form("Could not find method NameOf%s(%s) in class %s",fCutMethodName.Data(),
+ prototype.Data(),fCutObject->ClassName()));
+ delete fCutMethod;
+ fCutMethod=0x0;
+ return;
+ }
+
+ // Now check if we have some default parameters for the NameOf method
+ // Note that the only supported types for those default parameters
+ // are Int_t and Double_t (which must be then of the form const Double_t&,
+ // note the reference).
+
+ prototype.ReplaceAll("TString&","");
+
+ TObjArray* paramTypes = prototype.Tokenize(",");
+ TObjArray* paramValues = fDefaultParameters.Tokenize(",");
+
+ fDoubleParams.resize(paramValues->GetEntries());
+
+ Int_t nparams = paramValues->GetEntries();
+
+ // first parameter is always the TString&, i.e. the "output" of the NameOf
+ // method
+
+ fCallParams.resize(nparams+nMainPar);
+
+ if ( nMainPar == 2 )
+ {
+ fCallParams[0] = 0;
+ fCallParams[1] = reinterpret_cast<Long_t>(&fName);
+ }
+ else
+ {
+ fCallParams[0] = reinterpret_cast<Long_t>(&fName);
+ }
+
+ for ( Int_t i = 0; i < nparams; ++i )
+ {
+ TString pValue = static_cast<TObjString*>(paramValues->At(i))->String();
+ TString pType = static_cast<TObjString*>(paramTypes->At(i))->String();
+
+ if ( pType.Contains("Double_t"))
+ {
+ fDoubleParams[i] = pValue.Atof();
+ fCallParams[i+nMainPar] = reinterpret_cast<Long_t>(&fDoubleParams[i]);
+ }
+ else if ( pType.Contains("Int_t") )
+ {
+ fCallParams[i+nMainPar] = pValue.Atoi();
+ }
+ else
+ {
+ AliError(Form("Got a parameter of type %s which I don't exactly know how to deal with. Expect something bad to happen...",pType.Data()));
+ fCallParams[i+nMainPar] = reinterpret_cast<Long_t>(&pValue);
+ }
+ }
+
+ nameOfMethod.SetParamPtrs(&fCallParams[0+nMainPar-1]);
+
+ nameOfMethod.Execute(fCutObject);
+
+ delete paramTypes;
+ delete paramValues;
+ }
+ else
+ {
+ // check whether we have the input bit masks as well
+ Int_t nuint = CountOccurences(scutMethodPrototype,"UInt_t");
+
+ Bool_t ok =
+ ( nuint == 3 && nstrings == 2 && ( nuint + nstrings ) == fNofParams ) ||
+ ( nuint == 0 && nstrings == 2 && nstrings == fNofParams );
+
+ if (!ok)
+ {
+ AliError("Incorrect prototype for a trigger class cutter");
+ delete fCutMethod;
+ fCutMethod=0x0;
+ return;
+ }
+ }
+
+ // Final consistency ross-check
+
+ if ( expectedType == kEvent && ! (fIsEventCutter || fIsEventHandlerCutter) )
+ {
+ AliError("No, it's not an event cutter. Invalidate");
+ delete fCutMethod;
+ fCutMethod=0x0;
+ }
+
+ if ( expectedType == kTrack && !fIsTrackCutter )
+ {
+ AliError("No, it's not a track cutter. Invalidate");
+ delete fCutMethod;
+ fCutMethod=0x0;
+ }
+
+ if ( expectedType == kTrackPair && !fIsTrackPairCutter )
+ {
+ AliError("No, it's not a track pair cutter. Invalidate");
+ delete fCutMethod;
+ fCutMethod=0x0;
+ }
+
+ if ( expectedType == kTriggerClass && !fIsTriggerClassCutter )
+ {
+ AliError("No, it's not a trigger class cutter. Invalidate");
+ delete fCutMethod;
+ fCutMethod=0x0;
+ }
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutElement::IsEqual(const TObject* obj) const
+{
+ /// Whether we're the same cut as obj
+
+ if ( obj->IsA() != IsA() ) return kFALSE;
+
+ const AliAnalysisMuMuCutElement* cut = static_cast<const AliAnalysisMuMuCutElement*>(obj);
+
+ return ( fName == cut->fName &&
+ fIsEventCutter == cut->fIsEventCutter &&
+ fIsEventHandlerCutter == cut->fIsEventHandlerCutter &&
+ fIsTrackCutter == cut->fIsTrackCutter &&
+ fIsTrackPairCutter == cut->fIsTrackPairCutter &&
+ fIsTriggerClassCutter == cut->fIsTriggerClassCutter &&
+ fCutMethodName == cut->fCutMethodName &&
+ fCutMethodPrototype == cut->fCutMethodPrototype &&
+ fDefaultParameters == cut->fDefaultParameters &&
+ fCutObject == cut->fCutObject /* CHECK: should we really impose object equality or class equality would be enough ? */
+ );
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutElement::Pass(const AliVEvent& event) const
+{
+ /// Whether the event pass this cut
+ return CallCutMethod(reinterpret_cast<Long_t>(&event));
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutElement::Pass(const AliInputEventHandler& eventHandler) const
+{
+ /// Whether the eventHandler pass this cut
+ return CallCutMethod(reinterpret_cast<Long_t>(&eventHandler));
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutElement::Pass(const AliVParticle& part) const
+{
+ /// Whether the particle pass this cut
+ return CallCutMethod(reinterpret_cast<Long_t>(&part));
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutElement::Pass(const AliVParticle& p1, const AliVParticle& p2) const
+{
+ /// Whether the particle pair pass this cut
+ return CallCutMethod(reinterpret_cast<Long_t>(&p1),reinterpret_cast<Long_t>(&p2));
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuCutElement::Pass(const TString& firedTriggerClasses,
+ TString& acceptedTriggerClasses,
+ UInt_t L0, UInt_t L1, UInt_t L2) const
+{
+ /** Whether the firedTriggerClasses pass the cut.
+ * \param firedTriggerClasses (input) list of fired trigger classes (separated by space)
+ * \param acceptedTriggerClasses (output) list of accepted classes
+ * \param L0 (input, optional) level 0 trigger mask
+ * \param L1 (input, optional) level 1 trigger mask
+ * \param L2 (input, optional) level 2 trigger mask
+ */
+
+ if (!fCutMethod)
+ {
+ Init();
+ if (!fCutMethod) return kFALSE;
+ }
+
+ acceptedTriggerClasses = "";
+
+ Long_t result;
+ Long_t params[] = { reinterpret_cast<Long_t>(&firedTriggerClasses),
+ reinterpret_cast<Long_t>(&acceptedTriggerClasses),
+ L0,L1,L2 };
+
+ fCutMethod->SetParamPtrs(params);
+ fCutMethod->Execute(fCutObject,result);
+ return (result!=0);
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuCutElement::Print(Option_t* /*opt*/) const
+{
+ /// Printout of the cut information
+ if ( !fCutMethod )
+ {
+ Init();
+ }
+
+ std::cout << Form("Cut %s(%p) %s(%p)::%s(%s) [",
+ fName.Data(),this,
+ fCutObject->ClassName(),
+ fCutObject,
+ GetCallMethodName(),
+ GetCallMethodProto());
+
+ if ( IsEventCutter() ) std::cout << " E";
+ if ( IsEventHandlerCutter() ) std::cout << " EH";
+ if ( IsTrackCutter() ) std::cout << " T";
+ if ( IsTrackPairCutter() ) std::cout << " TP";
+ if ( IsTriggerClassCutter() ) std::cout << " TC";
+
+ std::cout << " ]" << std::endl;
+}
+
+//_____________________________________________________________________________
+//_____________________________________________________________________________
+//_____________________________________________________________________________
+
+/**
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuCutElementBar
+ *
+ * \brief The negation of an AliAnalysisMuMuCutElement
+ *
+ * \author L. Aphecetche (Subatech)
+ */
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElementBar::AliAnalysisMuMuCutElementBar() : AliAnalysisMuMuCutElement(),
+fCutElement(0x0)
+{
+ /// default ctor
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElementBar::AliAnalysisMuMuCutElementBar(const AliAnalysisMuMuCutElement& ce)
+: AliAnalysisMuMuCutElement(), fCutElement(&ce)
+{
+ /// ctor
+ fIsEventCutter = ce.IsEventCutter();
+ fIsEventHandlerCutter = ce.IsEventHandlerCutter();
+ fIsTrackCutter = ce.IsTrackCutter();
+ fIsTrackPairCutter = ce.IsTrackPairCutter();
+ fName = TString::Format("NOT%s",ce.GetName());
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElementBar::~AliAnalysisMuMuCutElementBar()
+{
+ /// dtor (nop as we're not the owner of fCutElement)
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuCutElementBar::Print(Option_t* /*opt*/) const
+{
+ /// Printout of the cut information
+ std::cout << Form("Cut %s(%p) : negation of %s(%p)",GetName(),this,fCutElement->GetName(),fCutElement)
+ << std::endl;
+}
+
--- /dev/null
+#ifndef ALIANALYSISMUMUCUTELEMENT_H
+#define ALIANALYSISMUMUCUTELEMENT_H
+
+/**
+ *
+ * \class AliAnalysisMuMuCutElement
+ *
+ * \brief Describes an elementary cut (either event cut, track cut, pair cut, or trigger class cut)
+ *
+ */
+
+#include "TObject.h"
+#include "TString.h"
+
+#include <vector>
+
+class TMethodCall;
+class AliVEvent;
+class AliInputEventHandler;
+class AliVParticle;
+
+class AliAnalysisMuMuCutElement : public TObject
+{
+public:
+
+ enum ECutType
+ {
+ kEvent=0, // a cut on event
+ kTrack=1, // a cut on track
+ kTrackPair=2, // a cut on track pair
+ kTriggerClass=3, // a cut on trigger class
+ kAny=4 // must be the last one
+ };
+
+ static const char* CutTypeName(ECutType type);
+
+ AliAnalysisMuMuCutElement();
+
+ AliAnalysisMuMuCutElement(ECutType expectedType,
+ TObject& cutObject,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters);
+
+ virtual ~AliAnalysisMuMuCutElement();
+
+ virtual Bool_t IsValid() const { return (fCutMethod != 0x0); }
+
+ const char* GetName() const { return fName.Data(); }
+
+ virtual Bool_t Pass(const AliVEvent& event) const;
+
+ virtual Bool_t Pass(const AliInputEventHandler& eventHandler) const;
+
+ virtual Bool_t Pass(const AliVParticle& particle) const;
+
+ virtual Bool_t Pass(const AliVParticle& p1, const AliVParticle& p2) const;
+
+ virtual Bool_t Pass(const TString& firedTriggerClasses, TString& acceptedTriggerClasses,
+ UInt_t L0, UInt_t L1, UInt_t L2) const;
+
+ virtual void Print(Option_t* opt="") const;
+
+ Bool_t IsEventCutter() const { return fIsEventCutter; }
+ Bool_t IsEventHandlerCutter() const { return fIsEventHandlerCutter; }
+ Bool_t IsTrackCutter() const { return fIsTrackCutter; }
+ Bool_t IsTrackPairCutter() const { return fIsTrackPairCutter; }
+ Bool_t IsTriggerClassCutter() const { return fIsTriggerClassCutter; }
+
+ TObject* GetCutObject() const { return fCutObject; }
+
+ const Long_t* GetCallParams() const { return &fCallParams[0]; }
+
+ const char* GetCallMethodName() const;
+ const char* GetCallMethodProto() const;
+
+ Bool_t IsEqual(const TObject* obj) const;
+
+private:
+
+ void Init(ECutType type=kAny) const;
+
+ Bool_t CallCutMethod(Long_t p) const;
+ Bool_t CallCutMethod(Long_t p1, Long_t p2) const;
+
+ Int_t CountOccurences(const TString& prototype, const char* search) const;
+
+ /// not implemented on purpose
+ AliAnalysisMuMuCutElement(const AliAnalysisMuMuCutElement& rhs);
+ /// not implemented on purpose
+ AliAnalysisMuMuCutElement& operator=(const AliAnalysisMuMuCutElement& rhs);
+
+protected:
+ TString fName; // name of the cut
+ mutable Bool_t fIsEventCutter; // whether or not the cut is an event cutter
+ mutable Bool_t fIsEventHandlerCutter; // whether or not the cut is an event handler cutter
+ mutable Bool_t fIsTrackCutter; // whether or not the cut is a track cutter
+ mutable Bool_t fIsTrackPairCutter; // whether or not the cut is a track pair cutter
+ mutable Bool_t fIsTriggerClassCutter; // whether or not the cut is a trigger class cutter
+private:
+
+ TObject* fCutObject; // pointer (not owner) to the object doing the actual cut work
+ TString fCutMethodName; // method (of fCutObject) to be called to do the cut
+ TString fCutMethodPrototype; // prototype of the method to be called to do the cut
+ TString fDefaultParameters; // default parameters of the cut method (might be empty)
+ mutable Int_t fNofParams; // number of parameters
+ mutable TMethodCall* fCutMethod; //! cut method
+
+ mutable std::vector<Long_t> fCallParams; //! vector of parameters for the fCutMethod
+ mutable std::vector<Double_t> fDoubleParams; //! temporary vector to hold the references
+
+ ClassDef(AliAnalysisMuMuCutElement,1) // One piece of a cut combination
+};
+
+class AliAnalysisMuMuCutElementBar : public AliAnalysisMuMuCutElement
+{
+public:
+ AliAnalysisMuMuCutElementBar();
+
+ AliAnalysisMuMuCutElementBar(const AliAnalysisMuMuCutElement& ce);
+
+ virtual ~AliAnalysisMuMuCutElementBar();
+
+ Bool_t IsValid() const { return fCutElement && fCutElement->IsValid(); }
+
+ Bool_t Pass(const AliVEvent& event) const { return !fCutElement->Pass(event); }
+
+ Bool_t Pass(const AliInputEventHandler& eventHandler) const { return !fCutElement->Pass(eventHandler); }
+
+ Bool_t Pass(const AliVParticle& particle) const { return !fCutElement->Pass(particle); }
+
+ Bool_t Pass(const AliVParticle& p1, const AliVParticle& p2) const { return !fCutElement->Pass(p1,p2); }
+
+ Bool_t Pass(const TString& firedTriggerClasses, TString& acceptedTriggerClasses,
+ UInt_t L0, UInt_t L1, UInt_t L2) const
+ { return fCutElement->Pass(firedTriggerClasses,acceptedTriggerClasses,L0,L1,L2); }
+
+ void Print(Option_t* opt="") const;
+
+private:
+ const AliAnalysisMuMuCutElement* fCutElement; // the cut element we're the negation of
+
+ ClassDef(AliAnalysisMuMuCutElementBar,1) // opposite of cut element (i.e. !cutelement)
+};
+
+#endif
+
--- /dev/null
+#include "AliAnalysisMuMuCutRegistry.h"
+
+/**
+ *
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuCutRegistry
+ * The cut elements and cut combinations are stored per type, i.e. there's a set for
+ * event cuts/combinations, a set for track cuts/combinations, and a set for track pair cuts/combinations.
+ *
+ * To define a new cut use the AddEventCut, AddTrackCut, AndTrackPairCut and AddTriggerClassCut methods.
+ *
+ * To add an existing cut see AddCutElement.
+ *
+ * To define the negation of a cut, use the Not method.
+ *
+ * To add a new combination use one of the AddCutCombination methods, depending on the number
+ * of cut element(s) the combination is made of.
+ *
+ * Note that what the sub-analysis are really concerned with are cut combinations (i.e. if
+ * you fail to define any combination, nothing will be cut, whatever the number of cut elements
+ * you've defined).
+ *
+ * This class also defines a few default control cut elements aptly named AlwaysTrue.
+ *
+ */
+
+#include <utility>
+#include "AliLog.h"
+#include "TMethodCall.h"
+#include "AliVEvent.h"
+#include <set>
+#include "AliAnalysisMuMuCutElement.h"
+#include "AliAnalysisMuMuCutCombination.h"
+#include "TObjArray.h"
+#include "Riostream.h"
+#include "TList.h"
+
+ClassImp(AliAnalysisMuMuCutRegistry)
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutRegistry::AliAnalysisMuMuCutRegistry()
+: TObject(),
+fCutElements(0x0),
+fCutCombinations(0x0)
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutRegistry::~AliAnalysisMuMuCutRegistry()
+{
+ /// dtor
+
+ delete fCutElements;
+ delete fCutCombinations;
+}
+
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuCutRegistry::AddCutCombination(const TObjArray& cutElements)
+{
+ /// Add a cut combination composed of the cuts in the cutElements array.
+ ///
+ /// \return 1 in case of success, 0 if already there, -1 failure
+
+ if ( cutElements.IsEmpty() ) return -1;
+
+ AliAnalysisMuMuCutCombination* cutCombination = new AliAnalysisMuMuCutCombination;
+
+ TIter next(&cutElements);
+ AliAnalysisMuMuCutElement* ce;
+
+ while ( ( ce = static_cast<AliAnalysisMuMuCutElement*>(next()) ) )
+ {
+ cutCombination->Add(ce);
+ }
+
+ if ( GetCutCombinations(AliAnalysisMuMuCutElement::kAny)->FindObject(cutCombination) )
+ {
+ delete cutCombination;
+ return 0;
+ }
+
+ GetCutCombinations(AliAnalysisMuMuCutElement::kAny)->Add(cutCombination);
+
+ if ( cutCombination->IsEventCutter() || cutCombination->IsEventHandlerCutter() )
+ {
+ GetCutCombinations(AliAnalysisMuMuCutElement::kEvent)->Add(cutCombination);
+ }
+
+ if ( cutCombination->IsTrackCutter() )
+ {
+ GetCutCombinations(AliAnalysisMuMuCutElement::kTrack)->Add(cutCombination);
+ }
+
+ if ( cutCombination->IsTrackPairCutter() )
+ {
+ GetCutCombinations(AliAnalysisMuMuCutElement::kTrackPair)->Add(cutCombination);
+ }
+
+ if ( cutCombination->IsTriggerClassCutter() )
+ {
+ GetCutCombinations(AliAnalysisMuMuCutElement::kTriggerClass)->Add(cutCombination);
+ }
+
+ return 1;
+}
+
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuCutRegistry::AddCutCombination(AliAnalysisMuMuCutElement* ce1)
+{
+ /// Convenience method to create a cut combination made of a single cut
+ TObjArray cutElements;
+ if ( ce1 ) cutElements.Add(ce1);
+ return AddCutCombination(cutElements);
+}
+
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuCutRegistry::AddCutCombination(AliAnalysisMuMuCutElement* ce1,
+ AliAnalysisMuMuCutElement* ce2)
+{
+ /// Convenience method to create a cut combination made of 2 cuts
+ TObjArray cutElements;
+ if ( ce1 ) cutElements.Add(ce1);
+ if ( ce2 ) cutElements.Add(ce2);
+ return AddCutCombination(cutElements);
+}
+
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuCutRegistry::AddCutCombination(AliAnalysisMuMuCutElement* ce1,
+ AliAnalysisMuMuCutElement* ce2,
+ AliAnalysisMuMuCutElement* ce3)
+{
+ /// Convenience method to create a cut combination made of 3 cuts
+ TObjArray cutElements;
+ if ( ce1 ) cutElements.Add(ce1);
+ if ( ce2 ) cutElements.Add(ce2);
+ if ( ce3 ) cutElements.Add(ce3);
+ return AddCutCombination(cutElements);
+}
+
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuCutRegistry::AddCutCombination(AliAnalysisMuMuCutElement* ce1, AliAnalysisMuMuCutElement* ce2, AliAnalysisMuMuCutElement* ce3,
+ AliAnalysisMuMuCutElement* ce4)
+{
+ /// Convenience method to create a cut combination made of 4 cuts
+ TObjArray cutElements;
+ if ( ce1 ) cutElements.Add(ce1);
+ if ( ce2 ) cutElements.Add(ce2);
+ if ( ce3 ) cutElements.Add(ce3);
+ if ( ce4 ) cutElements.Add(ce4);
+ return AddCutCombination(cutElements);
+}
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuCutRegistry::AddCutCombination(AliAnalysisMuMuCutElement* ce1, AliAnalysisMuMuCutElement* ce2, AliAnalysisMuMuCutElement* ce3,
+ AliAnalysisMuMuCutElement* ce4, AliAnalysisMuMuCutElement* ce5)
+{
+ /// Convenience method to create a cut combination made of 5 cuts
+
+ TObjArray cutElements;
+ if ( ce1 ) cutElements.Add(ce1);
+ if ( ce2 ) cutElements.Add(ce2);
+ if ( ce3 ) cutElements.Add(ce3);
+ if ( ce4 ) cutElements.Add(ce4);
+ if ( ce5 ) cutElements.Add(ce5);
+ return AddCutCombination(cutElements);
+}
+
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuCutRegistry::AddCutCombination(AliAnalysisMuMuCutElement* ce1, AliAnalysisMuMuCutElement* ce2, AliAnalysisMuMuCutElement* ce3,
+ AliAnalysisMuMuCutElement* ce4, AliAnalysisMuMuCutElement* ce5, AliAnalysisMuMuCutElement* ce6)
+{
+ /// Convenience method to create a cut combination made of 6 cuts
+
+ TObjArray cutElements;
+ if ( ce1 ) cutElements.Add(ce1);
+ if ( ce2 ) cutElements.Add(ce2);
+ if ( ce3 ) cutElements.Add(ce3);
+ if ( ce4 ) cutElements.Add(ce4);
+ if ( ce5 ) cutElements.Add(ce5);
+ if ( ce6 ) cutElements.Add(ce6);
+ return AddCutCombination(cutElements);
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement*
+AliAnalysisMuMuCutRegistry::CreateCutElement(AliAnalysisMuMuCutElement::ECutType type,
+ TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters)
+{
+ /** Create a cut element. See the ctor of AliAnalysisMuMuCutElement for the meaning
+ * of the parameters.
+ */
+
+ AliAnalysisMuMuCutElement* ce = new AliAnalysisMuMuCutElement(type,cutClass,cutMethodName,cutMethodPrototype,defaultParameters);
+
+ AliAnalysisMuMuCutElement* added = AddCutElement(ce);
+
+ if (!added)
+ {
+ delete ce;
+ }
+
+ return added;
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement*
+AliAnalysisMuMuCutRegistry::AddCutElement(AliAnalysisMuMuCutElement* ce)
+{
+ /// Add an existing cut element to the registry if it is valid
+
+ if ( ce && ce->IsValid() )
+ {
+ if (!GetCutElements(AliAnalysisMuMuCutElement::kAny)->FindObject(ce))
+ {
+ GetCutElements(AliAnalysisMuMuCutElement::kAny)->Add(ce);
+ if ( ce->IsEventCutter() || ce->IsEventHandlerCutter() )
+ {
+ GetCutElements(AliAnalysisMuMuCutElement::kEvent)->Add(ce);
+ }
+ else if ( ce->IsTrackCutter() )
+ {
+ GetCutElements(AliAnalysisMuMuCutElement::kTrack)->Add(ce);
+ }
+ else if ( ce->IsTrackPairCutter() )
+ {
+ GetCutElements(AliAnalysisMuMuCutElement::kTrackPair)->Add(ce);
+ }
+ else if ( ce->IsTriggerClassCutter() )
+ {
+ GetCutElements(AliAnalysisMuMuCutElement::kTriggerClass)->Add(ce);
+ }
+ }
+ return ce;
+ }
+ return 0x0;
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement* AliAnalysisMuMuCutRegistry::AddEventCut(TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters)
+{
+ /// Shortcut method to create a cut element of type kEvent
+ return CreateCutElement(AliAnalysisMuMuCutElement::kEvent,cutClass,cutMethodName,
+ cutMethodPrototype,defaultParameters);
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement* AliAnalysisMuMuCutRegistry::AddTrackCut(TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters)
+{
+ /// Shortcut method to create a cut element of type kTrack
+ return CreateCutElement(AliAnalysisMuMuCutElement::kTrack,cutClass,cutMethodName,
+ cutMethodPrototype,defaultParameters);
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement* AliAnalysisMuMuCutRegistry::AddTrackPairCut(TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters)
+{
+ /// Shortcut method to create a cut element of type kTrackPair
+ return CreateCutElement(AliAnalysisMuMuCutElement::kTrackPair,cutClass,cutMethodName,
+ cutMethodPrototype,defaultParameters);
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement* AliAnalysisMuMuCutRegistry::AddTriggerClassCut(TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters)
+{
+ /// Shortcut method to create a cut element of type kTriggerClass
+ return CreateCutElement(AliAnalysisMuMuCutElement::kTriggerClass,cutClass,cutMethodName,
+ cutMethodPrototype,defaultParameters);
+}
+
+//_____________________________________________________________________________
+const TObjArray* AliAnalysisMuMuCutRegistry::GetCutCombinations(AliAnalysisMuMuCutElement::ECutType type) const
+{
+ /// Get (and create if not already done) the array of cut combinations of the given type
+
+ if (!fCutCombinations) return 0x0;
+
+ return static_cast<TObjArray*>(fCutCombinations->At(type));
+}
+
+//_____________________________________________________________________________
+TObjArray* AliAnalysisMuMuCutRegistry::GetCutCombinations(AliAnalysisMuMuCutElement::ECutType type)
+{
+ /// Get (and create if not already done) the array of cut combinations of the given type
+
+ if (!fCutCombinations)
+ {
+ // the fCutCombinations array will be the owner of all the cut combinations
+
+ Int_t N = AliAnalysisMuMuCutElement::kAny + 1;
+
+ fCutCombinations = new TObjArray(N);
+ fCutCombinations->SetOwner(kTRUE);
+
+ for ( Int_t i = 0; i < N; ++i )
+ {
+ TObjArray* array = new TObjArray;
+ array->SetOwner(kFALSE);
+ if (i==AliAnalysisMuMuCutElement::kAny)
+ {
+ // only the first array, containing all the combinations
+ // is the owner of the combinations
+ // the other arrays are just pointing to those
+ array->SetOwner(kTRUE);
+ }
+ fCutCombinations->AddAt(array,i);
+ }
+ }
+ return static_cast<TObjArray*>(fCutCombinations->At(type));
+}
+
+//_____________________________________________________________________________
+const TObjArray* AliAnalysisMuMuCutRegistry::GetCutElements(AliAnalysisMuMuCutElement::ECutType type) const
+{
+ /// Get the array of cut elements of the given type. Return 0x0 if the array does not exist yet
+
+ if (!fCutElements) return 0x0;
+
+ return static_cast<TObjArray*>(fCutElements->At(type));
+}
+
+//_____________________________________________________________________________
+TObjArray* AliAnalysisMuMuCutRegistry::GetCutElements(AliAnalysisMuMuCutElement::ECutType type)
+{
+ /// Get (and create if not already done) the array of cut elements of the given type
+
+ if (!fCutElements)
+ {
+ // owner of all the cut elements
+ Int_t N = AliAnalysisMuMuCutElement::kAny + 1;
+ fCutElements = new TObjArray(N);
+ fCutElements->SetOwner(kTRUE);
+
+ for ( Int_t i = 0; i < N; ++i )
+ {
+ TObjArray* array = new TObjArray;
+ array->SetOwner(kFALSE);
+ if (i == AliAnalysisMuMuCutElement::kAny )
+ {
+ // only the first array is the owner of the cuts
+ // the other ones are just pointing to this one
+ array->SetOwner(kTRUE);
+ }
+ fCutElements->AddAt(array,i);
+ }
+ }
+ return static_cast<TObjArray*>(fCutElements->At(type));
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuCutElement* AliAnalysisMuMuCutRegistry::Not(const AliAnalysisMuMuCutElement& cutElement)
+{
+ /// Create a cut which is the opposite of cutElement, and adds it.
+
+ AliAnalysisMuMuCutElementBar* bar = new AliAnalysisMuMuCutElementBar(cutElement);
+
+ AliAnalysisMuMuCutElement* added = AddCutElement(bar);
+
+ if (!added)
+ {
+ delete bar;
+ }
+
+ return added;
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuCutRegistry::Print(Option_t* opt) const
+{
+ /// Printout
+
+ TString sopt(opt);
+ sopt.ToUpper();
+
+ std::cout << "++++ Cut combinations defined : " << std::endl;
+
+ AliAnalysisMuMuCutElement::ECutType cutTypes[] = { AliAnalysisMuMuCutElement::kEvent, AliAnalysisMuMuCutElement::kTrack,
+ AliAnalysisMuMuCutElement::kTrackPair, AliAnalysisMuMuCutElement::kTriggerClass };
+
+ Int_t i(1);
+
+ for ( Int_t iCutType = 0; iCutType < 4; ++iCutType )
+ {
+ if (GetCutElements(cutTypes[iCutType])->IsEmpty()) continue;
+ std::cout << " Cutting on " << AliAnalysisMuMuCutElement::CutTypeName(cutTypes[iCutType]) << std::endl;
+ TIter next(GetCutCombinations(cutTypes[iCutType]));
+ AliAnalysisMuMuCutCombination* cutCombination;
+
+ while ( ( cutCombination = static_cast<AliAnalysisMuMuCutCombination*>(next())) )
+ {
+ std::cout << Form(" %4d ",i);
+ cutCombination->Print(" ");
+ ++i;
+ }
+ }
+
+ if ( sopt.Contains("FULL") || sopt.Contains("ALL") )
+ {
+ std::cout << "++++ Individual cuts defined : " << std::endl;
+
+ for ( Int_t iCutType = 0; iCutType < 4; ++iCutType )
+ {
+ if (GetCutElements(cutTypes[iCutType])->IsEmpty()) continue;
+ std::cout << " Cutting on " << AliAnalysisMuMuCutElement::CutTypeName(cutTypes[iCutType]) << std::endl;
+ TIter nextCutRef(GetCutElements(cutTypes[iCutType]));
+ AliAnalysisMuMuCutElement* ce;
+ i = 1;
+ while ( ( ce = static_cast<AliAnalysisMuMuCutElement*>(nextCutRef()) ) )
+ {
+ std::cout << Form("%4d ",i);
+ ce->Print();
+ ++i;
+ }
+ }
+ }
+}
--- /dev/null
+#ifndef ALIANALYSISMUMUCUTREGISTRY_H
+#define ALIANALYSISMUMUCUTREGISTRY_H
+
+/**
+ *
+ * \class AliAnalysisMuMuCutRegistry
+ *
+ * \brief Container of AliAnalysisMuMuCutElement and AliAnalysisMuMuCutCombination objects.
+ *
+ * \author L. Aphecetche (Subatech)
+ *
+ */
+
+#include "TObject.h"
+#include "TString.h"
+#include "TMethodCall.h"
+#include "AliAnalysisMuMuCutElement.h"
+
+class AliVEvent;
+class AliAnalysisMuMuCutCombination;
+class AliVParticle;
+class AliVEventHandler;
+
+class AliAnalysisMuMuCutRegistry : public TObject
+{
+public:
+ AliAnalysisMuMuCutRegistry();
+ virtual ~AliAnalysisMuMuCutRegistry();
+
+ AliAnalysisMuMuCutElement* AddEventCut(TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters);
+
+ AliAnalysisMuMuCutElement* AddTrackCut(TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters);
+
+ AliAnalysisMuMuCutElement* AddTrackPairCut(TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters);
+
+ AliAnalysisMuMuCutElement* AddTriggerClassCut(TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters);
+
+ AliAnalysisMuMuCutElement* Not(const AliAnalysisMuMuCutElement& cutElement);
+
+ AliAnalysisMuMuCutElement* AddCutElement(AliAnalysisMuMuCutElement* ce);
+
+ Int_t AddCutCombination(const TObjArray& cutElements);
+
+ Int_t AddCutCombination(AliAnalysisMuMuCutElement* ce1);
+ Int_t AddCutCombination(AliAnalysisMuMuCutElement* ce1, AliAnalysisMuMuCutElement* ce2);
+ Int_t AddCutCombination(AliAnalysisMuMuCutElement* ce1, AliAnalysisMuMuCutElement* ce2,
+ AliAnalysisMuMuCutElement* ce3);
+ Int_t AddCutCombination(AliAnalysisMuMuCutElement* ce1, AliAnalysisMuMuCutElement* ce2,
+ AliAnalysisMuMuCutElement* ce3, AliAnalysisMuMuCutElement* ce4);
+ Int_t AddCutCombination(AliAnalysisMuMuCutElement* ce1, AliAnalysisMuMuCutElement* ce2,
+ AliAnalysisMuMuCutElement* ce3, AliAnalysisMuMuCutElement* ce4,
+ AliAnalysisMuMuCutElement* ce5);
+ Int_t AddCutCombination(AliAnalysisMuMuCutElement* ce1, AliAnalysisMuMuCutElement* ce2,
+ AliAnalysisMuMuCutElement* ce3, AliAnalysisMuMuCutElement* ce4,
+ AliAnalysisMuMuCutElement* ce5, AliAnalysisMuMuCutElement* ce6);
+
+ const TObjArray* GetCutCombinations(AliAnalysisMuMuCutElement::ECutType type) const;
+ TObjArray* GetCutCombinations(AliAnalysisMuMuCutElement::ECutType type);
+
+ const TObjArray* GetCutElements(AliAnalysisMuMuCutElement::ECutType type) const;
+ TObjArray* GetCutElements(AliAnalysisMuMuCutElement::ECutType type);
+
+ virtual void Print(Option_t* opt="") const;
+
+ Bool_t AlwaysTrue(const AliVEvent& /*event*/) const { return kTRUE; }
+ void NameOfAlwaysTrue(TString& name) const { name="ALL"; }
+ Bool_t AlwaysTrue(const AliVEventHandler& /*eventHandler*/) const { return kTRUE; }
+ Bool_t AlwaysTrue(const AliVParticle& /*part*/) const { return kTRUE; }
+ Bool_t AlwaysTrue(const AliVParticle& /*p1*/, const AliVParticle& /*p2*/) const { return kTRUE; }
+
+private:
+
+ /// not implemented on purpose
+ AliAnalysisMuMuCutRegistry(const AliAnalysisMuMuCutRegistry& rhs);
+ /// not implemented on purpose
+ AliAnalysisMuMuCutRegistry& operator=(const AliAnalysisMuMuCutRegistry& rhs);
+
+ AliAnalysisMuMuCutElement* CreateCutElement(AliAnalysisMuMuCutElement::ECutType expectedType,
+ TObject& cutClass,
+ const char* cutMethodName,
+ const char* cutMethodPrototype,
+ const char* defaultParameters);
+
+private:
+
+ mutable TObjArray* fCutElements; // cut elements
+ mutable TObjArray* fCutCombinations; // cut combinations
+
+ ClassDef(AliAnalysisMuMuCutRegistry,1) // storage for cut pointers
+};
+
+#endif
--- /dev/null
+#include "AliAnalysisMuMuEventCutter.h"
+
+/**
+ *
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuEventCutter
+ *
+ * We're grouping here various event cut methods that can be used
+ * as AliAnalysisMuMuCutElement. For instance :
+ *
+ * - \ref IsPhysicsSelected this is the normal physics selection check
+ * - \ref IsPhysicsSelectedVDM version of the physics selection used for VdM analysis
+ * - \ref IsSPDzVertexInRange selects event with a SPDvertex in a given range
+ * - \ref IsAbsZBelowValue selects event with |Zvertex| (being SPD or not) below a given value
+ * - \ref IsAbsZBelowValue as above but requesting explicitely the SPD vertex
+ * - \ref IsSPDzQA whether the SPD vertex is a good one
+ */
+
+#include "TObjString.h"
+#include "AliLog.h"
+#include "AliMuonEventCuts.h"
+#include "TList.h"
+#include "Riostream.h"
+#include "AliVVertex.h"
+#include "AliAODVertex.h"
+#include "AliVVZERO.h"
+#include "AliInputEventHandler.h"
+#include "AliVEvent.h"
+#include "TMath.h"
+#include "AliESDTZERO.h"
+#include "AliAODTZERO.h"
+#include "AliESDEvent.h"
+#include "AliAODEvent.h"
+
+ClassImp(AliAnalysisMuMuEventCutter)
+
+//______________________________________________________________________________
+AliAnalysisMuMuEventCutter::AliAnalysisMuMuEventCutter(TList* triggerClasses)
+: TObject(), fMuonEventCuts(0x0)
+{
+ /// ctor
+ TString tclasses;
+
+ if ( !triggerClasses )
+ {
+ tclasses = "ANY";
+ }
+ else
+ {
+ TObjString* tname;
+ TIter next(triggerClasses);
+
+ while ( ( tname = static_cast<TObjString*>(next()) ) )
+ {
+ if (tclasses.Length()>0)
+ {
+ tclasses += ",";
+ }
+
+ tclasses += tname->String();
+ }
+ }
+
+ MuonEventCuts()->SetTrigClassPatterns(tclasses);
+}
+
+//______________________________________________________________________________
+AliAnalysisMuMuEventCutter::~AliAnalysisMuMuEventCutter()
+{
+ /// dtor
+ delete fMuonEventCuts;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::SelectTriggerClass(const TString& firedTriggerClasses,
+ TString& acceptedClasses,
+ UInt_t L0, UInt_t L1, UInt_t L2) const
+{
+ /// Forward the trigger class selection to MuonEventCuts::GetSelectedTrigClassesInEvent
+ acceptedClasses = "";
+
+ TIter next(MuonEventCuts()->GetSelectedTrigClassesInEvent(firedTriggerClasses,L0,L1,L2));
+ TObjString* str;
+
+ while ( ( str = static_cast<TObjString*>(next()) ) )
+ {
+ acceptedClasses += str->String();
+ acceptedClasses += " ";
+ }
+ return (acceptedClasses.Length()>0);
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::IsPhysicsSelected(const AliInputEventHandler& eventHandler) const
+{
+ /// Whether or not the event is physics selected
+ return const_cast<AliInputEventHandler&>(eventHandler).IsEventSelected() & AliVEvent::kAny;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::IsPhysicsSelectedVDM(const AliVEvent& event) const
+{
+ // cut used in vdM scans
+
+ AliVVZERO* vzero = event.GetVZEROData();
+
+ if (vzero)
+ {
+ Float_t v0a = vzero->GetV0ATime();
+ Float_t v0c = vzero->GetV0CTime();
+
+ Float_t v0diff = v0a-v0c;
+ Float_t v0sum = v0a+v0c;
+
+ if ( ( v0sum > 10.5 && v0sum < 18 ) && ( v0diff > 4 && v0diff < 12 ) )
+ {
+ return kTRUE;
+ }
+ }
+ return kFALSE;
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::IsAbsZBelowValue(const AliVEvent& event, const Double_t& z) const
+{
+ // Checks if the absolute value of the Z component of the primary vertex is below a certain value
+
+ const AliVVertex* vertex = event.GetPrimaryVertex();
+ return (TMath::Abs(vertex->GetZ())<=z);
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::IsAbsZSPDBelowValue(const AliVEvent& event, const Double_t& z) const
+{
+ // Checks if the absolute value of the SPD Z component of the given vertex is below a certain value
+ AliAODVertex* SPDVertex = static_cast<const AliAODEvent*>(&event)->GetPrimaryVertexSPD();
+
+ if ( !SPDVertex )
+ {
+ AliError("SPD |z| cut requested and no SPD vertex found in the event");
+ return kFALSE;
+ }
+
+ else return (TMath::Abs(SPDVertex->GetZ())<=z);
+}
+
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::IsSPDzVertexInRange(AliVEvent& event, const Double_t& zMin, const Double_t& zMax) const
+{
+ /// Whether or not the SPD Z vertex is in the range [zMin,zMax[
+
+ AliAODVertex* SPDVertex = static_cast<AliAODEvent*>(&event)->GetPrimaryVertexSPD();
+
+ if ( !SPDVertex )
+ {
+ AliError("Cut on SPD z Vertex requested for an event with no SPD vertex info");
+ return kFALSE;
+ }
+ Double_t zV = SPDVertex->GetZ();
+
+ if ( zV >= zMin && zV < zMax ) return kTRUE;
+ else return kFALSE;
+}
+
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::HasSPDVertex(AliVEvent& event) const
+{
+ /// Does the event have a SPD vertex ?
+ AliAODVertex* SPDVertex = static_cast<AliAODEvent*>(&event)->GetPrimaryVertexSPD();
+ if ( SPDVertex && SPDVertex->GetNContributors() > 0) return kTRUE;
+ else return kFALSE;
+}
+
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::IsSPDzQA(const AliVEvent& event, /*const AliVVertex& vertex2Test,*/ const Double_t& zResCut, const Double_t& zDifCut) const
+{
+ // Checks if the value of the Z component of the given vertex fullfills the quality assurance condition
+
+ const AliVVertex* vertex = event.GetPrimaryVertex();
+ const AliAODVertex* vertex2Test = static_cast<const AliAODEvent*>(&event)->GetPrimaryVertexSPD();
+
+ Double_t cov[6]={0};
+ vertex2Test->GetCovarianceMatrix(cov);
+ Double_t zRes = TMath::Sqrt(cov[5]);
+
+ if ( (zRes < zResCut) && TMath::Abs(vertex2Test->GetZ() - vertex->GetZ()) <= zDifCut )
+ {
+ return kTRUE;
+ }
+ else return kFALSE;
+}
+
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::IsMeandNchdEtaInRange(AliVEvent& event, const Double_t& dNchdEtaMin, const Double_t& dNchdEtaMax) const
+{
+ TList* nchList = static_cast<TList*>(event.FindListObject("NCH"));
+
+ if (!nchList || nchList->IsEmpty())
+ {
+ AliFatal("No NCH information found in event. Nch analysis MUST be executed to apply a NCH cut");
+ return kFALSE;
+ }
+
+ Int_t i(0);
+
+ while ( nchList->At(i)->IsA() != TObjString::Class() ) //Asign a name to find it by name
+ {
+ i++;
+ }
+
+ TObjString* value = static_cast<TObjString*>(nchList->At(i));
+ Double_t meandNchdEta = value->String().Atof();
+
+ if ( meandNchdEta >= dNchdEtaMin && meandNchdEta < dNchdEtaMax ) return kTRUE;
+ else return kFALSE;
+}
+
+
+//_____________________________________________________________________________
+AliMuonEventCuts*
+AliAnalysisMuMuEventCutter::MuonEventCuts() const
+{
+ /// Return the single instance of AliMuonEventCuts object we're using
+
+ if (!fMuonEventCuts)
+ {
+ fMuonEventCuts = new AliMuonEventCuts("EventCut","");
+ }
+ return fMuonEventCuts;
+}
+
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuEventCutter::NameOfIsSPDzVertexInRange(TString& name, const Double_t& zMin, const Double_t& zMax) const
+{
+ name.Form("SPDZBTW%3.2f_%3.2f",zMin,zMax);
+}
+//_____________________________________________________________________________
+void AliAnalysisMuMuEventCutter::NameOfIsAbsZBelowValue(TString& name, const Double_t& z) const
+{
+ name.Form("ABSZLT%3.2f",z);
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuEventCutter::NameOfIsAbsZSPDBelowValue(TString& name, const Double_t& z) const
+{
+ name.Form("SPDABSZLT%3.2f",z);
+}
+
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuEventCutter::NameOfIsSPDzQA(TString& name, const Double_t& zResCut, const Double_t& zDifCut) const
+{
+ name.Form("SPDZQA_RES%3.2f_ZDIF%3.2f",zResCut,zDifCut);
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuEventCutter::NameOfIsMeandNchdEtaInRange(TString& name, const Double_t& dNchdEtaMin, const Double_t& dNchdEtaMax) const
+{
+ name.Form("MEANDNDETABTW%3.2f_%3.2f",dNchdEtaMin,dNchdEtaMax);
+}
+
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuEventCutter::IsTZEROPileUp(const AliVEvent& event) const
+{
+ Bool_t pileupFlag(kFALSE);
+
+ if ( event.IsA() == AliESDEvent::Class() )
+ {
+ const AliESDTZERO* tzero = static_cast<AliESDEvent&>(const_cast<AliVEvent&>(event)).GetESDTZERO();
+ if ( tzero )
+ {
+ pileupFlag = tzero->GetPileupFlag();
+ }
+ }
+ else if ( event.IsA() == AliAODEvent::Class() )
+ {
+ AliAODTZERO* tzero = static_cast<const AliAODEvent&>(event).GetTZEROData();
+ if ( tzero )
+ {
+ pileupFlag = tzero->GetPileupFlag();
+ }
+ }
+ return pileupFlag;
+}
--- /dev/null
+#ifndef ALIANALYSISMUMUEVENTCUTTER_H
+#define ALIANALYSISMUMUEVENTCUTTER_H
+
+/**
+ *
+ * \class AliAnalysisMuMuEventCutter
+ *
+ * \brief Various event cuts used in AliAnalysisTaskMuMu
+ *
+ * \author L. Aphecetche and J. Martin-Bianco
+ *
+ */
+
+#include "TObject.h"
+#include "TString.h"
+
+class AliMuonEventCuts;
+class TList;
+class AliVEvent;
+class AliVVertex;
+class AliInputEventHandler;
+
+class AliAnalysisMuMuEventCutter : public TObject
+{
+public:
+ AliAnalysisMuMuEventCutter(TList* triggerClassesToConsider=0x0);
+ virtual ~AliAnalysisMuMuEventCutter();
+
+ Bool_t SelectTriggerClass(const TString& firedTriggerClasses, TString& acceptedClasses,
+ UInt_t L0, UInt_t L1, UInt_t L2) const;
+
+ Bool_t IsTrue(const AliVEvent& /*event*/) const { return kTRUE; }
+ void NameOfIsTrue(TString& name) const { name="ALL"; }
+
+ Bool_t IsFalse(const AliVEvent& /*event*/) const { return kFALSE; }
+ void NameOfIsFalse(TString& name) const { name="NONE"; }
+
+ Bool_t IsPhysicsSelected(const AliInputEventHandler& eventHandler) const;
+ void NameOfIsPhysicsSelected(TString& name) const { name="PSALL"; }
+
+ Bool_t IsPhysicsSelectedVDM(const AliVEvent& event) const;
+ void NameOfIsPhysicsSelectedVDM(TString& name) const { name="VDM"; }
+
+ Bool_t IsAbsZBelowValue(const AliVEvent& event, const Double_t& z) const;
+ void NameOfIsAbsZBelowValue(TString& name, const Double_t& z) const;
+
+ Bool_t IsAbsZSPDBelowValue(const AliVEvent& event, const Double_t& z) const;
+ void NameOfIsAbsZSPDBelowValue(TString& name, const Double_t& z) const;
+
+ Bool_t IsSPDzVertexInRange(AliVEvent& event, const Double_t& zMin, const Double_t& zMax) const;
+ void NameOfIsSPDzVertexInRange(TString& name, const Double_t& zMin, const Double_t& zMax) const;
+
+ Bool_t IsSPDzQA(const AliVEvent& event/*, const AliVVertex& vertex2Test*/, const Double_t& zResCut, const Double_t& zDifCut) const;
+ void NameOfIsSPDzQA(TString& name, const Double_t& zResCut, const Double_t& zDifCut) const;
+
+ Bool_t HasSPDVertex(AliVEvent& event) const;
+ void NameOfHasSPDVertex(TString& name) const { name = "HASSPD"; }
+
+ Bool_t IsMeandNchdEtaInRange(AliVEvent& event, const Double_t& dNchdEtaMin, const Double_t& dNchdEtaMax) const;
+ void NameOfIsMeandNchdEtaInRange(TString& name, const Double_t& dNchdEtaMin, const Double_t& dNchdEtaMax) const;
+
+ Bool_t IsTZEROPileUp(const AliVEvent& event) const;
+ void NameOfIsTZEROPileUp(TString& name) const { name="TZEROPILEUP"; }
+
+ AliMuonEventCuts* MuonEventCuts() const;
+
+// enum EEventCut
+// {
+// kEventIR2PILEUP = BIT( 6), /// events with pile-up (using AliAnalysisUtils::IsOutOfBunchPileUp)
+//
+// kEventGOODVERTEX = BIT(10), /// events with a good vertex
+// kEventZPOS = BIT(14), /// events with z > 0
+// kEventZNEG = BIT(15), /// events with z < 0
+//
+// kEventTRKLETA1 = BIT(20), /// event with at least one tracklet in |eta| < fTrackletEtaCutValue[0]
+
+// kEvent0TVX = BIT(31), /// events with 0TVX L0 input
+// kEventV0AND = BIT(32), /// events with both 0V0C and 0V0A L0 inputs
+// kEvent0SM2 = BIT(33), /// events with 0SM2 L0 input
+// kEvent0MSL = BIT(34), /// events with 0MSL input
+// };
+
+private:
+
+ mutable AliMuonEventCuts* fMuonEventCuts; // common cuts for muon events (from Diego)
+
+ ClassDef(AliAnalysisMuMuEventCutter,1) // default event cutters for AliAnalysisTaskMuMu
+};
+
+#endif
--- /dev/null
+#include "AliAnalysisMuMuGlobal.h"
+
+/**
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuGlobal
+ *
+ * Very simple histogramming analysis for global event properties, like vertex, bunch-crossing,
+ * background, etc...
+ *
+ * Warning : not really ready for prime-time
+ *
+ */
+
+#include "TH1.h"
+#include "AliVVertex.h"
+#include "AliVEvent.h"
+#include "AliAODEvent.h"
+#include "AliAnalysisMuonUtility.h"
+#include "AliAODTZERO.h"
+#include "AliESDEvent.h"
+#include "AliAnalysisMuMuBinning.h"
+#include <set>
+#include "AliMergeableCollection.h"
+#include "AliAnalysisMuonUtility.h"
+
+ClassImp(AliAnalysisMuMuGlobal)
+
+//_____________________________________________________________________________
+AliAnalysisMuMuGlobal::AliAnalysisMuMuGlobal() : AliAnalysisMuMuBase()
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuGlobal::DefineHistogramCollection(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality)
+{
+ /// Actually create the histograms for phyics/triggerClassName
+
+ // AliInfo(Form("%s %s %s %d",eventSelection,triggerClassName,centrality,hasMC));
+
+ if (HistogramCollection()->Histo(Form("/%s/%s/%s/Zvertex",eventSelection,triggerClassName,centrality)))
+ {
+ return;
+ }
+
+ Double_t xmin = -40;
+ Double_t xmax = +40;
+ Int_t nbins = GetNbins(xmin,xmax,0.5);
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"Zvertex","z vertex",nbins,xmin,xmax);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"T0Zvertex","T0 zvertex",nbins,xmin,xmax);
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,
+ "RecZvertexVsMCZvertex","Reconstructed vertex (w/ Ncontrib>=1) vs MC vertex",nbins,xmin,xmax,nbins,xmin,xmax);
+
+ xmin = -5;
+ xmax = 5;
+ nbins = GetNbins(xmin,xmax,0.01);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"ZvertexMinusZvertexSPD","Primary vertex z - SPD vertex",nbins,xmin,xmax);
+
+ xmin = -1;
+ xmax = 50;
+ nbins = GetNbins(xmin,xmax,1);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"ZvertexNContributors","z vertex nof contributors",nbins,xmin,xmax);
+
+ xmin = -2;
+ xmax = 2;
+ nbins = GetNbins(xmin,xmax,0.01);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"Xvertex","x vertex",nbins,xmin,xmax);
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"Yvertex","y vertex",nbins,xmin,xmax);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"Nevents","number of events",2,-0.5,1.5);
+
+ CreateEventHistos(kHistoForMCInput | kHistoForData,eventSelection,triggerClassName,centrality,
+ "VertexType","Type of vertexer used",10,0,10);
+
+
+ xmin = 0;
+ xmax = 3564;
+ nbins = GetNbins(xmin,xmax,1.0);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"BCX","bunch-crossing ids",nbins,xmin-0.5,xmax-0.5);
+
+
+ xmin = -30;
+ xmax = +30;
+ nbins = GetNbins(xmin,xmax,0.1);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"V02D","V0C+V0A versus V0A-V0C;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"V02DwT0BB","V0C+V0A versus V0A-V0C with T0 BB;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"V02DwT0BG","V0C+V0A versus V0A-V0C with T0 background flag on;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"V02DwT0PU","V0C+V0A versus V0A-V0C with T0 pile up flag on;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"V02DwT0SAT","V0C+V0A versus V0A-V0C with T0 satellite flag on;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
+
+ xmin = 0;
+ xmax = 600;
+ nbins = GetNbins(xmin,xmax,1);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"V0AMult","V0A multiplicity",nbins,xmin,xmax);
+
+ if ( !IsHistogramDisabled("Centrality") )
+ {
+ TObjArray* centralities = Binning()->CreateBinObjArray("centrality");
+ TIter next(centralities);
+ AliAnalysisMuMuBinning::Range* r;
+ std::set<std::string> estimators;
+
+ while ( ( r = static_cast<AliAnalysisMuMuBinning::Range*>(next())) )
+ {
+ estimators.insert(r->Quantity().Data());
+ }
+
+ std::set<std::string>::const_iterator it;
+
+ for ( it = estimators.begin(); it != estimators.end(); ++it )
+ {
+ TH1* h = new TH1F("Centrality","Centrality",12,-10,110);
+ HistogramCollection()->Adopt(Form("/%s/%s/%s",eventSelection,triggerClassName,it->c_str()),h);
+ }
+
+ delete centralities;
+ }
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"PileUpEstimators","pile up estimators",10,0,10);
+}
+
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuGlobal::FillHistosForEvent(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality)
+{
+ // Fill event-wise histograms
+
+ if (!IsHistogramDisabled("BCX"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"BCX")->Fill(1.0*Event()->GetBunchCrossNumber());
+ }
+ if (!IsHistogramDisabled("Nevents"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"Nevents")->Fill(1.0);
+ }
+
+ const AliVVertex* vertex = Event()->GetPrimaryVertex();
+ const AliVVertex* vertexFromSPD = AliAnalysisMuonUtility::GetVertexSPD(Event());
+
+ if ( vertex && vertexFromSPD )
+ {
+ if ( vertex->GetNContributors() > 0 )
+ {
+ if (!IsHistogramDisabled("Xvertex"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"Xvertex")->Fill(vertex->GetX());
+ }
+ if (!IsHistogramDisabled("Yvertex"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"Yvertex")->Fill(vertex->GetY());
+ }
+ if (!IsHistogramDisabled("Zvertex"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"Zvertex")->Fill(vertex->GetZ());
+ }
+ if (!IsHistogramDisabled("ZvertexMinusZvertexSPD"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"ZvertexMinusZvertexSPD")->Fill(vertexFromSPD->GetZ()-vertex->GetZ());
+ }
+ if (!IsHistogramDisabled("VertexType"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"VertexType")->Fill(vertex->GetTitle(),1.0);
+ }
+ }
+ if (!IsHistogramDisabled("ZvertexNContributors"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"ZvertexNContributors")->Fill(vertex->GetNContributors());
+ }
+ }
+
+ if ( AliAnalysisMuonUtility::IsAODEvent(Event()) )
+ {
+ const AliAODTZERO* tzero = static_cast<const AliAODEvent*>(Event())->GetTZEROData();
+
+ if (tzero && !IsHistogramDisabled("T0Zvertex"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"T0Zvertex")->Fill(tzero->GetT0VertexRaw());
+ }
+ }
+ else
+ {
+ const AliESDTZERO* tzero = static_cast<const AliESDEvent*>(Event())->GetESDTZERO();
+
+ if (tzero && !IsHistogramDisabled("T0Zvertex"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"T0Zvertex")->Fill(tzero->GetT0zVertex());
+ }
+ }
+
+ AliVVZERO* vzero = Event()->GetVZEROData();
+
+ if (vzero)
+ {
+ Float_t v0a = vzero->GetV0ATime();
+ Float_t v0c = vzero->GetV0CTime();
+
+ Float_t x = v0a-v0c;
+ Float_t y = v0a+v0c;
+
+ if (!IsHistogramDisabled("V0A"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"V0AMult")->Fill(vzero->GetMTotV0A());
+ }
+ if (!IsHistogramDisabled("V02D"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"V02D")->Fill(x,y);
+ }
+
+ Bool_t background,pileup,satellite;
+
+ Bool_t tzero = AliAnalysisMuonUtility::EAGetTZEROFlags(Event(),background,pileup,satellite);
+
+ if (tzero)
+ {
+ if ( background )
+ {
+ if (!IsHistogramDisabled("V02DwT0BG"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"V02DwT0BG")->Fill(x,y);
+ }
+ }
+
+ if ( pileup )
+ {
+ if (!IsHistogramDisabled("V02DwT0PU"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"V02DwT0PU")->Fill(x,y);
+ }
+
+ if ( !IsHistogramDisabled("PileUpEstimators") )
+ {
+ Histo(eventSelection,triggerClassName,centrality,"PileUpEstimators")->Fill("TZERO",1.0);
+ }
+ }
+
+ if ( satellite )
+ {
+ if (!IsHistogramDisabled("V02DwT0SAT"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"V02DwT0SAT")->Fill(x,y);
+ }
+ }
+
+ if ( !background && !pileup && !satellite )
+ {
+ if (!IsHistogramDisabled("V02DwT0BB"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,"V02DwT0BB")->Fill(x,y);
+ }
+ }
+ }
+ }
+
+ // /* FIXME : how to properly get multiplicity from AOD and ESD consistently ?
+ // is is doable at all ?
+
+ TH1* hpileup = Histo(eventSelection,triggerClassName,centrality,"PileUpEstimators");
+
+
+ // virtual Bool_t IsPileupFromSPD(Int_t minContributors=3, Double_t minZdist=0.8, Double_t nSigmaZdist=3., Double_t nSigmaDiamXY=2., Double_t nSigmaDiamZ=5.) const;
+
+ const Double_t nSigmaZdist=3.0;
+ const Double_t nSigmaDiamXY=2.0;
+ const Double_t nSigmaDiamZ=5.0;
+
+ for ( Int_t minContributors = 3; minContributors <= 6; ++minContributors )
+ {
+ for ( double minZdist = 0.6; minZdist <= 0.8; minZdist += 0.2 )
+ {
+ if ( Event()->IsPileupFromSPD(minContributors,minZdist,nSigmaZdist,nSigmaDiamXY,nSigmaDiamZ) )
+ {
+ hpileup->Fill(Form("SPD:n%dd%d",minContributors,static_cast<Int_t>(10*minZdist)),1);
+ }
+ }
+ }
+
+
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuGlobal::FillHistosForMCEvent(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality)
+{
+ // Fill MCEvent-wise histograms
+
+ Double_t Zvertex = AliAnalysisMuonUtility::GetMCVertexZ(Event(),MCEvent());
+
+ if (!IsHistogramDisabled("Zvertex"))
+ {
+ MCHisto(eventSelection,triggerClassName,centrality,"Zvertex")->Fill(Zvertex);
+ }
+
+ if (!IsHistogramDisabled("RecZvertexVsMCZvertex"))
+ {
+ const AliVVertex* vertex = Event()->GetPrimaryVertex();
+ if (vertex && vertex->GetNContributors()>0)
+ {
+ MCHisto(eventSelection,triggerClassName,centrality,"RecZvertexVsMCZvertex")->Fill(Zvertex,vertex->GetZ());
+ }
+ }
+
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuGlobal::SelectAnyTriggerClass(const TString& firedTriggerClasses, TString& acceptedTriggerClasses) const
+{
+ /// Accept all trigger classes
+ if ( firedTriggerClasses.Length()>0)
+ {
+ acceptedTriggerClasses = "NOTRIGGERSELECTION";
+ return kTRUE;
+ }
+ return kFALSE;
+}
+
--- /dev/null
+#ifndef ALIANALYSISMUMUGLOBAL_H
+#define ALIANALYSISMUMUGLOBAL_H
+
+/**
+ * \class AliAnalysisMuMuGlobal
+ * \brief Basic histogramming of global event properties (vertex, pile-up, background)
+ * \author L. Aphecetche (Subatech)
+ */
+
+#include "AliAnalysisMuMuBase.h"
+
+class AliAnalysisMuMuGlobal : public AliAnalysisMuMuBase
+{
+public:
+ AliAnalysisMuMuGlobal();
+ virtual ~AliAnalysisMuMuGlobal() {}
+
+ void FillHistosForEvent(const char* eventSelection, const char* triggerClassName,
+ const char* centrality);
+
+ void FillHistosForMCEvent(const char* eventSelection, const char* triggerClassName,
+ const char* centrality);
+
+ virtual void DefineHistogramCollection(const char* eventSelection, const char* triggerClassName,
+ const char* centrality);
+
+ Bool_t SelectAnyTriggerClass(const TString& firedTriggerClasses, TString& acceptedTriggerClasses) const;
+
+
+private:
+ ClassDef(AliAnalysisMuMuGlobal,1) // implementation of AliAnalysisMuMuBase for global event properties
+};
+
+#endif
--- /dev/null
+#include "AliAnalysisMuMuMinv.h"
+
+/**
+ *
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuMinv
+ *
+ * Analysis which fills a bunch of histograms for invariant mass analysis of J/psi
+ *
+ * Can be used on real data and/or simulated (for instance to get Acc x Eff)
+ *
+ * Can optionally use as input an already computed Acc x Eff matrix that will be applied
+ * when filling the invariant mass histograms.
+ *
+ */
+
+#include "TH2F.h"
+#include "AliLog.h"
+#include "TObjArray.h"
+#include "AliAnalysisMuMuBinning.h"
+#include "TString.h"
+#include "TLorentzVector.h"
+#include "TString.h"
+#include "AliMCEvent.h"
+#include "AliMergeableCollection.h"
+#include "AliAnalysisMuonUtility.h"
+#include "TParameter.h"
+#include <cassert>
+
+ClassImp(AliAnalysisMuMuMinv)
+
+//_____________________________________________________________________________
+AliAnalysisMuMuMinv::AliAnalysisMuMuMinv()
+: AliAnalysisMuMuBase(),
+fAccEffHisto(0x0)
+{
+ // FIXME : find the AccxEff histogram from HistogramCollection()->Histo("/EXCHANGE/JpsiAccEff")
+
+// if ( accEff )
+// {
+// fAccEffHisto = static_cast<TH2F*>(accEff->Clone());
+// fAccEffHisto->SetDirectory(0);
+// }
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuMinv::~AliAnalysisMuMuMinv()
+{
+ /// dtor
+ delete fAccEffHisto;
+}
+
+//_____________________________________________________________________________
+void
+AliAnalysisMuMuMinv::DefineHistogramCollection(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality)
+{
+ /// Define the histograms this analysis will use
+
+ if ( Histo(eventSelection,triggerClassName,centrality,"AliAnalysisMuMuMinv") )
+ {
+ return;
+ }
+
+ // dummy histogram to signal that we already defined all our histograms (see above)
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"AliAnalysisMuMuMinv","Dummy semaphore",1,0,1);
+
+ /// Create invariant mass histograms
+
+ Double_t minvMin = 0;
+ Double_t minvMax = 16;
+ Int_t nMinvBins = GetNbins(minvMin,minvMax,0.025);
+
+ Int_t nMCMinvBins = GetNbins(minvMin,minvMax,0.1);
+
+ // TObjArray* bins = fBinning->CreateBinObjArray("psi","y vs pt,integrated,pt,y,phi","");
+ TObjArray* bins = Binning()->CreateBinObjArray("psi");
+
+ CreatePairHistos(eventSelection,triggerClassName,centrality,"Pt","#mu+#mu- Pt distribution",
+ 200,0,20);
+
+ Int_t nbinsy = 6;
+ Double_t ymin = -4.0;
+ Double_t ymax = -2.5;
+
+ CreatePairHistos(eventSelection,triggerClassName,centrality,"y","#mu+#mu- y distribution",nbinsy,ymin,ymax);
+
+ // CreatePairHistos(eventSelection,triggerClassName,centrality,"BinFlowPt","#mu+#mu- BinFlowPt distribution",
+ // 200,0,20);
+
+ CreatePairHistos(eventSelection,triggerClassName,centrality,"PtRecVsSim","#mu+#mu- Pt distribution rec vs sim",
+ 200,0,20,200,0,20);
+
+ if (!Histo("INPUT","ALL","Pt"))
+ {
+ HistogramCollection()->Adopt("/INPUT/ALL",new TH1F("Pt","Pt",200,0,20));
+ HistogramCollection()->Adopt("/INPUT/INYRANGE",new TH1F("Pt","Pt",200,0,20));
+ HistogramCollection()->Adopt("/INPUT/ALL",new TH1F("Y","Y",nbinsy,ymin,ymax));
+ HistogramCollection()->Adopt("/INPUT/INYRANGE",new TH1F("Y","Y",nbinsy,ymin,ymax));
+ }
+
+ TIter next(bins);
+ AliAnalysisMuMuBinning::Range* r;
+ Int_t nb(0);
+
+ while ( ( r = static_cast<AliAnalysisMuMuBinning::Range*>(next()) ) )
+ {
+ TString minvName(GetMinvHistoName(*r,ShouldCorrectDimuonForAccEff()));
+
+ if ( IsHistogramDisabled(minvName.Data()) ) continue;
+
+ ++nb;
+
+ AliDebug(1,Form("bin %d %s histoname = %s",nb,r->AsString().Data(),minvName.Data()));
+
+ CreatePairHistos(eventSelection,triggerClassName,centrality,minvName.Data(),
+ Form("#mu+#mu- inv. mass %s %s;M_{#mu^+#mu^-} (GeV/c^2)",
+ ShouldCorrectDimuonForAccEff() ? "(AccxEff corrected)":"",
+ r->AsString().Data()),
+ nMinvBins,minvMin,minvMax);
+
+ TString hname(GetMinvHistoName(*r,kFALSE));
+
+ TH1* h = HistogramCollection()->Histo("/INPUT/ALL",hname.Data());
+ if (!h)
+ {
+ h = new TH1F(hname.Data(),Form("MC #mu+#mu- inv. mass %s",r->AsString().Data()),
+ nMCMinvBins,minvMin,minvMax);
+
+ HistogramCollection()->Adopt("/INPUT/ALL",h);
+
+ HistogramCollection()->Adopt("/INPUT/INYRANGE",static_cast<TH1*>(h->Clone()));
+ }
+ }
+
+ delete bins;
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuMinv::FillHistosForPair(const char* eventSelection, const char* triggerClassName,
+ const char* centrality, const char* pairCutName,
+ const AliVParticle& tracki,
+ const AliVParticle& trackj)
+{
+ /** Fill histograms for muon track pairs
+ */
+
+ if (!AliAnalysisMuonUtility::IsMuonTrack(&tracki) ) return;
+ if (!AliAnalysisMuonUtility::IsMuonTrack(&trackj) ) return;
+
+ TLorentzVector pi(tracki.Px(),tracki.Py(),tracki.Pz(),
+ TMath::Sqrt(AliAnalysisMuonUtility::MuonMass2()+tracki.P()*tracki.P()));
+
+
+ TLorentzVector pair4Momentum(trackj.Px(),trackj.Py(),trackj.Pz(),
+ TMath::Sqrt(AliAnalysisMuonUtility::MuonMass2()+trackj.P()*trackj.P()));
+
+ pair4Momentum += pi;
+
+
+ if (!IsHistogramDisabled("Chi12"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,pairCutName,"Chi12")
+ ->Fill(
+ AliAnalysisMuonUtility::GetChi2perNDFtracker(&tracki),
+ AliAnalysisMuonUtility::GetChi2perNDFtracker(&trackj));
+ }
+
+ if (!IsHistogramDisabled("Rabs12"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,pairCutName,"Rabs12")
+ ->Fill(AliAnalysisMuonUtility::GetRabs(&tracki),
+ AliAnalysisMuonUtility::GetRabs(&trackj));
+ }
+
+ if ( ( tracki.Charge() != trackj.Charge() ) )
+ {
+ if ( !IsHistogramDisabled("Pt") )
+ {
+ Histo(eventSelection,triggerClassName,centrality,pairCutName,"Pt")->Fill(pair4Momentum.Pt());
+ }
+
+ if ( !IsHistogramDisabled("y") )
+ {
+ Histo(eventSelection,triggerClassName,centrality,pairCutName,"y")->Fill(pair4Momentum.Y());
+ }
+
+ if ( HasMC() )
+ {
+ Int_t labeli = tracki.GetLabel();
+ Int_t labelj = trackj.GetLabel();
+
+ if ( labeli < 0 || labelj < 0 )
+ {
+ AliError("Got negative labels!");
+ }
+ else
+ {
+ AliVParticle* mcTracki = MCEvent()->GetTrack(labeli);
+ AliVParticle* mcTrackj = MCEvent()->GetTrack(labelj);
+
+ TLorentzVector mcpi(mcTracki->Px(),mcTracki->Py(),mcTracki->Pz(),
+ TMath::Sqrt(AliAnalysisMuonUtility::MuonMass2()+mcTracki->P()*mcTracki->P()));
+ TLorentzVector mcpj(mcTrackj->Px(),mcTrackj->Py(),mcTrackj->Pz(),
+ TMath::Sqrt(AliAnalysisMuonUtility::MuonMass2()+mcTrackj->P()*mcTrackj->P()));
+
+ mcpj += mcpi;
+
+ Histo(eventSelection,triggerClassName,centrality,pairCutName,"PtRecVsSim")->Fill(mcpj.Pt(),pair4Momentum.Pt());
+
+ }
+ }
+
+
+ TObjArray* bins = Binning()->CreateBinObjArray("psi","ptvsy,yvspt,pt,y,phi","");
+ TIter nextBin(bins);
+ AliAnalysisMuMuBinning::Range* r;
+
+ while ( ( r = static_cast<AliAnalysisMuMuBinning::Range*>(nextBin()) ) )
+ {
+ Bool_t ok(kFALSE);
+
+ if ( r->IsIntegrated() )
+ {
+ ok = kTRUE;
+ }
+ else if ( r->Is2D() )
+ {
+ if ( r->AsString().BeginsWith("PTVSY") )
+ {
+ ok = r->IsInRange(pair4Momentum.Rapidity(),pair4Momentum.Pt());
+ }
+ else if ( r->AsString().BeginsWith("YVSPT") )
+ {
+ ok = r->IsInRange(pair4Momentum.Pt(),pair4Momentum.Rapidity());
+ }
+ else
+ {
+ AliError(Form("Don't know how to deal with 2D bin %s",r->AsString().Data()));
+ }
+ }
+ else
+ {
+ if ( r->Quantity() == "PT" )
+ {
+ ok = r->IsInRange(pair4Momentum.Pt());
+ }
+ else if ( r->Quantity() == "Y" )
+ {
+ ok = r->IsInRange(pair4Momentum.Rapidity());
+ }
+ else if ( r->Quantity() == "PHI" )
+ {
+ ok = r->IsInRange(pair4Momentum.Phi());
+ }
+ else if ( r->Quantity() == "NCH" )
+ {
+ TList* list = static_cast<TList*>(Event()->FindListObject("NCH"));
+ if (list)
+ {
+ TIter next(list);
+ TParameter<Double_t>* p;
+
+ while ( ( p = static_cast<TParameter<Double_t>*>(next())) )
+ {
+ if (TString(eventSelection).Contains(p->GetName()))
+ {
+ ok = r->IsInRange(p->GetVal());
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if ( ok )
+ {
+ TString minvName = GetMinvHistoName(*r,kFALSE);
+
+ if (!IsHistogramDisabled(minvName.Data()))
+ {
+ TH1* h = Histo(eventSelection,triggerClassName,centrality,pairCutName,minvName.Data());
+
+ if (!h)
+ {
+ AliError(Form("Could not get %s",minvName.Data()));
+ continue;
+ }
+ h->Fill(pair4Momentum.M());
+
+ if ( fAccEffHisto )
+ {
+ // FIXME : fill Minv with weight = 1/AccxEff
+ }
+ }
+ }
+ }
+
+ delete bins;
+ }
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuMinv::FillHistosForMCEvent(const char* /*eventSelection*/,
+ const char* /*triggerClassName*/,
+ const char* /*centrality*/)
+{
+ /** Fill histograms for MC event
+ *
+ * FIXME: this is here we should streamline a bit the code to carefully
+ * compute the measured and truth values for Pt, Y, and (Pt,Y), in order
+ * to be able to investigate unfolding techniques later on...
+ */
+
+ Int_t nMCTracks = MCEvent()->GetNumberOfTracks();
+
+ for ( Int_t i = 0; i < nMCTracks; ++i )
+ {
+ AliVParticle* part = MCEvent()->GetTrack(i);
+
+ if ( AliAnalysisMuonUtility::IsPrimary(part,MCEvent()) &&
+ AliAnalysisMuonUtility::GetMotherIndex(part)==-1 )
+ {
+ Histo("INPUT","ALL","Pt")->Fill(part->Pt());
+ Histo("INPUT","ALL","Y")->Fill(part->Y());
+ if ( part->Y() < -2.5 && part->Y() > -4.0 )
+ {
+ Histo("INPUT","INYRANGE","Pt")->Fill(part->Pt());
+ Histo("INPUT","INYRANGE","Y")->Fill(part->Y());
+ }
+
+ }
+
+ }
+
+// Int_t nTracks = AliAnalysisMuonUtility::GetNTracks(Event());
+//
+// Double_t measuredY(0.0);
+//
+// for (Int_t i = 0; i < nTracks; ++i)
+// {
+// AliVParticle* tracki = AliAnalysisMuonUtility::GetTrack(i,Event());
+//
+// if (!AliAnalysisMuonUtility::IsMuonTrack(tracki) ) continue;
+//
+// for (Int_t j = i+1; j < nTracks; ++j )
+// {
+// AliVParticle* trackj = AliAnalysisMuonUtility::GetTrack(j,Event());
+//
+// if (!AliAnalysisMuonUtility::IsMuonTrack(trackj) ) continue;
+//
+// TLorentzVector pi(tracki->Px(),tracki->Py(),tracki->Pz(),
+// TMath::Sqrt(AliAnalysisMuonUtility::MuonMass2()+tracki->P()*tracki->P()));
+//
+// TLorentzVector pair4Momentum(trackj->Px(),trackj->Py(),trackj->Pz(),
+// TMath::Sqrt(AliAnalysisMuonUtility::MuonMass2()+trackj->P()*trackj->P()));
+//
+// pair4Momentum += pi;
+//
+// measuredY = pi.Y();
+//
+// rur->Fill(measuredY,trueY); // FIXME : is this working if more than one pair is found in the reconstructed tracks ???
+// // should we try to find the closest one in minv and assign the other(s)
+// // to rur->Fake() ?
+// }
+//
+// }
+//
+// if ( ! ( measuredY < 0.0 ) )
+// {
+// rur->Miss(trueY);
+// }
+}
+
+////_____________________________________________________________________________
+//void AliAnalysisMuMuMinv::FillMC()
+//{
+// // Fill the input Monte-Carlo histograms related to muons
+//
+// // Specific things for MC
+// if (!Histo("INPUT","ALL","Pt"))
+// {
+// HistogramCollection()->Adopt("/INPUT/ALL",new TH1F("Pt","Pt",200,0,20));
+// HistogramCollection()->Adopt("/INPUT/INYRANGE",new TH1F("Pt","Pt",200,0,20));
+//
+// Double_t rapidityMin = -5;
+// Double_t rapidityMax = -2;
+// Int_t nbinsRapidity = GetNbins(rapidityMin,rapidityMax,0.05);
+//
+// HistogramCollection()->Adopt("/INPUT/ALL",new TH1F("Y","Y",nbinsRapidity,rapidityMin,rapidityMax));
+// HistogramCollection()->Adopt("/INPUT/INYRANGE",new TH1F("Y","Y",nbinsRapidity,rapidityMin,rapidityMax));
+//
+// Double_t etaMin = -5;
+// Double_t etaMax = -2;
+// Int_t nbinsEta = GetNbins(etaMin,etaMax,0.05);
+//
+// HistogramCollection()->Adopt("/INPUT/ALL",new TH1F("Eta","Eta",nbinsEta,etaMin,etaMax));
+// HistogramCollection()->Adopt("/INPUT/INYRANGE",new TH1F("Eta","Eta",nbinsEta,etaMin,etaMax));
+// }
+//
+// Int_t nMCTracks = MCEvent()->GetNumberOfTracks();
+//
+// TObjArray* bins = Binning()->CreateBinObjArray("psi","ptvsy,yvspt,pt,y,phi","");
+// TIter nextBin(bins);
+// AliAnalysisMuMuBinning::Range* r;
+//
+// for ( Int_t i = 0; i < nMCTracks; ++i )
+// {
+// AliVParticle* part = MCEvent()->GetTrack(i);
+//
+// // std::cout << "part " << i << " isprimary=" << AliAnalysisMuonUtility::IsPrimary(part,MCEvent()) << " motherindex=" << AliAnalysisMuonUtility::GetMotherIndex(part) << std::endl;
+// //
+// // part->Print();
+//
+// if (AliAnalysisMuonUtility::IsPrimary(part,MCEvent()) &&
+// AliAnalysisMuonUtility::GetMotherIndex(part)==-1)
+// {
+//
+// Histo("INPUT","ALL","Pt")->Fill(part->Pt());
+// Histo("INPUT","ALL","Y")->Fill(part->Y());
+// Histo("INPUT","ALL","Eta")->Fill(part->Eta());
+//
+// if ( part->Y() < -2.5 && part->Y() > -4.0 )
+// {
+// Histo("INPUT","INYRANGE","Pt")->Fill(part->Pt());
+// Histo("INPUT","INYRANGE","Y")->Fill(part->Y());
+// Histo("INPUT","INYRANGE","Eta")->Fill(part->Eta());
+// }
+//
+// nextBin.Reset();
+//
+// while ( ( r = static_cast<AliAnalysisMuMuBinning::Range*>(nextBin()) ) )
+// {
+// Bool_t ok(kFALSE);
+//
+// if ( r->IsIntegrated() )
+// {
+// ok = kTRUE;
+// }
+// else if ( r->Is2D() )
+// {
+// if ( r->AsString().BeginsWith("PTVSY") )
+// {
+// ok = r->IsInRange(part->Y(),part->Pt());
+// }
+// else if ( r->AsString().BeginsWith("YVSPT") )
+// {
+// ok = r->IsInRange(part->Pt(),part->Y());
+// }
+// else
+// {
+// AliError(Form("Don't know how to deal with 2D bin %s",r->AsString().Data()));
+// }
+// }
+// else
+// {
+// if ( r->Quantity() == "PT" )
+// {
+// ok = r->IsInRange(part->Pt());
+// }
+// else if ( r->Quantity() == "Y" )
+// {
+// ok = r->IsInRange(part->Y());
+// }
+// else if ( r->Quantity() == "PHI" )
+// {
+// ok = r->IsInRange(part->Phi());
+// }
+// }
+//
+// if ( ok )
+// {
+// TString hname = GetMinvHistoName(*r,kFALSE);
+//
+// if (!IsHistogramDisabled(hname.Data()))
+// {
+//
+// TH1* h = Histo("INPUT","ALL",hname.Data());
+//
+// if (!h)
+// {
+// AliError(Form("Could not get ALL %s",hname.Data()));
+// continue;
+// }
+//
+// h->Fill(part->M());
+//
+// if ( part->Y() < -2.5 && part->Y() > -4.0 )
+// {
+// h = Histo("INPUT","INYRANGE",hname.Data());
+// if (!h)
+// {
+// AliError(Form("Could not get INYRANGE %s",hname.Data()));
+// continue;
+// }
+// h->Fill(part->M());
+// }
+//
+// }
+//
+// }
+// }
+// }
+// }
+//
+// delete bins;
+//}
+//
+
+//_____________________________________________________________________________
+TString AliAnalysisMuMuMinv::GetMinvHistoName(const AliAnalysisMuMuBinning::Range& r, Bool_t accEffCorrected) const
+{
+ /// Get the invariant mass histogram name
+ return TString::Format("MinvUS%s%s",r.AsString().Data(),
+ accEffCorrected ? "_AccEffCorr" : "");
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuMinv::IsRapidityInRange(const AliVParticle& t1, const AliVParticle& t2, Double_t& ymin, Double_t& ymax) const
+{
+ /// Whether the particle pair has its rapidity within [ymin,ymax[
+
+ TLorentzVector p1(t1.Px(),t1.Py(),t1.Pz(),TMath::Sqrt(AliAnalysisMuonUtility::MuonMass2()+t1.P()*t1.P()));
+ TLorentzVector p2(t2.Px(),t2.Py(),t2.Pz(),TMath::Sqrt(AliAnalysisMuonUtility::MuonMass2()+t2.P()*t2.P()));
+
+ TLorentzVector total(p1+p2);
+
+ Double_t y = total.Rapidity();
+
+ return ( y < ymax && y > ymin );
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuMinv::NameOfIsRapidityInRange(TString& name, Double_t& ymin, Double_t& ymax) const
+{
+ /** Get the name of the rapidity range (making the IsRapidityInRange method useable as an
+ * AliAnalysisMuMuCutElement
+ */
+
+ name.Form("PAIRYIN%2.1f-%2.1f",ymin,ymax);
+}
+
--- /dev/null
+#ifndef ALIANALYSISMUMUMINV_H
+#define ALIANALYSISMUMUMINV_H
+
+/**
+ * \class AliAnalysisMuMuMinv
+ * \brief Invariant mass analysis of muon pairs
+ * \author L. Aphecetche (Subatech)
+ */
+
+#include "AliAnalysisMuMuBase.h"
+#include "AliAnalysisMuMuBinning.h"
+#include "TString.h"
+
+class TH2F;
+class AliVParticle;
+
+class AliAnalysisMuMuMinv : public AliAnalysisMuMuBase
+{
+public:
+
+ AliAnalysisMuMuMinv();
+ virtual ~AliAnalysisMuMuMinv();
+
+ Bool_t IsRapidityInRange(const AliVParticle& t1, const AliVParticle& t2,
+ Double_t& ymin, Double_t& ymax) const;
+
+ virtual void FillHistosForMCEvent(const char* /*eventSelection*/,const char* /*triggerClassName*/,const char* /*centrality*/);
+
+ void NameOfIsRapidityInRange(TString& name, Double_t& ymin, Double_t& ymax) const;
+
+ Bool_t ShouldCorrectDimuonForAccEff() const { return (fAccEffHisto != 0x0); }
+
+ void DefineHistogramCollection(const char* eventSelection, const char* triggerClassName,
+ const char* centrality);
+
+ virtual void FillHistosForPair(const char* eventSelection,const char* triggerClassName,
+ const char* centrality,
+ const char* pairCutName,
+ const AliVParticle& part,
+ const AliVParticle& part2);
+
+private:
+
+ /// not implemented on purpose
+ AliAnalysisMuMuMinv(const AliAnalysisMuMuMinv& rhs);
+ /// not implemented on purpose
+ AliAnalysisMuMuMinv& operator=(const AliAnalysisMuMuMinv& rhs);
+
+ void CreateMinvHistograms(const char* eventSelection, const char* triggerClassName, const char* centrality);
+
+ TString GetMinvHistoName(const AliAnalysisMuMuBinning::Range& r, Bool_t accEffCorrected) const;
+
+
+private:
+ TH2F* fAccEffHisto; // input Acc x Eff (optional)
+
+ ClassDef(AliAnalysisMuMuMinv,1) // implementation of AliAnalysisMuMuBase for muon pairs
+};
+
+#endif
+
--- /dev/null
+#include "AliAnalysisMuMuNch.h"
+
+/**
+ *
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuNch
+ *
+ * SPD tracklet to Nch analysis
+ *
+ * The idea is that this sub-analysis is used first (within the AliAnalysisTaskMuMu sub-framework)
+ * in order to compute the number of charged particles within an event, so that information
+ * can be used in subsequent sub-analysis, like the invariant mass or mean pt ones.
+ *
+ */
+
+#include "AliAODTracklets.h"
+#include "AliAnalysisMuonUtility.h"
+#include "AliLog.h"
+#include "AliAODEvent.h"
+#include "AliESDUtils.h"
+#include "TMath.h"
+#include "AliAnalysisMuMuCutRegistry.h"
+#include "AliAnalysisMuMuCutElement.h"
+#include "Riostream.h"
+#include "TParameter.h"
+#include <set>
+#include <utility>
+#include "AliMergeableCollection.h"
+#include "AliMCEvent.h"
+#include "AliAODMCParticle.h"
+#include "TAxis.h"
+#include "TCanvas.h"
+#include "TH2F.h"
+#include "TF1.h"
+#include "TProfile.h"
+#include "TObjString.h"
+
+
+namespace {
+
+ Double_t SPDgeomR(Double_t* x,Double_t* par) // Eta position of the SPD right edge eta as "seen" from a z vertex position
+ {
+ // par[0] = radius of SPD layer
+
+ Double_t d = x[0];
+ Double_t z(0.);
+ Double_t theta(0.);
+
+ if( d < 14.09999 )
+ {
+ z = 14.1 - d;
+ theta = TMath::ATan(par[0]/z);
+ }
+
+ else if( d > 14.09999 )
+ {
+ z = d - 14.1;
+ theta = TMath::Pi() - TMath::ATan(par[0]/z);
+ }
+
+ return -TMath::Log(TMath::Tan(theta/2.));
+ }
+
+ Double_t SPDgeomL(Double_t* x,Double_t* par) // Eta position of the SPD left edge eta as "seen" from a z vertex position
+ {
+ // par[0] = radius of SPD layer
+
+ Double_t d = x[0];
+ Double_t z(0.);
+ Double_t theta(0.);
+
+ if( d > -14.09999 )
+ {
+ z = 14.1 + d;
+ theta = TMath::Pi() - TMath::ATan(par[0]/z);
+ }
+
+ if( d < -14.09999 )
+ {
+ z = -14.1 - d;
+ theta = TMath::ATan(par[0]/z);
+ }
+
+ return -TMath::Log(TMath::Tan(theta/2.));
+ }
+
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuNch::AliAnalysisMuMuNch(TH2* spdCorrection, Double_t etaMin, Double_t etaMax
+ , Double_t zMin, Double_t zMax,Bool_t disableHistos, Bool_t computeResolution)
+: AliAnalysisMuMuBase(),
+fSPDCorrection(0x0),
+fEtaAxis(new TAxis(TMath::Nint(10./0.1),-5.,5.)),
+fZAxis(new TAxis(TMath::Nint(80/0.25),-40.,40.)),
+fCurrentEvent(0x0),
+fEtaMin(etaMin),
+fEtaMax(etaMax),
+fZMin(zMin),
+fZMax(zMax),
+fResolution(computeResolution)
+{
+ if ( spdCorrection )
+ {
+ fSPDCorrection = static_cast<TH2F*>(spdCorrection->Clone());
+ fSPDCorrection->SetDirectory(0);
+ }
+ DefineSPDAcceptance();
+
+ if ( disableHistos )
+ {
+ DisableHistograms("*");
+ }
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuNch::~AliAnalysisMuMuNch()
+{
+ delete fSPDCorrection;
+ delete fEtaAxis;
+ delete fZAxis;
+ delete fSPD1LR;
+ delete fSPD1LL;
+ delete fSPD2LR;
+ delete fSPD2LL;
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::DefineHistogramCollection(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality)
+{
+ // Define multiplicity histos
+
+ if ( Histo(eventSelection,triggerClassName,centrality,"AliAnalysisMuMuNch") )
+ {
+ return;
+ }
+
+ // dummy histogram to signal that we already defined all our histograms (see above)
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"AliAnalysisMuMuNch","Dummy semaphore",1,0,1);
+
+ Double_t multMin = 0.; //Tracklets multiplicity range
+ Double_t multMax = 500.;
+ Int_t nbinsMult = GetNbins(multMin,multMax,1.);
+
+ Double_t phimin = 0.; //Phi range
+ Double_t phimax = 2*TMath::Pi();
+ Int_t nphibins = GetNbins(phimin,phimax,0.05);
+
+ if ( !fSPDCorrection && fResolution ) // Resolution histos
+ {
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"EtaRes","#eta resolution;#eta_{Reco} - #eta_{MC};Counts",(fEtaAxis->GetNbins())*2,fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"PhiRes","#phi resolution;#phi_{Reco} - #phi_{MC};Counts",nphibins*2,-phimax,phimax);
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"PhiResShifted","#phi resolution;#phi_{Reco} - #phi_{MC};Counts",nphibins*4,-phimax/4,phimax/4);
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"EtaResVsZ","#eta resolution vs MC Zvertex;ZVertex (cm);#eta_{Reco} - #eta_{MC}",(fZAxis->GetNbins())*20,fZAxis->GetXmin(),fZAxis->GetXmax(),(fEtaAxis->GetNbins())*8,fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"PhiResVsZ","#phi resolution vs MC Zvertex;ZVertex (cm);#phi_{Reco} - #phi_{MC}",(fZAxis->GetNbins())*20,fZAxis->GetXmin(),fZAxis->GetXmax(),nphibins*4,-phimax/4,phimax/4);
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"EtaResVsnC","#eta resolution vs Nof contributors to SPD vertex;NofContributors;#eta_{Reco} - #eta_{MC}",200,0,200,(fEtaAxis->GetNbins())*8,fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"PhiResVsnC","#phi resolution vs Nof contributors to SPD vertex;NofContributors;#phi_{Reco} - #phi_{MC}",200,0,200,nphibins*4,-phimax/4,phimax/4);
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"SPDZvResVsnC","SPD Zvertex resolution vs Nof contributors;NofContributors;Zvertex_{Reco} - Zvertex_{MC} (cm)",200,0,200,(fZAxis->GetNbins())*20,fZAxis->GetXmin(),fZAxis->GetXmax());
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"SPDZvResVsMCz","SPD Zvertex resolution vs MC z vertex;MC Zvertex (cm);Zvertex_{Reco} - Zvertex_{MC} (cm)",(fZAxis->GetNbins())*20,fZAxis->GetXmin(),fZAxis->GetXmax(),(fZAxis->GetNbins())*10,fZAxis->GetXmin(),fZAxis->GetXmax());
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"Phi","Reco #phi distribution;#phi;Counts",nphibins,phimin,phimax);
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"MCPhi","MC #phi distribution;#phi;Counts",nphibins,phimin,phimax);
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"Eta","Reco #eta distribution;#phi;Counts",(fEtaAxis->GetNbins())*2,fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"MCEta","MC #eta distribution;#phi;Counts",(fEtaAxis->GetNbins())*2,fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ return; // When computing resolutions we don't want to create the rest of histos
+ }
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"TrackletsVsZVertexVsPhi","Number of tracklets vs Z vertex vs #phi;Z vertex;#phi",fZAxis->GetNbins(),fZAxis->GetXmin(),fZAxis->GetXmax(),nphibins,phimin,phimax);
+ AttachSPDAcceptance(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"TrackletsVsZVertexVsPhi");// Attach the SPD acc curves
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"TrackletsVsZVertexVsEta","Number of tracklets vs ZVertex vs #eta;ZVertex;#eta",fZAxis->GetNbins(),fZAxis->GetXmin(),fZAxis->GetXmax(),fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+ AttachSPDAcceptance(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"TrackletsVsZVertexVsEta");
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"Tracklets","Number of tracklets distribution;N_{Tracklets};N_{events}",nbinsMult,multMin,multMax);
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"NBkgTrackletsVsZVertexVsEta","Number of background tracklets vs ZVertex vs #eta;ZVertex;#eta",fZAxis->GetNbins(),fZAxis->GetXmin(),fZAxis->GetXmax(),fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+ AttachSPDAcceptance(kHistoForMCInput,eventSelection,triggerClassName,centrality,"NBkgTrackletsVsZVertexVsEta");
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"NchVsZVertexVsEta","Number of charged particles vs ZVertex vs #eta;ZVertex;#eta",fZAxis->GetNbins(),fZAxis->GetXmin(),fZAxis->GetXmax(),fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+ AttachSPDAcceptance(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"NchVsZVertexVsEta");
+
+ CreateEventHistos(kHistoForMCInput,eventSelection,triggerClassName,centrality,"NchVsZVertexVsPhi","Number of charged particles vs ZVertex vs #phi;ZVertex;#eta",fZAxis->GetNbins(),fZAxis->GetXmin(),fZAxis->GetXmax(),nphibins,phimin,phimax);
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"EventsVsZVertexVsEta","Effective number of events vs ZVertex vs #eta;ZVertex;#eta",fZAxis->GetNbins(),fZAxis->GetXmin(),fZAxis->GetXmax(),fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax()); // Fill 1 unit in each "touched" eta bin per event (represents the eta bins in which each event contributes)
+ AttachSPDAcceptance(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"EventsVsZVertexVsEta");
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"Nch","Number of charged particles distribution;N_{ch};N_{events}",nbinsMult,multMin,multMax);
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"dNchdEta","<dNchdEta> distribution;dN_{ch}/d#eta;N_{events}",nbinsMult,multMin,multMax);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"TrackletsVsNch","Number of tracklets vs Number of charged particles;N_{ch};N_{tracklets}",nbinsMult,multMin,multMax,nbinsMult,multMin,multMax); //Response matrix
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"V0AMultVsNch","V0A multiplicity vs Number of charged particles;N_{ch};V0A Mult",nbinsMult,multMin,multMax,nbinsMult,multMin,multMax);
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"V0CMultVsNch","V0C multiplicity vs Number of charged particles;N_{ch};V0C Mult",nbinsMult,multMin,multMax,nbinsMult,multMin,multMax);
+
+ // profile histograms
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"MeanTrackletsVsEta","Mean number of tracklets vs #eta;#eta;<N_{Tracklets}>",fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax(),0);
+
+ CreateEventHistos(kHistoForData,eventSelection,triggerClassName,centrality,"MeanTrackletsVsZVertex","Mean number of tracklets vs Z vertex;Z vertex;<N_{Tracklets}>",fZAxis->GetNbins(),fZAxis->GetXmin(),fZAxis->GetXmax(),0);
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"MeanNchVsEta","Mean number of charged particles vs #eta;#eta;<N_{ch}>",fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax(),0); // Each bin has to be divided by the binwidth to became dNch/dEta (Done in the terminate and stored in MeandNchdEta histo)
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,eventSelection,triggerClassName,centrality,"MeanNchVsZVertex","Mean number of charged particles vs Z vertex;Z vertex;<N_{ch}>",fZAxis->GetNbins(),fZAxis->GetXmin(),fZAxis->GetXmax(),0);
+
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::DefineSPDAcceptance()
+{
+ // Defines the functions ( eta = f(z) )of the edges (right/left) of the inner and outer SPD layers
+ // R_in = 3.9 cm ; R_out = 7.6 cm
+ fSPD1LR = new TF1("fSPD1LR",SPDgeomR,-40,40,1);
+ fSPD1LR->SetParameter(0,3.9);
+ fSPD1LL = new TF1("fSPD1LL",SPDgeomL,-40,40,1);
+ fSPD1LL->SetParameter(0,3.9);
+ fSPD2LR = new TF1("fSPD2LR",SPDgeomR,-40,40,1);
+ fSPD2LR->SetParameter(0,7.6);
+ fSPD2LL = new TF1("fSPD2LL",SPDgeomL,-40,40,1);
+ fSPD2LL->SetParameter(0,7.6);
+
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::AddHisto(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* histoname,
+ Double_t z,
+ TH1* h,Bool_t isMC)
+{
+ // Adds the content of a 1D histo to a 2D histo a the z position
+
+ Int_t zbin = fZAxis->FindBin(z);
+ TH2F* h2;
+ if (isMC) h2 = static_cast<TH2F*>(MCHisto(eventSelection,triggerClassName,centrality,histoname));
+ else h2 = static_cast<TH2F*>(Histo(eventSelection,triggerClassName,centrality,histoname));
+
+ for ( Int_t i = 1; i <= h->GetXaxis()->GetNbins(); ++i )
+ {
+ Double_t content = h2->GetCellContent(zbin,i);
+
+ if ( h->GetBinContent(i) > 0 )
+ {
+ h2->SetCellContent(zbin,i,content + h->GetBinContent(i));
+ }
+ }
+
+ h2->SetEntries(h2->GetSumOfWeights());
+}
+
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::AttachSPDAcceptance(UInt_t dataType,
+ const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,const char* histoname)
+{
+ if ( dataType & kHistoForData )
+ {
+ if( !Histo(eventSelection,triggerClassName,centrality,histoname) )
+ {
+ AliError(Form("ERROR: SPD Acceptance curves attach failed. Histo /%s/%s/%s/%s not found",eventSelection,triggerClassName,centrality,histoname));
+ return;
+ }
+
+ Histo(eventSelection,triggerClassName,centrality,histoname)->GetListOfFunctions()->Add(fSPD1LR);
+ Histo(eventSelection,triggerClassName,centrality,histoname)->GetListOfFunctions()->Add(fSPD1LL);
+ Histo(eventSelection,triggerClassName,centrality,histoname)->GetListOfFunctions()->Add(fSPD2LR);
+ Histo(eventSelection,triggerClassName,centrality,histoname)->GetListOfFunctions()->Add(fSPD2LL);
+ }
+ if ( dataType & kHistoForMCInput )
+ {
+ if( !MCHisto(eventSelection,triggerClassName,centrality,histoname) )
+ {
+ AliError(Form("ERROR: SPD Acceptance curves attach failed. MC Histo /%s/%s/%s/%s not found",eventSelection,triggerClassName,centrality,histoname));
+ return;
+ }
+
+ MCHisto(eventSelection,triggerClassName,centrality,histoname)->GetListOfFunctions()->Add(fSPD1LR);
+ MCHisto(eventSelection,triggerClassName,centrality,histoname)->GetListOfFunctions()->Add(fSPD1LL);
+ MCHisto(eventSelection,triggerClassName,centrality,histoname)->GetListOfFunctions()->Add(fSPD2LR);
+ MCHisto(eventSelection,triggerClassName,centrality,histoname)->GetListOfFunctions()->Add(fSPD2LL);
+ }
+
+}
+
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::FillHistosForEvent(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality)
+{
+ // Fills the data (or reco if simu) multiplicity histos
+
+ if ( IsHistogrammingDisabled() ) return;
+
+ if ( fResolution ) return; //When computing resolutions we skip this method
+
+ if ( !AliAnalysisMuonUtility::IsAODEvent(Event()) )
+ {
+ AliError("Don't know how to deal with ESDs...");
+ return;
+ }
+
+ if ( HasMC() && !fSPDCorrection ) // We have MC but no correction (SPD correction computation mode)so we skip the method
+ {
+ return;
+ }
+
+ AliAODEvent* aod = static_cast<AliAODEvent*>(Event());
+
+ AliVVertex* vertex = aod->GetPrimaryVertexSPD();
+
+ TList* nchList = static_cast<TList*>(Event()->FindListObject("NCH"));
+
+ if (!nchList || nchList->IsEmpty() ) // Empty NCH means that there is no SPD vertex ( see SetEvent() ) when runing on data.
+ {
+ return;
+ }
+
+ Double_t SPDZv;
+
+ if ( !vertex || vertex->GetZ() == 0.0 ) // Running in Simu the spdZ == 0 means no SPD info. In data, avoid breaks in events w/o SPD vertex
+ {
+ SPDZv = -40.;
+ }
+
+ else SPDZv = vertex->GetZ();
+
+ TH1* hSPDcorrectionVsEta = static_cast<TH1*>(nchList->FindObject("SPDcorrectionVsEta"));
+ TH1* hNTrackletVsEta = static_cast<TH1*>(nchList->FindObject("NTrackletVsEta"));
+ TH1* hNTrackletVsPhi = static_cast<TH1*>(nchList->FindObject("NTrackletVsPhi"));
+
+ TH1* hNchVsEta =static_cast<TH1*>(hNTrackletVsEta->Clone("NchVsEta"));
+
+ TProfile* hMeanTrackletsVsEta = static_cast<TProfile*>(Histo(eventSelection,triggerClassName,centrality,"MeanTrackletsVsEta"));
+ TProfile* hMeanNchVsEta = static_cast<TProfile*>(Histo(eventSelection,triggerClassName,centrality,"MeanNchVsEta"));
+
+ TH2* hEventsVsZVertexVsEta = static_cast<TH2*>(Histo(eventSelection,triggerClassName,centrality,"EventsVsZVertexVsEta"));
+
+ Int_t nBins(0);
+
+ Double_t nch(0.0);
+ Double_t nTracklets(0.0);
+
+ for (Int_t j = 1 ; j <= fEtaAxis->GetNbins() ; j++) // Loop over eta bins
+ {
+ Double_t correction = hSPDcorrectionVsEta->GetBinContent(j);
+
+ Double_t eta = fEtaAxis->GetBinCenter(j);
+
+ if ( correction < 0 ) continue;
+ else if ( correction == 0.0 ) // No tracklets found in this eta bin.
+ {
+ correction = GetSPDCorrection(SPDZv,eta);
+
+ if ( correction == 0. || correction > 2.5) continue; // We need to know if the eta bin is in a region we want to take into account to count or not the zero
+ }
+
+ Double_t ntr = hNTrackletVsEta->GetBinContent(j); // Tracklets in eta bin
+
+ nch += ntr * correction; // Number of charged particles (corrected tracklets)
+
+ nTracklets += ntr;
+
+ hMeanTrackletsVsEta->Fill(eta,ntr); // Fill the number of tracklets of each eta bin in the profile
+
+ hMeanNchVsEta->Fill(eta,ntr*correction);
+
+ ++nBins; // We sum up the number of bins entering in the computation
+
+ // Fill the number of charged particles of each eta bin in the profile
+ hNchVsEta->SetBinContent( j, hNchVsEta->GetBinContent(j) * correction );
+
+ hEventsVsZVertexVsEta->Fill(SPDZv,eta,1.0); // Fill 1 count each eta bin where the events contributes
+ }
+
+ AddHisto(eventSelection,triggerClassName,centrality,"TrackletsVsZVertexVsPhi",SPDZv,hNTrackletVsPhi);
+ AddHisto(eventSelection,triggerClassName,centrality,"TrackletsVsZVertexVsEta",SPDZv,hNTrackletVsEta);
+
+ AddHisto(eventSelection,triggerClassName,centrality,"NchVsZVertexVsEta",SPDZv,hNchVsEta);
+
+ Histo(eventSelection,triggerClassName,centrality,"Tracklets")->Fill(nTracklets);
+ Histo(eventSelection,triggerClassName,centrality,"MeanTrackletsVsZVertex")->Fill(SPDZv,nTracklets);
+ Histo(eventSelection,triggerClassName,centrality,"MeanNchVsZVertex")->Fill(SPDZv,nch);
+
+ Histo(eventSelection,triggerClassName,centrality,"TrackletsVsNch")->Fill(nTracklets,nch);
+ Histo(eventSelection,triggerClassName,centrality,"Nch")->Fill(nch);
+
+ Double_t V0AMult = 0.;
+ Double_t V0CMult = 0.;
+
+ AliVVZERO* vzero = aod->GetVZEROData();
+ if (vzero)
+ {
+ Double_t multV0A = vzero->GetMTotV0A();
+ V0AMult = AliESDUtils::GetCorrV0A(multV0A,SPDZv);
+ Double_t multV0C = vzero->GetMTotV0C();
+ V0CMult = AliESDUtils::GetCorrV0C(multV0C,SPDZv);
+
+ Histo(eventSelection,triggerClassName,centrality,"V0AMultVsNch")->Fill(V0AMult,nch);
+ Histo(eventSelection,triggerClassName,centrality,"V0CMultVsNch")->Fill(V0CMult,nch);
+
+ }
+
+
+ delete hNchVsEta;
+
+ // Mean dNch/dEta computation
+ Double_t meandNchdEta(0.);
+
+ if ( nBins > 0 )
+ {
+ meandNchdEta = nch / (nBins*fEtaAxis->GetBinWidth(5)); // Divide by nBins to get the mean and by the binWidht to get the d/dEta
+ }
+
+ Histo(eventSelection,triggerClassName,centrality,"dNchdEta")->Fill(meandNchdEta);
+
+
+
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::FillHistosForMCEvent(const char* eventSelection,const char* triggerClassName,const char* centrality)
+{
+ /// Fill input MC multiplicity histos
+
+ if ( IsHistogrammingDisabled() ) return;
+
+ TList* nchList = static_cast<TList*>(Event()->FindListObject("NCH"));
+
+ if (!nchList || nchList->IsEmpty())
+ {
+ return;
+ }
+
+ Double_t MCZv = AliAnalysisMuonUtility::GetMCVertexZ(Event(),MCEvent()); // Definition of MC generated z vertex
+ AliVVertex* vertex = static_cast<AliAODEvent*>(Event())->GetPrimaryVertexSPD();
+
+ Double_t SPDZv(0.);
+
+ //____Resolution Histos___
+ if ( !fSPDCorrection && fResolution )
+ {
+ Int_t nContributors(0);
+ if ( vertex )
+ {
+ nContributors = vertex->GetNContributors();
+ SPDZv = vertex->GetZ();
+ }
+ MCHisto(eventSelection,triggerClassName,centrality,"SPDZvResVsnC")->Fill(nContributors,SPDZv - MCZv);
+ MCHisto(eventSelection,triggerClassName,centrality,"SPDZvResVsMCz")->Fill(MCZv,SPDZv - MCZv);
+
+ Double_t EtaReco(0.),EtaMC(0.),PhiReco(0.),PhiMC(0.);
+ Int_t i(-1),labelEtaReco(-1),labelEtaMC(-1),labelPhiReco(-1),labelPhiMC(-1);
+
+ while ( i < nchList->GetEntries() - 1 )
+ {
+ i++;
+ while ( nchList->At(i)->IsA() != TObjString::Class() ) // In case there is a diferent object, just to skip it
+ {
+ i++;
+ }
+
+ TParameter<Double_t>* p = static_cast<TParameter<Double_t>*>(nchList->At(i));
+
+
+ //Eta Resolution
+ if ( TString(p->GetName()).Contains("EtaReco") ) // We take the reco eta
+ {
+ sscanf(p->GetName(),"EtaReco%d",&labelEtaReco);
+ EtaReco = p->GetVal();
+ MCHisto(eventSelection,triggerClassName,centrality,"Eta")->Fill(EtaReco);
+ }
+ else if ( TString(p->GetName()).Contains("EtaMC") ) // We take the generated eta
+ {
+ sscanf(p->GetName(),"EtaMC%d",&labelEtaMC);
+ EtaMC = p->GetVal();
+ MCHisto(eventSelection,triggerClassName,centrality,"MCEta")->Fill(EtaMC);
+ }
+ if ( labelEtaReco > 0 && labelEtaReco == labelEtaMC ) // To be sure we compute the difference for the same particle
+ {
+ labelEtaReco = -1; // Restart of the label value to avoid double count the eta difference when computing the phi one
+ Double_t EtaDif = EtaReco - EtaMC;
+ MCHisto(eventSelection,triggerClassName,centrality,"EtaRes")->Fill(EtaDif);
+ MCHisto(eventSelection,triggerClassName,centrality,"EtaResVsZ")->Fill(MCZv,EtaDif);
+ MCHisto(eventSelection,triggerClassName,centrality,"EtaResVsnC")->Fill(nContributors,EtaDif);
+ }
+
+ //Phi Resolution
+ else if ( TString(p->GetName()).Contains("PhiReco") ) // We take the reco phi
+ {
+ sscanf(p->GetName(),"PhiReco%d",&labelPhiReco);
+ PhiReco = p->GetVal();
+ MCHisto(eventSelection,triggerClassName,centrality,"Phi")->Fill(PhiReco);
+ }
+ else if ( TString(p->GetName()).Contains("PhiMC") ) // We take the generated phi
+ {
+ sscanf(p->GetName(),"PhiMC%d",&labelPhiMC);
+ PhiMC = p->GetVal();
+ MCHisto(eventSelection,triggerClassName,centrality,"MCPhi")->Fill(PhiMC);
+ }
+
+ if ( labelPhiReco > 0 && labelPhiReco == labelPhiMC ) // To be sure we compute the difference for the same particle
+ {
+ labelPhiReco = -1; // Restart of the label value to avoid double count the phi difference when computing the eta one
+ Double_t PhiDif = PhiReco - PhiMC;
+ MCHisto(eventSelection,triggerClassName,centrality,"PhiRes")->Fill(PhiDif);
+
+ //___With the following algorithm we refer the differences to the interval [-Pi/2,Pi/2]
+ if ( PhiDif < -TMath::PiOver2() && PhiDif > -TMath::Pi() )
+ {
+ PhiDif = -TMath::Pi() - PhiDif;
+ }
+ else if ( PhiDif < -TMath::Pi() )
+ {
+ PhiDif = -2.*TMath::Pi() - PhiDif;
+ if ( PhiDif < -TMath::PiOver2() )
+ {
+ PhiDif = -TMath::Pi() - PhiDif;
+ }
+ }
+
+ else if ( PhiDif > TMath::PiOver2() && PhiDif < TMath::Pi() )
+ {
+ PhiDif = TMath::Pi() - PhiDif;
+ }
+ else if ( PhiDif > TMath::Pi() )
+ {
+ PhiDif = 2.*TMath::Pi() - PhiDif;
+ if ( PhiDif > TMath::PiOver2() )
+ {
+ PhiDif = TMath::Pi() - PhiDif;
+ }
+ }
+ //___
+
+ MCHisto(eventSelection,triggerClassName,centrality,"PhiResVsZ")->Fill(MCZv,PhiDif);
+ MCHisto(eventSelection,triggerClassName,centrality,"PhiResShifted")->Fill(PhiDif);
+ MCHisto(eventSelection,triggerClassName,centrality,"PhiResVsnC")->Fill(nContributors,PhiDif);
+ }
+ }
+
+ return; // When computing resolutions we skip the rest of the method
+ }
+ //_____
+
+
+ //___Multiplicity histos (just when not computing resolutions)___
+ TH1* hSPDcorrectionVsEta = static_cast<TH1*>(nchList->FindObject("MCSPDcorrectionVsEta"));
+ TH1* hNBkgTrackletsVSEta = static_cast<TH1*>(nchList->FindObject("NBkgTrackletsVSEta"));
+ TH1* hNchVsPhi = static_cast<TH1*>(nchList->FindObject("MCNchVsPhi"));
+ TH1* hNchVsEta = static_cast<TH1*>(nchList->FindObject("MCNchVsEta"));
+ TH1* hNTrackletVsEta = static_cast<TH1*>(nchList->FindObject("MCNTrackletVsEta"));
+ TH1* hNTrackletVsPhi = static_cast<TH1*>(nchList->FindObject("MCNTrackletVsPhi"));
+
+ TProfile* hMeanNchVsEta = static_cast<TProfile*>(MCHisto(eventSelection,triggerClassName,centrality,"MeanNchVsEta"));
+
+ TH2* hEventsVsZVertexVsEta = static_cast<TH2*>(MCHisto(eventSelection,triggerClassName,centrality,"EventsVsZVertexVsEta"));
+
+ Int_t nBins(0);
+
+ Double_t nchSum(0.),nTracklets(0.);
+ for (Int_t j = 1 ; j <= fEtaAxis->GetNbins() ; j++) //Loop over eta bins
+ {
+ Double_t correction = hSPDcorrectionVsEta->GetBinContent(j);
+
+ if ( correction < 0 ) continue; // We count just the particles in the SPD acceptance.
+
+ nTracklets += hNTrackletVsEta->GetBinContent(j); // Reco tracklets
+
+ ++nBins; // We sum up the number of bins entering in the computation
+
+ Double_t eta = fEtaAxis->GetBinCenter(j);
+ Double_t nch = hNchVsEta->GetBinContent(j); // Generated particles
+
+ nchSum += nch;
+
+ hMeanNchVsEta->Fill(eta,nch); // Fill the number of charged particles of each eta bin in the profile
+
+ hEventsVsZVertexVsEta->Fill(MCZv,eta,1.0); // Fill 1 count each eta bin where the events contributes
+ }
+
+ MCHisto(eventSelection,triggerClassName,centrality,"Tracklets")->Fill(nTracklets);
+
+ if ( vertex )
+ {
+ SPDZv = vertex->GetZ();
+ }
+
+ Bool_t isMChisto = kTRUE; // Used to get the MC histos in the Add method
+
+ AddHisto(eventSelection,triggerClassName,centrality,"NBkgTrackletsVsZVertexVsEta",SPDZv,hNBkgTrackletsVSEta,isMChisto);
+ AddHisto(eventSelection,triggerClassName,centrality,"NchVsZVertexVsPhi",MCZv,hNchVsPhi,isMChisto);
+ AddHisto(eventSelection,triggerClassName,centrality,"NchVsZVertexVsEta",MCZv,hNchVsEta,isMChisto);
+ AddHisto(eventSelection,triggerClassName,centrality,"TrackletsVsZVertexVsEta",SPDZv,hNTrackletVsEta,isMChisto);
+ AddHisto(eventSelection,triggerClassName,centrality,"TrackletsVsZVertexVsPhi",SPDZv,hNTrackletVsPhi,isMChisto);
+
+ MCHisto(eventSelection,triggerClassName,centrality,"MeanNchVsZVertex")->Fill(MCZv,nchSum);
+ MCHisto(eventSelection,triggerClassName,centrality,"Nch")->Fill(nchSum);
+
+
+ // Mean dNch/dEta computation
+ Double_t meandNchdEta(0.);
+
+ if ( nBins > 0 )
+ {
+ meandNchdEta = nchSum / (nBins*fEtaAxis->GetBinWidth(5)); // Divide by nBins to get the mean and by the binWidht to get the d/dEta
+ }
+
+ MCHisto(eventSelection,triggerClassName,centrality,"dNchdEta")->Fill(meandNchdEta);
+
+ Double_t V0AMult = 0.;
+ Double_t V0CMult = 0.;
+
+ AliVVZERO* vzero = Event()->GetVZEROData();
+ if (vzero)
+ {
+ Double_t multV0A = vzero->GetMTotV0A();
+ V0AMult = AliESDUtils::GetCorrV0A(multV0A,MCZv);
+ Double_t multV0C = vzero->GetMTotV0C();
+ V0CMult = AliESDUtils::GetCorrV0C(multV0C,MCZv);
+
+ MCHisto(eventSelection,triggerClassName,centrality,"V0AMultVsNch")->Fill(V0AMult,nchSum);
+ MCHisto(eventSelection,triggerClassName,centrality,"V0CMultVsNch")->Fill(V0CMult,nchSum);
+
+ }
+ //____
+}
+
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::GetEtaRangeSPD(Double_t spdZVertex, Double_t etaRange[])
+{
+ // Returns the SPD eta range for a given z vertex.
+
+ Double_t etaMax(fEtaMax),etaMin(fEtaMin);
+
+ Double_t vf1LR = fSPD1LR->Eval(spdZVertex); //Eta values for the z vertex over the SPD acceptance curves
+ Double_t vf2LR = fSPD2LR->Eval(spdZVertex);
+ Double_t vf1LL = fSPD1LL->Eval(spdZVertex);
+ Double_t vf2LL = fSPD2LL->Eval(spdZVertex);
+
+ //____We start by asigning the eta range as the eta values in the SPD acceptance curve
+ if ( spdZVertex < 0. )
+ {
+ etaMax = vf2LR;
+ etaMin = TMath::Max(vf1LL,vf2LL);
+ }
+ else
+ {
+ etaMax = TMath::Min(vf1LR,vf2LR);
+ etaMin = vf2LL;
+ }
+ //____
+
+
+ //____Algorithm to avoid taking bins which are crossed by the SPD acceptance curves
+ Int_t binYMin = fEtaAxis->FindBin(etaMin); // Find the corresponding bins for eta max & min and z vertex
+ Int_t binYMax = fEtaAxis->FindBin(etaMax);
+ Int_t binX = fZAxis->FindBin(spdZVertex);
+
+ // Define the values for the relevant edges of the eta and z bins
+ Double_t upEdge = fEtaAxis->GetBinUpEdge(binYMax); // up edge of the top eta bin
+ Double_t lowEdge = fEtaAxis->GetBinLowEdge(binYMin); // low edge of the bottom eta bin
+ Double_t leftEdge = fZAxis->GetBinLowEdge(binX); // left edge of the z bin
+ Double_t rightEdge = fZAxis->GetBinUpEdge(binX); // right edge of the z bin
+
+ Double_t etaMaxTemp(0.),etaMinTemp(0.);
+ if ( spdZVertex < 0. )
+ {
+ etaMaxTemp = fSPD2LR->Eval(rightEdge); // Define the temporary eta max as the value of the curve int the righ edge of the bin
+ etaMinTemp = TMath::Max(fSPD1LL->Eval(leftEdge),fSPD2LL->Eval(leftEdge));
+ }
+ else
+ {
+ etaMaxTemp = TMath::Min(fSPD1LR->Eval(rightEdge),fSPD2LR->Eval(rightEdge));
+ etaMinTemp = fSPD2LL->Eval(leftEdge);
+ }
+
+ while ( upEdge > etaMaxTemp ) //We take eta max as the up edge of the 1st bin which is inside the SPD acceptance but not crossed by the curve
+ {
+ binYMax = binYMax - 1; // Since the up edge of the current bin is bigger than the SPD acc curve we move 1 bin below
+ upEdge = fEtaAxis->GetBinUpEdge(binYMax); // Take the up edge of the new bin
+ etaMax = upEdge - 1E-6; // We substract 1E-6 cause the up edge of the a bin belongs to the bin+1
+
+ }
+
+ //We take eta min as the low edge of the 1st bin which is inside the SPD acceptance but not crossed by the curve
+ while ( lowEdge < etaMinTemp )
+ {
+ binYMin = binYMin + 1; // Since the low edge of the current bin is smaller than the SPD acc curve we move 1 bin above
+ lowEdge = fEtaAxis->GetBinLowEdge(binYMin); // Take the low edge of the new bin
+ etaMin = lowEdge + 1E-6;
+ }
+ //____
+
+ // In case the eta range we want (given in the constructor) is smaller than the one found by the algorithm (max range) we redefine the values
+ if ( etaMin < fEtaMin ) etaMin = fEtaMin + 1E-6;
+ if ( etaMax > fEtaMax ) etaMax = fEtaMax - 1E-6;
+
+ etaRange[0] = etaMin;
+ etaRange[1] = etaMax;
+}
+
+//_____________________________________________________________________________
+Double_t AliAnalysisMuMuNch::GetSPDCorrection(Double_t zvert, Double_t eta) const
+{
+ if (!fSPDCorrection)
+ {
+ AliFatal("ERROR: No SPD Correction");
+ return 0;
+ }
+ Int_t bin = fSPDCorrection->FindBin(zvert,eta);
+ return fSPDCorrection->GetBinContent(bin);
+}
+
+
+//==============================These methods are useless here, anyway they should go in the EventCutterClass=================
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuNch::HasAtLeastNTrackletsInEtaRange(const AliVEvent& event, Int_t n, Double_t& etaMin, Double_t& etaMax) const
+{
+ if ( event.IsA() != AliAODEvent::Class() )
+ {
+ return kFALSE;
+ }
+
+ AliAODTracklets* tracklets = static_cast<const AliAODEvent&>(event).GetTracklets();
+
+ if (!tracklets)
+ {
+ return kFALSE;
+ }
+
+ Int_t nTrackletsInRange(0);
+
+ Int_t nTracklets = tracklets->GetNumberOfTracklets();
+
+ for (Int_t i = 0 ; i < nTracklets && nTrackletsInRange < n; i++)
+ {
+ Double_t eta = -TMath::Log(TMath::Tan(tracklets->GetTheta(i)/2.0));
+
+ if ( eta > etaMin && eta < etaMax )
+ {
+ ++nTrackletsInRange;
+ }
+ }
+
+ return (nTrackletsInRange>=n);
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::NameOfHasAtLeastNTrackletsInEtaRange(TString& name, Int_t n, Double_t& etaMin, Double_t& etaMax) const
+{
+ if ( TMath::AreEqualAbs(TMath::Abs(etaMin),TMath::Abs(etaMax),1E-9 ) )
+ {
+ name.Form("ATLEAST%dTRKLINABSETALT%3.1f",n,TMath::Abs(etaMin));
+ }
+ else
+ {
+ name.Form("ATLEAST%dTRKLINETA%3.1f-%3.1f",n,etaMin,etaMax);
+ }
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::SetEvent(AliVEvent* event, AliMCEvent* mcEvent)
+{
+ /// Set the event, compute multiplicities and add them to the event
+
+ if ( event->IsA() != AliAODEvent::Class() )
+ {
+ AliError("Only working for AODs for the moment.");
+ return;
+ }
+
+ AliAnalysisMuMuBase::SetEvent(event,mcEvent); // To have Event() and MCEvent() method working
+
+ TList* nchList = static_cast<TList*>(event->FindListObject("NCH")); // Define the list with the NCH info for each event
+ if (!nchList)
+ {
+ nchList = new TList;
+ nchList->SetOwner(kTRUE);
+ nchList->SetName("NCH");
+ event->AddObject(nchList);
+ }
+
+ const AliAODVertex* vertexSPD = static_cast<const AliAODEvent*>(Event())->GetPrimaryVertexSPD(); // SPD vertex object
+ AliAODTracklets* tracklets = static_cast<const AliAODEvent*>(Event())->GetTracklets(); // Tracklets object
+
+ TH1* hSPDcorrectionVsEta(0x0); // Pointers for the individual event histos
+ TH1* hNchVsEta(0x0);
+ TH1* hNTrackletVsEta(0x0);
+ TH1* hNTrackletVsPhi(0x0);
+
+ //_______Create once the histos with the individual event "properties" (cleared at the beginning of each new event)_______
+ if ( !fResolution ) // When computing resolutions we dont do anything else
+ {
+ if ( !Histo("AliAnalysisMuMuNch","SPDcorrectionVsEta") )
+ {
+ CreateEventHistos(kHistoForData | kHistoForMCInput,"AliAnalysisMuMuNch","SPDcorrectionVsEta","SPD correction-like vs #eta;#eta",fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ CreateEventHistos(kHistoForMCInput,"AliAnalysisMuMuNch","NchVsEta","Nch vs #eta;#eta",fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,"AliAnalysisMuMuNch","NTrackletVsEta","Ntracklet vs #eta;#eta",fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ CreateEventHistos(kHistoForData,"AliAnalysisMuMuNch","NBkgTrackletsVSEta","NBkg Tracklets vs #eta;#eta",fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ Double_t phimin = 0.; //Phi range
+ Double_t phimax = 2*TMath::Pi();
+ Int_t nphibins = GetNbins(phimin,phimax,0.05);
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,"AliAnalysisMuMuNch","NTrackletVsPhi","Ntracklet vs #phi;#phi",nphibins,phimin,phimax);
+
+ CreateEventHistos(kHistoForMCInput,"AliAnalysisMuMuNch","NchVsPhi","Nch vs #phi;#phi",nphibins,phimin,phimax);
+
+ CreateEventHistos(kHistoForData | kHistoForMCInput,"AliAnalysisMuMuNch","test","test",fZAxis->GetNbins(),fZAxis->GetXmin(),fZAxis->GetXmax(),fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ Histo("AliAnalysisMuMuNch","test")->GetListOfFunctions()->Add(fSPD1LR);
+ Histo("AliAnalysisMuMuNch","test")->GetListOfFunctions()->Add(fSPD1LL);
+ Histo("AliAnalysisMuMuNch","test")->GetListOfFunctions()->Add(fSPD2LR);
+ Histo("AliAnalysisMuMuNch","test")->GetListOfFunctions()->Add(fSPD2LL);
+ }
+ //_________
+
+
+ hSPDcorrectionVsEta = Histo("AliAnalysisMuMuNch","SPDcorrectionVsEta"); // Set the individual event histos
+ hNTrackletVsEta = Histo("AliAnalysisMuMuNch","NTrackletVsEta");
+ hNTrackletVsPhi = Histo("AliAnalysisMuMuNch","NTrackletVsPhi");
+
+
+ hSPDcorrectionVsEta->Reset(); // Reset of the individual event histos
+ hNTrackletVsEta->Reset();
+ hNTrackletVsPhi->Reset();
+ }
+
+ Double_t etaRange[2]; // Variables we will use in the multiplicity computation
+ Int_t binMin,binMax;
+ Int_t nTracklets(0);
+ Double_t thetaTracklet(0.),phiTracklet(0.),etaTracklet(0.);
+ Double_t nch(0.0);
+ Int_t nBins(0);
+
+
+ //____Data (or Reco if simu) multiplicity computation___
+ if ( fSPDCorrection && !fResolution ) // When computing resolutions we dont do anything else
+ {
+ if ( tracklets && vertexSPD )
+ {
+ Double_t SPDZv = vertexSPD->GetZ();
+
+ GetEtaRangeSPD(SPDZv,etaRange);
+
+ Histo("AliAnalysisMuMuNch","test")->Fill(SPDZv,etaRange[1]);
+ Histo("AliAnalysisMuMuNch","test")->Fill(SPDZv,etaRange[0]);
+
+ nTracklets = tracklets->GetNumberOfTracklets();
+
+ Double_t SPDr;
+ for (Int_t i = 0 ; i < nTracklets ; i++)
+ {
+ thetaTracklet = tracklets->GetTheta(i);
+ etaTracklet = -TMath::Log(TMath::Tan(thetaTracklet/2.));
+ if ( etaTracklet < etaRange[0] || etaTracklet > etaRange[1] ) continue; // Avoid tracklets out of the eta SPD acceptance or out of the eta cut
+
+ SPDr = GetSPDCorrection(SPDZv,etaTracklet);
+
+ Int_t bin = fEtaAxis->FindBin(etaTracklet);
+
+ if ( SPDr!=0. && SPDr <= 2.5) // Threshold to reduce border effects
+ {
+ hSPDcorrectionVsEta->SetBinContent(bin,SPDr);
+ hNTrackletVsEta->Fill(etaTracklet);
+ hNTrackletVsPhi->Fill(tracklets->GetPhi(i));
+ }
+ else // If the correction is above the threshold we store a -1 in the correction to skip this eta bin int the fill method
+ {
+ hSPDcorrectionVsEta->SetBinContent(bin,-1.0);
+ }
+ }
+
+ //___ Fill the out-of-eta-range bins with -1.0
+
+ binMin = fEtaAxis->FindBin(etaRange[0]);
+ binMax = fEtaAxis->FindBin(etaRange[1]);
+
+ for ( Int_t i = 1; i < binMin; ++i )
+ {
+ hSPDcorrectionVsEta->SetBinContent(i,-1.0);
+ }
+ for ( Int_t i = binMax + 1 ; i <= fEtaAxis->GetNbins(); ++i )
+ {
+ hSPDcorrectionVsEta->SetBinContent(i,-1.0);
+ }
+ //____
+ nchList->Clear(); // We clear the NCH list for this new event
+
+ if ( !IsHistogrammingDisabled() )
+ {
+ nchList->Add(hSPDcorrectionVsEta->Clone());
+ nchList->Add(hNTrackletVsEta->Clone());
+ nchList->Add(hNTrackletVsPhi->Clone());
+ }
+
+ //----- Mean dNchdEta computation to set it into the event
+ for (Int_t j = 1 ; j <= fEtaAxis->GetNbins() ; j++) // Loop over eta bins
+ {
+ Double_t correction = hSPDcorrectionVsEta->GetBinContent(j);
+
+ Double_t eta = fEtaAxis->GetBinCenter(j);
+
+ if ( correction < 0 ) continue; // If the correction is < 0 we skip that eta bin
+ else if ( correction == 0.0 ) // If the correction is 0 we have no tracklets in that eta bin
+ {
+ Double_t spdCorrection = GetSPDCorrection(SPDZv,eta);
+ if ( spdCorrection == 0. || spdCorrection > 2.5) continue; // If the correction in the eta bin is not within the threshold we do not count the "0"(that eta bin will not count for nBins)
+ }
+
+ nch += hNTrackletVsEta->GetBinContent(j) * correction; // Number of charged particles (tracklets*SPDcorrection)
+
+ ++nBins; // We sum up the number of bins entering in the computation
+ }
+
+ Double_t meandNchdEta(0.); // We compute the mean dNch/dEta in the event
+ if ( nBins > 0 )
+ {
+ meandNchdEta = nch / (nBins*fEtaAxis->GetBinWidth(5));
+ }
+
+ nchList->Add(new TParameter<Double_t>("MeandNchdEta",meandNchdEta)); // We add the mean dNch/dEta to the event. It will serve us as a multiplicity estimator.
+ //------
+
+ }
+
+ else nchList->Clear(); //To clear the NCH list for MC in case the event has no reconstructed SPD vertex
+ }
+ //_______
+
+ else nchList->Clear(); // To clear the NCH list for MC in case we have MC and no correction (SPD correction computation mode)
+
+
+ //____Input MC multiplicity computation ___
+ if ( HasMC() )
+ {
+ if ( !fResolution ) //When computing resolutions we dont do anything else
+ {
+ Double_t MCZv = AliAnalysisMuonUtility::GetMCVertexZ(Event(),MCEvent());
+ GetEtaRangeSPD(MCZv,etaRange);
+
+ hNchVsEta = MCHisto("AliAnalysisMuMuNch","NchVsEta");
+ hSPDcorrectionVsEta = MCHisto("AliAnalysisMuMuNch","SPDcorrectionVsEta");
+ TH1* hNchVsPhi = MCHisto("AliAnalysisMuMuNch","NchVsPhi");
+ hNTrackletVsEta = MCHisto("AliAnalysisMuMuNch","NTrackletVsEta");
+ hNTrackletVsPhi = MCHisto("AliAnalysisMuMuNch","NTrackletVsPhi");
+
+ hNTrackletVsEta->Reset();
+ hNchVsEta->Reset();
+ hNchVsPhi->Reset();
+ hSPDcorrectionVsEta->Reset();
+ hNTrackletVsPhi->Reset();
+
+ //___ Fill the out-of-eta-range bins with -1.0
+ binMin = fEtaAxis->FindBin(etaRange[0]);
+ binMax = fEtaAxis->FindBin(etaRange[1]);
+
+ for ( Int_t i = 1; i < binMin; ++i )
+ {
+ hSPDcorrectionVsEta->SetBinContent(i,-1.0);
+ }
+ for ( Int_t i = binMax + 1 ; i <= fEtaAxis->GetNbins(); ++i )
+ {
+ hSPDcorrectionVsEta->SetBinContent(i,-1.0);
+ }
+ for ( Int_t i = binMin; i <= binMax; ++i ) // Fill the bins inside the eta range with +1
+ {
+ hSPDcorrectionVsEta->SetBinContent(i,1.0);
+ }
+ //___
+
+ Int_t nMCTracks = MCEvent()->GetNumberOfTracks(); // MC number of MC tracks
+
+ for ( Int_t i = 0; i < nMCTracks ; ++i ) //Loop over generated tracks
+ {
+ AliAODMCParticle* AODpart = static_cast<AliAODMCParticle*>(mcEvent->GetTrack(i));
+
+ if ( AODpart->IsPhysicalPrimary() ) // We take only particles produced in the collision (Particles produced in the collision including products of strong and electromagnetic decay and excluding feed-down from weak decays of strange particles)
+ {
+ if ( AODpart->Charge()!=0 ) // We take only charged particles
+ {
+ hNchVsEta->Fill(AODpart->Eta());
+ hNchVsPhi->Fill(AODpart->Phi());
+
+ }
+ }
+ }
+
+ nchList->Add(hNchVsEta->Clone("MCNchVsEta"));
+ nchList->Add(hNchVsPhi->Clone("MCNchVsPhi"));
+ nchList->Add(hSPDcorrectionVsEta->Clone("MCSPDcorrectionVsEta"));
+ }
+ //__Bkg tracklets and Resolution estimation __
+ if ( tracklets ) // We can compute the Bkg tracklets and resolution only if we have the tracklets object in the event
+ {
+ TH1* hNBkgTrackletsVSEta(0x0); // Pointer for the Bkg histo
+ if ( !fResolution )
+ {
+ hNBkgTrackletsVSEta = Histo("AliAnalysisMuMuNch","NBkgTrackletsVSEta");
+
+ hNBkgTrackletsVSEta->Reset();
+ }
+
+ nTracklets = tracklets->GetNumberOfTracklets();
+
+ for (Int_t i = 0 ; i < nTracklets ; i++) // Loop over tracklets to check if they come or not from the same MC particle
+ {
+ thetaTracklet = tracklets->GetTheta(i);
+ etaTracklet = -TMath::Log(TMath::Tan(thetaTracklet/2.));
+ phiTracklet = tracklets->GetPhi(i);
+
+
+ if ( !fResolution )
+ {
+ hNTrackletVsEta->Fill(etaTracklet);
+ hNTrackletVsPhi->Fill(phiTracklet);
+ }
+
+ Int_t label1 = tracklets->GetLabel(i,0);
+ Int_t label2 = tracklets->GetLabel(i,1);
+
+ if (label1 != label2 ) // Tracklets not comming from the same MC particle are Bkg
+ {
+ if (!fResolution ) hNBkgTrackletsVSEta->Fill(etaTracklet);
+ }
+ else if ( !fSPDCorrection && fResolution ) // Compute the resolutions with the tracklets comming from the same MC particle
+ {
+ AliAODMCParticle* AODpartMC = static_cast<AliAODMCParticle*>(MCEvent()->GetTrack(label1));
+ Double_t etaTrackletMC = AODpartMC->Eta();
+ Double_t phiTrackletMC = AODpartMC->Phi();
+
+ // Resolution variables
+ nchList->Add(new TParameter<Double_t>(Form("EtaReco%d",label1),etaTracklet));
+ nchList->Add(new TParameter<Double_t>(Form("EtaMC%d",label1),etaTrackletMC));
+
+ nchList->Add(new TParameter<Double_t>(Form("PhiReco%d",label1),phiTracklet));
+ nchList->Add(new TParameter<Double_t>(Form("PhiMC%d",label1),phiTrackletMC));
+
+ }
+ }
+
+ if (!fResolution )
+ {
+ nchList->Add(hNTrackletVsEta->Clone("MCNTrackletVsEta"));
+ nchList->Add(hNTrackletVsPhi->Clone("MCNTrackletVsPhi"));
+ nchList->Add(hNBkgTrackletsVSEta->Clone());
+ }
+
+ }
+
+ }
+ //_______
+
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuNch::Terminate(Option_t *)
+{
+ /// Called once at the end of the query
+ if ( !HistogramCollection() ) return;
+
+ if ( HistogramCollection()->FindObject("/MCINPUT/AliAnalysisMuMuNch/NTrackletVsEta") )
+ {
+ HistogramCollection()->Remove("/MCINPUT/AliAnalysisMuMuNch/NTrackletVsEta");
+ HistogramCollection()->Remove("/MCINPUT/AliAnalysisMuMuNch/NTrackletVsPhi");
+ HistogramCollection()->Remove("/MCINPUT/AliAnalysisMuMuNch/NchVsEta");
+ HistogramCollection()->Remove("/MCINPUT/AliAnalysisMuMuNch/NchVsPhi");
+ HistogramCollection()->Remove("/MCINPUT/AliAnalysisMuMuNch/SPDcorrectionVsEta");
+ HistogramCollection()->Remove("/AliAnalysisMuMuNch/NBkgTrackletsVSEta");
+ }
+
+ if ( HistogramCollection()->FindObject("/AliAnalysisMuMuNch/NTrackletVsEta") )
+ {
+ HistogramCollection()->Remove("/AliAnalysisMuMuNch/NTrackletVsEta");
+ HistogramCollection()->Remove("/AliAnalysisMuMuNch/test");
+ HistogramCollection()->Remove("/AliAnalysisMuMuNch/NTrackletVsPhi");
+ HistogramCollection()->Remove("/AliAnalysisMuMuNch/SPDcorrectionVsEta");
+ }
+ //____ Compute dNchdEta histo
+ TObjArray* idArr = HistogramCollection()->SortAllIdentifiers();
+
+ TIter next(idArr);
+ TObjString* id;
+
+ while ( (id = static_cast<TObjString*>(next())) )
+ {
+ TProfile* p = static_cast<TProfile*>(HistogramCollection()->FindObject(Form("%s%s",id->GetName(),"MeanNchVsEta")));
+
+ if ( !p ) continue;
+
+ TH1* h = new TH1F("MeandNchdEta","Event averaged dN_{ch}/d#eta ;#eta;<dN_{ch}/d#eta>",fEtaAxis->GetNbins(),fEtaAxis->GetXmin(),fEtaAxis->GetXmax());
+
+ if ( p->GetNbinsX() != h->GetNbinsX() || p->GetXaxis()->GetXmin() != h->GetXaxis()->GetXmin() || p->GetXaxis()->GetXmax() != h->GetXaxis()->GetXmax() )
+ {
+ AliError("ERROR: Cannot compute MeandNchdEta since the binning doesn't match with MeanNchVsEta histo");
+ continue;
+ }
+
+ for ( Int_t i = 1 ; i < h->GetNbinsX() ; i++ )
+ {
+ h->SetBinContent(i,p->GetBinContent(i)/p->GetBinWidth(i));
+ h->SetBinError(i,p->GetBinError(i)/p->GetBinWidth(i));
+ h->SetEntries(p->GetEntries());
+ }
+
+ HistogramCollection()->Adopt(Form("%s",id->GetName()),h);
+ }
+
+ delete idArr;
+ //___
+}
--- /dev/null
+#ifndef ALIANALYSISMUMUNCH_H
+#define ALIANALYSISMUMUNCH_H
+
+/**
+ *
+ * \class AliAnalysisMuMuNch
+ * \brief Charged particle multiplicity analysis (for plotting muon variables against it)
+ * \author L. Aphecetche and J. Martin-Bianco (Subatech)
+ */
+
+#include "AliAnalysisMuMuBase.h"
+
+class TH2F;
+class TH2;
+class AliVEvent;
+class TAxis;
+class TF1;
+class AliAODVertex;
+
+class AliAnalysisMuMuNch : public AliAnalysisMuMuBase
+{
+public:
+
+ AliAnalysisMuMuNch(TH2* spdCorrection=0x0, Double_t etaMin=-0.5, Double_t etaMax=0.5
+ , Double_t zmin=-40, Double_t zmax=40,Bool_t disableHistos=kFALSE,
+ Bool_t computeResolution=kFALSE);
+ virtual ~AliAnalysisMuMuNch();
+
+ Bool_t HasAtLeastNTrackletsInEtaRange(const AliVEvent& event, Int_t n,
+ Double_t& etaMin, Double_t& etaMax) const;
+
+ void NameOfHasAtLeastNTrackletsInEtaRange(TString& name, Int_t n,
+ Double_t& etaMin, Double_t& etaMax) const;
+
+ virtual void SetEvent(AliVEvent* event, AliMCEvent* mcEvent=0x0);
+
+ virtual void Terminate(Option_t* /*opt*/="");
+
+protected:
+
+ void AddHisto(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* histoname,
+ Double_t z,
+ TH1* h,
+ Bool_t isMC=kFALSE);
+
+ void AttachSPDAcceptance(UInt_t dataType,
+ const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,const char* histoname);
+
+
+ void FillHistosForMCEvent(const char* eventSelection, const char* triggerClassName,
+ const char* centrality);
+
+
+ void FillHistosForEvent(const char* eventSelection, const char* triggerClassName,
+ const char* centrality);
+
+ virtual void DefineHistogramCollection(const char* eventSelection, const char* triggerClassName,
+ const char* centrality);
+
+ void DefineSPDAcceptance();
+
+ void GetEtaRangeSPD(Double_t spdZVertex, Double_t etaRange[]);
+
+ Double_t GetSPDCorrection(Double_t zvert, Double_t eta) const;
+
+private:
+ TH2F* fSPDCorrection; // Nch/Tracklets_SPD (eta vs z)
+ TAxis* fEtaAxis; // Eta axis used for the histos
+ TAxis* fZAxis; // Z vertex axis used for the histos
+ AliVEvent* fCurrentEvent; //! cache of the current event
+ Double_t fEtaMin; // Minimum tracklet eta value
+ Double_t fEtaMax; // Maximum tracklet eta value
+ Double_t fZMin; // Minimum z vertex value
+ Double_t fZMax; // Maximum z vertex value
+ Bool_t fResolution; // Flag to set the resolution computation
+
+ TF1* fSPD1LR; // SPD acceptance shape
+ TF1* fSPD1LL; // SPD acceptance shape
+ TF1* fSPD2LR; // SPD acceptance shape
+ TF1* fSPD2LL; // SPD acceptance shape
+
+ ClassDef(AliAnalysisMuMuNch,1) // implementation of AliAnalysisMuMuBase for Nch analysis
+};
+
+#endif
--- /dev/null
+#include "AliAnalysisMuMuSingle.h"
+
+/**
+ *
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisMuMuSingle
+ *
+ * Histogramming of single muon tracks. Mostly to get control plots for
+ * the AliAnalysisMuMuMinv sub-analysis, with respect to track cuts used,
+ * like Rabs, p x DCA, etc...
+ *
+ */
+
+
+#include "TH2F.h"
+#include "AliMuonTrackCuts.h"
+#include "AliAnalysisMuonUtility.h"
+#include "TMath.h"
+#include "AliLog.h"
+#include "AliVParticle.h"
+#include "TLorentzVector.h"
+#include "AliAnalysisMuMuCutCombination.h"
+#include "AliAnalysisMuMuCutRegistry.h"
+#include "AliMergeableCollection.h"
+
+ClassImp(AliAnalysisMuMuSingle)
+
+//_____________________________________________________________________________
+AliAnalysisMuMuSingle::AliAnalysisMuMuSingle()
+: AliAnalysisMuMuBase(),
+fMuonTrackCuts(0x0),
+fShouldSeparatePlusAndMinus(kFALSE),
+fAccEffHisto(0x0)
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+AliAnalysisMuMuSingle::~AliAnalysisMuMuSingle()
+{
+ /// dtor
+ delete fMuonTrackCuts;
+ delete fAccEffHisto;
+}
+
+
+//_____________________________________________________________________________
+void
+AliAnalysisMuMuSingle::CreateTrackHisto(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy, Double_t ymin, Double_t ymax,
+ Bool_t separatePlusAndMinus) const
+{
+ /// Append histograms for single track to our histogram collection
+
+ if ( IsHistogramDisabled(hname) ) return;
+
+ if ( separatePlusAndMinus )
+ {
+ const char* suffix[] = { "Plus", "Minus" };
+ const char* symbol[] = { "+", "-" };
+
+ for ( Int_t i = 0; i < 2; ++i )
+ {
+ TString shtitle(htitle);
+ TString shname(hname);
+
+ shtitle.ReplaceAll("#mu",Form("#mu^{%s}",symbol[i]));
+
+ shname += suffix[i];
+
+ CreateTrackHistos(eventSelection,triggerClassName,centrality,shname.Data(),shtitle.Data(),
+ nbinsx,xmin,xmax,nbinsy,ymin,ymax);
+ }
+ }
+ else
+ {
+ CreateTrackHistos(eventSelection,triggerClassName,centrality,hname,htitle,
+ nbinsx,xmin,xmax,nbinsy,ymin,ymax);
+ }
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuSingle::IsRabsOK(const AliVParticle& part) const
+{
+ Double_t thetaAbsEndDeg = AliAnalysisMuonUtility::GetThetaAbsDeg(&part);
+
+ return ( thetaAbsEndDeg > 2. && thetaAbsEndDeg < 10. );
+}
+
+//_____________________________________________________________________________
+Bool_t AliAnalysisMuMuSingle::IsEtaInRange(const AliVParticle& part, Double_t& etamin, Double_t& etamax) const
+{
+ return (part.Eta() >= etamin && part.Eta() <= etamax);
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuSingle::SetRun(const AliInputEventHandler* eventHandler)
+{
+ MuonTrackCuts()->SetRun(eventHandler);
+}
+
+//_____________________________________________________________________________
+Int_t AliAnalysisMuMuSingle::EAGetNumberOfMuonTracks() const
+{
+ // Get the number of muon tracks *that are not ghosts*
+
+ Int_t ntracks = AliAnalysisMuonUtility::GetNTracks(Event());
+
+ for ( Int_t i = 0; i < ntracks; ++i )
+ {
+ AliVParticle* track = AliAnalysisMuonUtility::GetTrack(i,Event());
+ if (AliAnalysisMuonUtility::IsMuonGhost(track)) --ntracks;
+ }
+
+ return ntracks;
+}
+
+////_____________________________________________________________________________
+//Int_t AliAnalysisMuMuSingle::EAGetNumberOfSelectMuonTracks() const
+//{
+// // Get the number of "very good" muon tracks :
+// // Rabs + DCA + pT > 1.5 Gev/C
+//
+// Int_t nTracks = AliAnalysisMuonUtility::GetNTracks(Event());
+//
+// UInt_t check = kAll | kMatched | kRabs | kDCA | kEta | kPt1dot5;
+//
+// Int_t nGood(0);
+//
+// for ( Int_t i = 0; i < nTracks; ++i )
+// {
+// ULong64_t m = GetTrackMask(i);
+// if ( ( m & check ) == check )
+// {
+// ++nGood;
+// }
+// }
+// return nGood;
+//}
+
+//_____________________________________________________________________________
+Double_t AliAnalysisMuMuSingle::EAGetTrackDCA(const AliVParticle& track) const
+{
+ // Get track DCA
+
+ Double_t xdca = AliAnalysisMuonUtility::GetXatDCA(&track);
+ Double_t ydca = AliAnalysisMuonUtility::GetYatDCA(&track);
+
+ return TMath::Sqrt(xdca*xdca+ydca*ydca);
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuSingle::DefineHistogramCollection(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality)
+{
+ /// Actually create the histograms for phyics/triggerClassName
+
+ if ( Histo(eventSelection,triggerClassName,centrality,"AliAnalysisMuMuSingle") )
+ {
+ return;
+ }
+
+ AliAnalysisMuMuBase::EDataType dt = AliAnalysisMuMuBase::kHistoForData;
+
+ // dummy histogram to signal that we already defined all our histograms (see above)
+ CreateEventHistos(dt,eventSelection,triggerClassName,centrality,"AliAnalysisMuMuSingle","Dummy semaphore",1,0,1);
+
+ Double_t ptMin = 0;
+ Double_t ptMax = 12*3;
+ Int_t nbinsPt = GetNbins(ptMin,ptMax,0.5);
+ Double_t pMin = 0;
+ Double_t pMax = 100*3;
+ Int_t nbinsP = GetNbins(pMin,pMax,2.0);
+ Double_t etaMin = -5;
+ Double_t etaMax = -2;
+ Int_t nbinsEta = GetNbins(etaMin,etaMax,0.05);
+
+ Double_t rapidityMin = -5;
+ Double_t rapidityMax = -2;
+ Int_t nbinsRapidity = GetNbins(rapidityMin,rapidityMax,0.05);
+
+ Double_t phiMin = -TMath::Pi();
+ Double_t phiMax = TMath::Pi();
+ Int_t nbinsPhi = GetNbins(phiMin,phiMax,0.05);
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"Chi2MatchTrigger","Chi2 Match Trigger",72,0,72);
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"EtaRapidityMu", "Eta distribution vs Rapidity for #mu", nbinsRapidity,rapidityMin,rapidityMax,nbinsEta,etaMin,etaMax, fShouldSeparatePlusAndMinus);
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"PtEtaMu", "P_{T} distribution vs Eta for #mu", nbinsEta,etaMin,etaMax, nbinsPt,ptMin,ptMax,fShouldSeparatePlusAndMinus);
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"PtRapidityMu", "P_{T} distribution vs Rapidity for #mu", nbinsRapidity,rapidityMin,rapidityMax, nbinsPt,ptMin,ptMax,fShouldSeparatePlusAndMinus);
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"PtPhiMu", "P_{T} distribution vs phi for #mu", nbinsPhi,phiMin,phiMax, nbinsPt,ptMin,ptMax,fShouldSeparatePlusAndMinus);
+
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"PEtaMu", "P distribution for #mu",nbinsEta,etaMin,etaMax,nbinsP,pMin,pMax,fShouldSeparatePlusAndMinus);
+
+ Double_t chi2min = 0;
+ Double_t chi2max = 20;
+ Int_t nbinchi2 = GetNbins(chi2min,chi2max,0.05);
+
+ CreateTrackHisto(eventSelection, triggerClassName, centrality, "Chi2Mu", "chisquare per NDF #mu", nbinchi2, chi2min, chi2max,-1, 0.0, 0.0, fShouldSeparatePlusAndMinus);
+
+ Double_t xmin = 0;
+ Double_t xmax = 150;
+ Int_t nbins = GetNbins(xmin,xmax,2.0);
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"dcaP23Mu","#mu DCA vs P for 2-3 degrees;P (GeV);DCA (cm)",nbinsP,pMin,pMax,nbins,xmin,xmax,fShouldSeparatePlusAndMinus);
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"dcaP310Mu","#mu DCA vs P for 3-10 degrees;P (GeV);DCA (cm)",nbinsP,pMin,pMax,nbins,xmin,xmax,fShouldSeparatePlusAndMinus);
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"dcaPwPtCut23Mu","#mu DCA vs P for 2-3 degrees with Pt Cut;P (GeV);DCA (cm)",nbinsP,pMin,pMax,nbins,xmin,xmax,fShouldSeparatePlusAndMinus);
+
+ CreateTrackHisto(eventSelection,triggerClassName,centrality,"dcaPwPtCut310Mu","#mu DCA vs P for 3-10 degrees with Pt Cut;P (GeV);DCA (cm)",nbinsP,pMin,pMax,nbins,xmin,xmax,fShouldSeparatePlusAndMinus);
+
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuSingle::FillHistosForTrack(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* trackCutName,
+ const AliVParticle& track)
+{
+ /// Fill histograms for one track
+
+ if (!AliAnalysisMuonUtility::IsMuonTrack(&track) ) return;
+
+ if ( HasMC() )
+ {
+ MuonTrackCuts()->SetIsMC();
+ }
+
+ TLorentzVector p(track.Px(),track.Py(),track.Pz(),
+ TMath::Sqrt(AliAnalysisMuonUtility::MuonMass2()+track.P()*track.P()));
+
+
+ TString charge("");
+
+ if ( ShouldSeparatePlusAndMinus() )
+ {
+ if ( track.Charge() < 0 )
+ {
+ charge = "Minus";
+ }
+ else
+ {
+ charge = "Plus";
+ }
+ }
+
+ Double_t dca = EAGetTrackDCA(track);
+
+ Double_t theta = AliAnalysisMuonUtility::GetThetaAbsDeg(&track);
+
+ if (!IsHistogramDisabled("Chi2MatchTrigger"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,"Chi2MatchTrigger")->Fill(AliAnalysisMuonUtility::GetChi2MatchTrigger(&track));
+ }
+
+ if (!IsHistogramDisabled("EtaRapidityMu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("EtaRapidityMu%s",charge.Data()))->Fill(p.Rapidity(),p.Eta());
+ }
+
+ if (!IsHistogramDisabled("PtEtaMu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("PtEtaMu%s",charge.Data()))->Fill(p.Eta(),p.Pt());
+ }
+
+ if (!IsHistogramDisabled("PtRapidityMu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("PtRapidityMu%s",charge.Data()))->Fill(p.Rapidity(),p.Pt());
+ }
+
+ if (!IsHistogramDisabled("PEtaMu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("PEtaMu%s",charge.Data()))->Fill(p.Eta(),p.P());
+ }
+
+ if (!IsHistogramDisabled("PtPhiMu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("PtPhiMu%s",charge.Data()))->Fill(p.Phi(),p.Pt());
+ }
+
+ if (!IsHistogramDisabled("Chi2Mu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("Chi2Mu%s",charge.Data()))->Fill(AliAnalysisMuonUtility::GetChi2perNDFtracker(&track));
+ }
+
+ if ( theta >= 2.0 && theta < 3.0 )
+ {
+
+ if (!IsHistogramDisabled("dcaP23Mu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("dcaP23Mu%s",charge.Data()))->Fill(p.P(),dca);
+ }
+
+ if ( p.Pt() > 2 )
+ {
+ if (!IsHistogramDisabled("dcaPwPtCut23Mu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("dcaPwPtCut23Mu%s",charge.Data()))->Fill(p.P(),dca);
+ }
+ }
+ }
+ else if ( theta >= 3.0 && theta < 10.0 )
+ {
+ if (!IsHistogramDisabled("dcaP310Mu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("dcaP310Mu%s",charge.Data()))->Fill(p.P(),dca);
+ }
+ if ( p.Pt() > 2 )
+ {
+ if (!IsHistogramDisabled("dcaPwPtCut310Mu*"))
+ {
+ Histo(eventSelection,triggerClassName,centrality,trackCutName,Form("dcaPwPtCut310Mu%s",charge.Data()))->Fill(p.P(),dca);
+ }
+ }
+ }
+}
+
+//_____________________________________________________________________________
+AliMuonTrackCuts* AliAnalysisMuMuSingle::MuonTrackCuts()
+{
+ /// Get (and create the first time) our internal track cuts
+ if (!fMuonTrackCuts)
+ {
+ fMuonTrackCuts = new AliMuonTrackCuts;
+
+ fMuonTrackCuts->SetAllowDefaultParams(kTRUE);
+
+ fMuonTrackCuts->SetFilterMask(AliMuonTrackCuts::kMuEta |
+ AliMuonTrackCuts::kMuThetaAbs |
+ AliMuonTrackCuts::kMuPdca |
+ AliMuonTrackCuts::kMuMatchApt |
+ AliMuonTrackCuts::kMuMatchLpt |
+ AliMuonTrackCuts::kMuMatchHpt |
+ AliMuonTrackCuts::kMuTrackChiSquare);
+
+ }
+
+ return fMuonTrackCuts;
+}
+
+//_____________________________________________________________________________
+void AliAnalysisMuMuSingle::SetMuonTrackCuts(const AliMuonTrackCuts& trackCuts)
+{
+ /// Set our muontrackcuts from external source
+ delete fMuonTrackCuts;
+ fMuonTrackCuts = static_cast<AliMuonTrackCuts*>(trackCuts.Clone());
+}
--- /dev/null
+#ifndef ALIANALYSISMUMUSINGLE_H
+#define ALIANALYSISMUMUSINGLE_H
+
+/**
+ *
+ * \class AliAnalysisMuMuSingle
+ *
+ * \brief Histogramming of single muon tracks.
+ *
+ * \author L. Aphecetche (Subatech)
+ *
+ */
+
+#include "AliAnalysisMuMuBase.h"
+
+class AliMuonTrackCuts;
+class TH2F;
+class TObjArray;
+
+class AliAnalysisMuMuSingle : public AliAnalysisMuMuBase
+{
+public:
+
+ AliAnalysisMuMuSingle();
+ virtual ~AliAnalysisMuMuSingle();
+
+ virtual void ShouldSeparatePlusAndMinus(Bool_t value) { fShouldSeparatePlusAndMinus = value; }
+
+ virtual Bool_t ShouldSeparatePlusAndMinus() const { return fShouldSeparatePlusAndMinus; }
+
+ AliMuonTrackCuts* MuonTrackCuts();
+
+ void SetMuonTrackCuts(const AliMuonTrackCuts& trackCuts);
+
+ Bool_t IsRabsOK(const AliVParticle& part) const;
+ void NameOfIsRabsOK(TString& name) const { name = "RABS"; }
+
+ Bool_t IsEtaInRange(const AliVParticle& part, Double_t& etamin, Double_t& etamax) const;
+ void NameOfIsEtaInRange(TString& name, Double_t& etamin, Double_t& etamax) const
+ { name.Form("ETA%3.1f-%3.1f",etamin,etamax); }
+
+ void SetRun(const AliInputEventHandler* eventHandler);
+
+protected:
+
+ void DefineHistogramCollection(const char* eventSelection, const char* triggerClassName,
+ const char* centrality);
+
+ virtual void FillHistosForTrack(const char* eventSelection, const char* triggerClassName,
+ const char* centrality,
+ const char* trackCutName,
+ const AliVParticle& part);
+
+private:
+
+ void CreateTrackHisto(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality,
+ const char* hname, const char* htitle,
+ Int_t nbinsx, Double_t xmin, Double_t xmax,
+ Int_t nbinsy=-1, Double_t ymin=0.0, Double_t ymax=0.0,
+ Bool_t separatePlusAndMinus=kFALSE) const;
+
+ Double_t GetTrackTheta(const AliVParticle& particle) const;
+
+ /* methods prefixed with EA should really not exist at all. They are there
+ only because the some of our base interfaces are shamelessly incomplete or
+ inadequate...
+ */
+
+ Int_t EAGetNumberOfMuonTracks() const;
+
+// Int_t EAGetNumberOfSelectMuonTracks() const;
+
+ Double_t EAGetTrackDCA(const AliVParticle& particle) const;
+
+private:
+ AliMuonTrackCuts* fMuonTrackCuts; //! common cuts for muon tracks (from Diego)
+ Bool_t fShouldSeparatePlusAndMinus; // whether or not to histogram mu+ and mu- separately
+ TH2F* fAccEffHisto; // dimuon acc x eff (y vs pt)
+
+ ClassDef(AliAnalysisMuMuSingle,1) // implementation of AliAnalysisMuMuBase for single mu analysis
+};
+
+#endif
#include "TFile.h"
// STEER includes
-#include "AliInputEventHandler.h"
-#include "AliAODHeader.h"
#include "AliAODEvent.h"
-#include "AliAODTrack.h"
+#include "AliAODHeader.h"
#include "AliAODMCHeader.h"
#include "AliAODMCParticle.h"
-#include "AliMCEvent.h"
-#include "AliMCParticle.h"
+#include "AliAODTrack.h"
+#include "AliAODTZERO.h"
#include "AliESDEvent.h"
#include "AliESDMuonTrack.h"
-#include "AliVVertex.h"
+#include "AliESDTZERO.h"
+#include "AliInputEventHandler.h"
#include "AliLog.h"
+#include "AliMCEvent.h"
+#include "AliMCParticle.h"
+#include "AliVVertex.h"
#include "AliStack.h"
// CORRFW includes
return trackHistory;
}
+//________________________________________________________________________
+Bool_t AliAnalysisMuonUtility::EAGetTZEROFlags(const AliVEvent* event, Bool_t& backgroundFlag, Bool_t& pileupFlag, Bool_t& satelliteFlag)
+{
+ // get the TZERO decisions
+ // return false if there's no tzero information in this event
+
+ Bool_t rv(kFALSE);
+
+ if ( event->IsA() == AliESDEvent::Class() )
+ {
+ const AliESDTZERO* tzero = static_cast<AliESDEvent*>(const_cast<AliVEvent*>(event))->GetESDTZERO();
+ if ( tzero )
+ {
+ backgroundFlag = tzero->GetBackgroundFlag();
+ pileupFlag = tzero->GetPileupFlag();
+ satelliteFlag = tzero->GetSatellite();
+ rv = kTRUE;
+ }
+ }
+ else if ( event->IsA() == AliAODEvent::Class() )
+ {
+ AliAODTZERO* tzero = static_cast<const AliAODEvent*>(event)->GetTZEROData();
+ if ( tzero )
+ {
+ backgroundFlag = tzero->GetBackgroundFlag();
+ pileupFlag = tzero->GetPileupFlag();
+ satelliteFlag = tzero->GetSatellite();
+ rv = kTRUE;
+ }
+ }
+ else
+ {
+ AliErrorClass(Form("Unknown class for the event = %s",event->ClassName()));
+ }
+
+ return rv;
+}
//_______________________________________________________________________
Bool_t AliAnalysisMuonUtility::SetSparseRange(AliCFGridSparse* gridSparse,
static UInt_t GetMCProcess ( const AliVParticle* mcParticle );
static UInt_t GetStatusCode ( const AliVParticle* mcParticle );
+ static Bool_t EAGetTZEROFlags(const AliVEvent* event, Bool_t& backgroundFlag, Bool_t& pileupFlag, Bool_t& satelliteFlag);
+
// A useful constant
static Double_t MuonMass2();
#include "AliAnalysisManager.h"
#include "AliAnalysisMuMuBinning.h"
#include "AliAnalysisMuonUtility.h"
+#include "AliAnalysisUtils.h"
#include "AliAODEvent.h"
#include "AliAODMCParticle.h"
#include "AliAODTrack.h"
#include "AliCodeTimer.h"
#include "AliCounterCollection.h"
#include "AliESDEvent.h"
-#include "AliESDMuonTrack.h"
#include "AliESDTZERO.h"
#include "AliInputEventHandler.h"
#include "AliLog.h"
#include "TMath.h"
#include "TObjString.h"
#include "TPaveText.h"
+#include "TProfile.h"
#include "TRegexp.h"
#include "TROOT.h"
#include <algorithm>
#include <cassert>
-
-//
-// AliAnalysisTaskMuMu : base class for mu pairs analysis
-//
-// Mainly invariant mass (for J/psi and Upsilon) but also
-// some single control histograms.
-//
-// This base class contains common things for ESD-based
-// and AOD-based analysis
-//
-// The output contains an AliHistogramCollection and
-// an AliCounterCollection
-//
-// author: L. Aphecetche (Subatech)
-//
+#include "AliAnalysisMuMuBase.h"
+#include "AliInputEventHandler.h"
+#include "AliAnalysisMuMuCutRegistry.h"
+#include "AliAnalysisMuMuCutElement.h"
+#include "AliAnalysisMuMuCutCombination.h"
+#include <set>
+
+/**
+ * \class AliAnalysisTaskMuMu
+ *
+ * This class steers the work of one or more sub-analysis deriving from AliAnalysisMuMuBase
+ * The output contains an AliHistogramCollection, an AliCounterCollection
+ * and an AliAnalysisMuMuBinning
+ * This task must be configured a bit before being used. For instance
+ * you can select various event cuts, single muon track cuts and
+ * muon pairs cut, as well as defining various bins (for minv and mean pt
+ * histograms) in pt,y,phi etc...
+ *
+ * Note that it's also possible to disable some (or all) histograms
+ * (to save speed/memory), using DisableHistograms() method.
+ *
+ * For an example of such configuration, \see AddTaskMuMu.C
+ */
using std::cout;
using std::endl;
ClassImp(AliAnalysisTaskMuMu)
-ClassImp(AliAnalysisTaskMuMu::PairCut)
-
-namespace
-{
- Int_t GetNbins(Double_t xmin, Double_t xmax, Double_t xstep)
- {
- if ( TMath::AreEqualRel(xstep,0.0,1E-9) ) return 1;
-
- return TMath::Nint(TMath::Abs((xmax-xmin)/xstep));
- }
-
- TObjArray* GetMuonTriggerList()
- {
- TObjArray* a = new TObjArray;
- a->SetOwner(kTRUE);
-
- a->Add(new TObjString("CMUL"));
- a->Add(new TObjString("CMLL"));
- a->Add(new TObjString("C0MUL"));
- a->Add(new TObjString("CMSL"));
- a->Add(new TObjString("CMSH"));
-
- return a;
- }
-
- TObjArray* GetEmcalTriggerList()
- {
- TObjArray* a = new TObjArray;
- a->SetOwner(kTRUE);
-
- a->Add(new TObjString("CEMC"));
-
- return a;
- }
-
- TObjArray* GetMBTriggerList()
- {
- TObjArray* a = new TObjArray;
- a->SetOwner(kTRUE);
-
- a->Add(new TObjString("CINT7-S-"));
- a->Add(new TObjString("CINT7-B-"));
- a->Add(new TObjString("CINT8-S-"));
-
- return a;
- }
-
- TString GetMinvHistoName(const AliAnalysisMuMuBinning::Range& r)
- {
- return TString::Format("MinvUS%s",r.AsString().Data());
- }
-
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::PairCut::Print(Option_t* /*opt*/) const
-{
- std::cout << Form("PAIR CUT %20s SINGLE MASK %x PAIR MASK %x",GetName(),MaskForOneOrBothTrack(),MaskForTrackPair())
- << std::endl;
-}
-
-//_____________________________________________________________________________
-AliAnalysisTaskMuMu::AliAnalysisTaskMuMu() : AliAnalysisTaskSE("AliAnalysisTaskMuMu"),
-fHistogramCollection(0),
-fEventCounters(0),
-fMuonTrackCuts(0x0),
-fPrecomputedTrackMasks(),
-fIsFromESD(kFALSE),
-fShouldSeparatePlusAndMinus(kFALSE),
-fBeamYear("pp"),
-fSingleTrackCutNames(0x0),
-fPairTrackCutNames(0x0),
-fCentralityNames(0x0),
-fEventCutNames(0x0),
-fUseBackgroundTriggers(kFALSE),
-fTriggerInputBitMap(),
-fBinning(0x0),
-fHistogramToDisable(0x0),
-fBinArray(0x0),
-fHasMC(kFALSE),
-fEventCuts(0x0)
-{
- /// default ctor
-}
-
-//_____________________________________________________________________________
-AliAnalysisTaskMuMu::AliAnalysisTaskMuMu(Bool_t fromESD, const char* beamYear, TArrayF* centralities)
-: AliAnalysisTaskSE(Form("AliAnalysisTaskMuMu-from%s",fromESD ? "ESD":"AOD")),
-fHistogramCollection(0),
-fEventCounters(0),
-fMuonTrackCuts(0x0),
-fPrecomputedTrackMasks(),
-fIsFromESD(fromESD),
-fShouldSeparatePlusAndMinus(kFALSE),
-fBeamYear(beamYear),
-fSingleTrackCutNames(0x0),
-fPairTrackCutNames(0x0),
-fCentralityNames(new TObjArray),
-fEventCutNames(0x0),
-fUseBackgroundTriggers(kFALSE),
-fTriggerInputBitMap(),
-fBinning(0x0),
-fHistogramToDisable(0x0),
-fBinArray(0x0),
-fHasMC(kFALSE),
-fEventCuts(0x0)
-{
- /// Constructor
- /// The list of triggers to be considered will be updated on the fly
-
- DefineOutput(1,AliMergeableCollection::Class());
- DefineOutput(2,AliCounterCollection::Class());
- DefineOutput(3,AliAnalysisMuMuBinning::Class());
-
- DefineDefaultBinning();
-
- DefineCentralityClasses(centralities);
-}
//_____________________________________________________________________________
-AliAnalysisTaskMuMu::AliAnalysisTaskMuMu(Bool_t fromESD, TList* triggerClasses, const char* beamYear, TArrayF* centralities)
-: AliAnalysisTaskSE(Form("AliAnalysisTaskMuMu-from%s",fromESD ? "ESD":"AOD")),
+AliAnalysisTaskMuMu::AliAnalysisTaskMuMu()
+: AliAnalysisTaskSE("AliAnalysisTaskMuMu"),
fHistogramCollection(0),
fEventCounters(0),
-fMuonTrackCuts(0x0),
-fPrecomputedTrackMasks(),
-fIsFromESD(fromESD),
-fShouldSeparatePlusAndMinus(kFALSE),
-fBeamYear(beamYear),
-fSingleTrackCutNames(0x0),
-fPairTrackCutNames(0x0),
-fCentralityNames(new TObjArray),
-fEventCutNames(0x0),
-fUseBackgroundTriggers(kFALSE),
-fTriggerInputBitMap(),
fBinning(0x0),
+fCutRegistry(0x0),
+fBeamYear(""),
fHistogramToDisable(0x0),
-fBinArray(0x0),
-fHasMC(kFALSE),
-fEventCuts(0x0)
+fSubAnalysisVector(0x0)
{
/// Constructor with a predefined list of triggers to consider
+ /// Note that we take ownership of cutRegister
+ ///
+
+// fBranchNames = "AOD:header,tracks,vertices,tracklets,AliAODTZERO,AliAODVZERO";
DefineOutput(1,AliMergeableCollection::Class());
DefineOutput(2,AliCounterCollection::Class());
DefineOutput(3,AliAnalysisMuMuBinning::Class());
-
- TObjString* tname;
- TIter next(triggerClasses);
- TString tclasses;
-
- while ( ( tname = static_cast<TObjString*>(next()) ) )
- {
- if (tclasses.Length()>0)
- {
- tclasses += ",";
- }
-
- tclasses += tname->String();
- }
-
- EventCuts()->SetTrigClassPatterns(tclasses);
-
- DefineDefaultBinning();
-
- DefineCentralityClasses(centralities);
}
//_____________________________________________________________________________
delete fBinning;
}
- delete fMuonTrackCuts;
-
- delete fSingleTrackCutNames;
- delete fPairTrackCutNames;
- delete fCentralityNames;
- delete fEventCutNames;
delete fHistogramToDisable;
- delete fBinArray;
- delete fEventCuts;
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::AddBin(const char* particle, const char* type,
- Double_t xmin, Double_t xmax,
- Double_t ymin, Double_t ymax,
- const char* flavour)
-{
- /// Add one bin
- fBinning->AddBin(particle,type,xmin,xmax,ymin,ymax,flavour);
-
- // invalidate cached bins, if any
- if (fBinArray)
- {
- delete fBinArray;
- fBinArray = 0x0;
- }
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::AddPairCut(const char* cutName, UInt_t maskForOneOrBothTrack, UInt_t maskForTrackPair)
-{
- /// Add a cut for a pair.
- /// maskForOneOrBothTrack is the mask of cuts that at least one track must satisfy
- /// maskForTrackPair is the mask of cuts that *both* tracks must satisfy.
- /// if maskForTrackPair is 0, then no (extra) condition is applied to the pair
-
- if ( !fPairTrackCutNames )
- {
- fPairTrackCutNames = new TObjArray;
- fPairTrackCutNames->SetOwner(kTRUE);
- }
- fPairTrackCutNames->Add(new AliAnalysisTaskMuMu::PairCut(cutName,maskForOneOrBothTrack,maskForTrackPair));
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::AddSingleCut(const char* name, UInt_t mask)
-{
- /// Add a cut for single tracks
- if ( !fSingleTrackCutNames )
- {
- fSingleTrackCutNames = new TObjArray;
- fSingleTrackCutNames->SetOwner(kTRUE);
- }
- TObjString* oname = new TObjString(Form("s%s",name));
- oname->SetUniqueID(mask);
- fSingleTrackCutNames->Add(oname);
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::AddEventCut(const char* name, UInt_t mask)
-{
- /// Add a cut at event level
- if ( !fEventCutNames )
- {
- fEventCutNames = new TObjArray;
- fEventCutNames->SetOwner(kTRUE);
- }
- TObjString* oname = new TObjString(Form("%s",name));
- oname->SetUniqueID(mask);
- fEventCutNames->Add(oname);
-}
-
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::AssertHistogramCollection(const char* physics, const char* triggerClassName)
-{
- // insure that a given set of histogram is created
- if (!fHistogramCollection->Histo(Form("/%s/%s/%s/Zvertex",physics,triggerClassName,DefaultCentralityName())))
- {
- FillHistogramCollection(physics,triggerClassName);
- }
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::BeautifyHistos()
-{
- /// Put the titles, marker sizes, color, etc...
-
- TIter next(fHistogramCollection->CreateIterator());
- TH1* h;
-
- while ( ( h = static_cast<TH1*>(next()) ) )
- {
- TString name(h->GetName());
-
- if ( name.Contains("Plus") )
- {
- h->SetMarkerStyle(kFullCircle);
- h->SetMarkerColor(kBlue);
- h->SetLineColor(kBlue);
- }
- else if ( name.Contains("Minus") )
- {
- h->SetMarkerStyle(kOpenCircle);
- h->SetMarkerColor(kRed);
- h->SetLineColor(kRed);
- }
- }
-}
-
-//_____________________________________________________________________________
-const char*
-AliAnalysisTaskMuMu::CentralityName(Double_t centrality) const
-{
- /// Get centrality name corresponding to the floating ^point value
-
- if ( centrality > 0 && centrality <= 100.0 )
- {
- return Form("CENT%02d",TMath::Nint(centrality));
- }
- else
- {
- return DefaultCentralityName();
- }
-}
-
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::ComputeTrackMask(const AliVParticle& track, Int_t trackIndex)
-{
- // Compute the track mask
- UInt_t m(kAll);
- UInt_t selectionMask = MuonTrackCuts()->GetSelectionMask(&track);
+ delete fCutRegistry;
- if ( ( selectionMask & AliMuonTrackCuts::kMuThetaAbs ) == AliMuonTrackCuts::kMuThetaAbs ) m |= kRabs;
-
- Double_t angle = AliAnalysisMuonUtility::GetThetaAbsDeg(&track);
-
- if ( angle >= 2.0 && angle < 3.0 ) m |= kDeg23;
-
- if ( angle >= 3.0 && angle < 10.0 ) m |= kDeg310;
-
- if ( selectionMask & AliMuonTrackCuts::kMuEta ) m |= kEta;
-
- Double_t pt = track.Pt();
-
- if ( pt > 1.0 ) m |= kPt1;
- if ( pt > 1.2 ) m |= kPt1dot2;
- if ( pt > 1.5 ) m |= kPt1dot5;
- if ( pt > 2.0 ) m |= kPt2;
-
- if ( track.P() > 10.0 ) m |= kP10;
-
- if ( pt < 4.0 ) m |= kBelowPt;
-
- if ( ( selectionMask & AliMuonTrackCuts::kMuMatchApt ) == AliMuonTrackCuts::kMuMatchApt ) m |= kMatched;
-
- if ( ( selectionMask & AliMuonTrackCuts::kMuMatchLpt ) == AliMuonTrackCuts::kMuMatchLpt ) m |= kMatchedLow;
-
- if ( ( selectionMask & AliMuonTrackCuts::kMuMatchHpt ) == AliMuonTrackCuts::kMuMatchHpt) m |= kMatchedHigh;
-
- if ( ( selectionMask & AliMuonTrackCuts::kMuTrackChiSquare ) == AliMuonTrackCuts::kMuTrackChiSquare ) m |= kChi2;
-
- if ( ( selectionMask & AliMuonTrackCuts::kMuPdca ) == AliMuonTrackCuts::kMuPdca ) m |= kDCA;
-
- if ( AliAnalysisMuonUtility::GetChi2MatchTrigger(&track) < 16.0 ) m |= kChi2MatchTrigger;
-
- fPrecomputedTrackMasks.SetAt(m,trackIndex);
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::CreateMesh(const char* particle, const char* type1, const char* type2, const char* flavour, Bool_t remove12)
-{
- /// Create a 2d binning from 2 1d binning.
- /// WARNING : not fully tested yet
-
- if (!fBinning)
- {
- AliError("Cannot create a mesh as I have no bin at all !");
- return;
- }
- fBinning->CreateMesh(particle,type1,type2,flavour,remove12);
+ delete fSubAnalysisVector;
}
//_____________________________________________________________________________
-void
-AliAnalysisTaskMuMu::CreateMinvHistograms(const char* physics,
- const char* triggerClassName)
+void AliAnalysisTaskMuMu::AdoptSubAnalysis(AliAnalysisMuMuBase* analysis)
{
- /// Create invariant mass histograms
-
- Double_t minvMin = 0;
- Double_t minvMax = 16;
- Int_t nMinvBins = GetNbins(minvMin,minvMax,0.025);
-
- Int_t nMCMinvBins = GetNbins(minvMin,minvMax,0.1);
-
- TObjArray* bins = fBinning->CreateBinObjArray("psi","y vs pt,integrated,pt,y,phi","");
-
- CreatePairHisto(physics,triggerClassName,"Pt","#mu+#mu- Pt distribution",
- 200,0,20);
-
-// CreatePairHisto(physics,triggerClassName,"BinFlowPt","#mu+#mu- BinFlowPt distribution",
-// 200,0,20);
-
- CreatePairHisto(physics,triggerClassName,"PtRecVsSim","#mu+#mu- Pt distribution rec vs sim",
- 200,0,20,200,0,20);
-
- TIter next(bins);
- AliAnalysisMuMuBinning::Range* r;
- while ( ( r = static_cast<AliAnalysisMuMuBinning::Range*>(next()) ) )
- {
- TString hname(GetMinvHistoName(*r));
-
- if ( IsHistogramDisabled(hname.Data()) ) continue;
-
- AliDebug(1,Form("histoname = %s",hname.Data()));
-
- CreatePairHisto(physics,triggerClassName,hname.Data(),
- Form("#mu+#mu- inv. mass %s",r->AsString().Data()),
- nMinvBins,minvMin,minvMax);
-
- TH1* h = fHistogramCollection->Histo("/INPUT/ALL",hname.Data());
- if (!h)
- {
- h = new TH1F(hname.Data(),Form("MC #mu+#mu- inv. mass %s",r->AsString().Data()),
- nMCMinvBins,minvMin,minvMax);
-
- fHistogramCollection->Adopt("/INPUT/ALL",h);
-
- fHistogramCollection->Adopt("/INPUT/INYRANGE",static_cast<TH1*>(h->Clone()));
- }
- }
-
-
- delete bins;
-}
-
-//_____________________________________________________________________________
-void
-AliAnalysisTaskMuMu::CreateSingleHisto(const char* physics,
- const char* triggerClassName,
- const char* hname, const char* htitle,
- Int_t nbinsx, Double_t xmin, Double_t xmax,
- Int_t nbinsy, Double_t ymin, Double_t ymax,
- Bool_t separatePlusAndMinus) const
-{
- /// Append histograms for single track to our histogram collection
-
- if ( IsHistogramDisabled(hname) ) return;
-
- if ( separatePlusAndMinus )
+ if (!fSubAnalysisVector)
{
- const char* suffix[] = { "Plus", "Minus" };
- const char* symbol[] = { "+", "-" };
-
- for ( Int_t i = 0; i < 2; ++i )
- {
- TString shtitle(htitle);
- TString shname(hname);
-
- shtitle.ReplaceAll("#mu",Form("#mu^{%s}",symbol[i]));
-
- shname += suffix[i];
-
- CreateHisto(fSingleTrackCutNames,physics,triggerClassName,shname.Data(),shtitle.Data(),
- nbinsx,xmin,xmax,nbinsy,ymin,ymax);
- }
+ fSubAnalysisVector = new TObjArray;
+ fSubAnalysisVector->SetOwner(kTRUE);
}
- else
+ if ( !fSubAnalysisVector->FindObject(analysis) )
{
- CreateHisto(fSingleTrackCutNames,physics,triggerClassName,hname,htitle,
- nbinsx,xmin,xmax,nbinsy,ymin,ymax);
+ fSubAnalysisVector->Add(analysis);
}
}
//_____________________________________________________________________________
-void
-AliAnalysisTaskMuMu::CreatePairHisto(const char* physics,
- const char* triggerClassName,
- const char* hname, const char* htitle,
- Int_t nbinsx, Double_t xmin, Double_t xmax,
- Int_t nbinsy, Double_t ymin, Double_t ymax) const
-{
- /// Append histograms for track pairs to our histogram collection
-
- if ( IsHistogramDisabled(hname) ) return;
-
- CreateHisto(fPairTrackCutNames,physics,triggerClassName,hname,htitle,
- nbinsx,xmin,xmax,nbinsy,ymin,ymax);
-}
-
-//_____________________________________________________________________________
-void
-AliAnalysisTaskMuMu::CreateEventHisto(const char* physics,
- const char* triggerClassName,
- const char* hname, const char* htitle,
- Int_t nbinsx, Double_t xmin, Double_t xmax,
- Int_t nbinsy, Double_t ymin, Double_t ymax) const
+AliAnalysisMuMuCutRegistry* AliAnalysisTaskMuMu::CutRegistry() const
{
- /// Append histograms at the event level
-
- if ( IsHistogramDisabled(hname) ) return;
-
- TIter next(fCentralityNames);
- TObjString* cent;
-
- while ( ( cent = static_cast<TObjString*>(next()) ) )
+ /// Return (and create if not yet there) our cut registry
+ if (!fCutRegistry)
{
- TH1* h(0x0);
-
- if ( nbinsy > 0 )
- {
- h = new TH2F(hname,htitle,nbinsx,xmin,xmax,nbinsy,ymin,ymax);
- }
- else
- {
- h = new TH1F(hname,htitle,nbinsx,xmin,xmax);
- }
-
- fHistogramCollection->Adopt(Form("/%s/%s/%s/",physics,triggerClassName,cent->String().Data()),h);
+ fCutRegistry = new AliAnalysisMuMuCutRegistry;
}
-}
-
-//_____________________________________________________________________________
-void
-AliAnalysisTaskMuMu::CreateHisto(TObjArray* array,
- const char* physics,
- const char* triggerClassName,
- const char* hname, const char* htitle,
- Int_t nbinsx, Double_t xmin, Double_t xmax,
- Int_t nbinsy, Double_t ymin, Double_t ymax) const
-{
- /// Create a bunch of histograms for all centralities
- /// FIXME: have a way to specify the histo precision (i.e. F vs I vs S ...)
-
- if ( IsHistogramDisabled(hname) ) return;
-
- TIter next(array);
- TObjString* tcn;
- while ( ( tcn = static_cast<TObjString*>(next()) ) )
- {
- TIter nextCent(fCentralityNames);
- TObjString* cent;
-
- while ( ( cent = static_cast<TObjString*>(nextCent()) ) )
- {
- TH1* h(0x0);
-
- if ( nbinsy > 0 )
- {
- h = new TH2F(hname,htitle,nbinsx,xmin,xmax,nbinsy,ymin,ymax);
- }
- else
- {
- h = new TH1F(hname,htitle,nbinsx,xmin,xmax);
- }
-
- fHistogramCollection->Adopt(Form("/%s/%s/%s/%s",physics,triggerClassName,cent->String().Data(),tcn->String().Data()),h);
- }
- }
+ return fCutRegistry;
}
//_____________________________________________________________________________
else return "PP";
}
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::DefineCentralityClasses(TArrayF* centralities)
-{
- /// Define the default centrality classes that will be used.
-
- if ( !fBeamYear.Contains("pp") )
- {
- if ( !centralities )
- {
-// // default values
-// fCentralityLimits.push_back(10.0);
-// fCentralityLimits.push_back(30.0);
-// fCentralityLimits.push_back(50.0);
-// fCentralityLimits.push_back(80.0);
- }
- else
- {
- for ( Int_t i = 0; i < centralities->GetSize(); ++i )
- {
-// fCentralityLimits.push_back(centralities->At(i));
- }
- }
- }
-
-// for ( std::vector<double>::size_type i = 0; i < fCentralityLimits.size(); ++i )
-// {
-// Double_t limit = fCentralityLimits[i];
-// fCentralityNames->Add(new TObjString(CentralityName(limit)));
-// }
-
- fCentralityNames->Add(new TObjString(DefaultCentralityName()));
- fCentralityNames->SetOwner(kTRUE);
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::DefineDefaultBinning()
-{
- fBinning = new AliAnalysisMuMuBinning("BIN");
- fBinning->AddBin("psi","integrated");
-}
-
//_____________________________________________________________________________
void AliAnalysisTaskMuMu::DisableHistograms(const char* pattern)
{
/// Disable the histogramming of all the histograms matching the pattern
- TString spattern(pattern);
- if (spattern=="*")
- {
- delete fHistogramToDisable;
- fHistogramToDisable = 0x0;
- }
-
- if (!fHistogramToDisable)
- {
- fHistogramToDisable = new TList;
- fHistogramToDisable->SetOwner(kTRUE);
- }
-
- fHistogramToDisable->Add(new TObjString(spattern));
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::EAComputeTrackMasks()
-{
- // compute the track masks for the event
-
- fPrecomputedTrackMasks.Reset();
- Int_t n = AliAnalysisMuonUtility::GetNTracks(Event()); //EAGetNumberOfMuonTracks();
- fPrecomputedTrackMasks.Set(n);
+ TIter next(fSubAnalysisVector);
+ AliAnalysisMuMuBase* a;
- for ( Int_t i = 0; i < n; ++i )
+ while ( ( a = static_cast<AliAnalysisMuMuBase*>(next()) ) )
{
- AliVParticle* track = AliAnalysisMuonUtility::GetTrack(i,Event());
- ComputeTrackMask(*track,i);
+ a->DisableHistograms(pattern);
}
}
//_____________________________________________________________________________
-Int_t AliAnalysisTaskMuMu::EAGetNumberOfMuonTracks() const
+AliVEvent*
+AliAnalysisTaskMuMu::Event() const
{
- // Get the number of muon tracks *that are not ghosts*
-
- Int_t ntracks = AliAnalysisMuonUtility::GetNTracks(Event());
-
- for ( Int_t i = 0; i < ntracks; ++i )
- {
- AliVParticle* track = AliAnalysisMuonUtility::GetTrack(i,Event());
- if (AliAnalysisMuonUtility::IsMuonGhost(track)) --ntracks;
- }
-
- return ntracks;
+ // some const-dirty-dancing
+ return const_cast<AliAnalysisTaskMuMu*>(this)->InputEvent();
}
//_____________________________________________________________________________
-Int_t AliAnalysisTaskMuMu::EAGetNumberOfSelectMuonTracks() const
-{
- // Get the number of "very good" muon tracks :
- // Rabs + DCA + pT > 1.5 Gev/C
- // must be called after EAComputeTrackMasks
-
- Int_t nTracks = AliAnalysisMuonUtility::GetNTracks(Event());
-
- UInt_t check = kAll | kMatched | kRabs | kDCA | kEta | kPt1dot5;
-
- Int_t nGood(0);
-
- for ( Int_t i = 0; i < nTracks; ++i )
- {
- UInt_t m = GetTrackMask(i);
- if ( ( m & check ) == check )
- {
- ++nGood;
- }
- }
- return nGood;
-}
-
-//_____________________________________________________________________________
-Double_t AliAnalysisTaskMuMu::EAGetTrackDCA(const AliVParticle& track) const
-{
- // Get track DCA
-
- Double_t xdca = AliAnalysisMuonUtility::GetXatDCA(&track);
- Double_t ydca = AliAnalysisMuonUtility::GetYatDCA(&track);
-
- return TMath::Sqrt(xdca*xdca+ydca*ydca);
-}
-
-//_____________________________________________________________________________
-Bool_t AliAnalysisTaskMuMu::EAGetTZEROFlags(Bool_t& backgroundFlag, Bool_t& pileupFlag, Bool_t& satelliteFlag) const
-{
- // get the TZERO decisions
- // return false if there's no tzero information in this event
-
- Bool_t rv(kFALSE);
-
- if ( Event()->IsA() == AliESDEvent::Class() )
- {
- const AliESDTZERO* tzero = static_cast<AliESDEvent*>(const_cast<AliVEvent*>(Event()))->GetESDTZERO();
- if ( tzero )
- {
- backgroundFlag = tzero->GetBackgroundFlag();
- pileupFlag = tzero->GetPileupFlag();
- satelliteFlag = tzero->GetSatellite();
- rv = kTRUE;
- }
- }
- else if ( Event()->IsA() == AliAODEvent::Class() )
- {
- AliAODTZERO* tzero = static_cast<const AliAODEvent*>(Event())->GetTZEROData();
- if ( tzero )
- {
- backgroundFlag = tzero->GetBackgroundFlag();
- pileupFlag = tzero->GetPileupFlag();
- satelliteFlag = tzero->GetSatellite();
- rv = kTRUE;
- }
- }
- else
- {
- AliError(Form("Unknown class for the event = %s",Event()->ClassName()));
- }
-
- return rv;
-
-}
-
-//_____________________________________________________________________________
-AliVEvent*
-AliAnalysisTaskMuMu::Event() const
-{
- // some const-dirty-dancing
- return const_cast<AliAnalysisTaskMuMu*>(this)->InputEvent();
-}
-
-//_____________________________________________________________________________
-AliMuonEventCuts*
-AliAnalysisTaskMuMu::EventCuts() const
-{
- /// Return the single instance of AliMuonEventCuts object we're using
-
- if (!fEventCuts)
- {
- fEventCuts = new AliMuonEventCuts("EventCut","");
- }
- return fEventCuts;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliAnalysisTaskMuMu::AtLeastOneMBTrigger(const TString& firedTriggerClasses) const
-{
- // whether or not we have a least one MB trigger in the fired trigger classes
- static TObjArray* triggerList = GetMBTriggerList();
- TIter next(triggerList);
- TObjString* str;
-
- while ( ( str = static_cast<TObjString*>(next())))
- {
- if ( firedTriggerClasses.Contains(str->String().Data())) return kTRUE;
- }
-
- return kFALSE;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliAnalysisTaskMuMu::AtLeastOneMuonTrigger(const TString& firedTriggerClasses) const
-{
- // whether or not we have a least one muon trigger in the fired trigger classes
- static TObjArray* triggerList = GetMuonTriggerList();
- TIter next(triggerList);
- TObjString* str;
-
- while ( ( str = static_cast<TObjString*>(next())))
- {
- if ( firedTriggerClasses.Contains(str->String().Data())) return kTRUE;
- }
-
- return kFALSE;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliAnalysisTaskMuMu::AtLeastOneEmcalTrigger(const TString& firedTriggerClasses) const
-{
- // whether or not we have a least one emcal trigger in the fired trigger classes
- static TObjArray* triggerList = GetEmcalTriggerList();
- TIter next(triggerList);
- TObjString* str;
-
- while ( ( str = static_cast<TObjString*>(next())))
- {
- if ( firedTriggerClasses.Contains(str->String().Data())) return kTRUE;
- }
-
- return kFALSE;
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::FillMC()
-{
- // Fill the input MC histograms
-
- if (!HasMC()) return;
-
- // Specific things for MC
- if (!Histo("INPUT","ALL","Pt"))
- {
- fHistogramCollection->Adopt("/INPUT/ALL",new TH1F("Pt","Pt",200,0,20));
- fHistogramCollection->Adopt("/INPUT/INYRANGE",new TH1F("Pt","Pt",200,0,20));
-
- Double_t rapidityMin = -5;
- Double_t rapidityMax = -2;
- Int_t nbinsRapidity = GetNbins(rapidityMin,rapidityMax,0.05);
-
- fHistogramCollection->Adopt("/INPUT/ALL",new TH1F("Y","Y",nbinsRapidity,rapidityMin,rapidityMax));
- fHistogramCollection->Adopt("/INPUT/INYRANGE",new TH1F("Y","Y",nbinsRapidity,rapidityMin,rapidityMax));
-
- Double_t etaMin = -5;
- Double_t etaMax = -2;
- Int_t nbinsEta = GetNbins(etaMin,etaMax,0.05);
-
- fHistogramCollection->Adopt("/INPUT/ALL",new TH1F("Eta","Eta",nbinsEta,etaMin,etaMax));
- fHistogramCollection->Adopt("/INPUT/INYRANGE",new TH1F("Eta","Eta",nbinsEta,etaMin,etaMax));
- }
-
- Int_t nMCTracks = MCEvent()->GetNumberOfTracks();
-
- if (!fBinArray)
- {
- fBinArray = fBinning->CreateBinObjArray("psi","y vs pt,integrated,pt,y","");
- }
-
- TIter nextBin(fBinArray);
- AliAnalysisMuMuBinning::Range* r;
-
- for ( Int_t i = 0; i < nMCTracks; ++i )
- {
- AliVParticle* part = MCEvent()->GetTrack(i);
-
-// std::cout << "part " << i << " isprimary=" << AliAnalysisMuonUtility::IsPrimary(part,MCEvent()) << " motherindex=" << AliAnalysisMuonUtility::GetMotherIndex(part) << std::endl;
-//
-// part->Print();
-
- if (AliAnalysisMuonUtility::IsPrimary(part,MCEvent()) &&
- AliAnalysisMuonUtility::GetMotherIndex(part)==-1)
- {
-
- Histo("INPUT","ALL","Pt")->Fill(part->Pt());
- Histo("INPUT","ALL","Y")->Fill(part->Y());
- Histo("INPUT","ALL","Eta")->Fill(part->Eta());
-
- if ( part->Y() < -2.5 && part->Y() > -4.0 )
- {
- Histo("INPUT","INYRANGE","Pt")->Fill(part->Pt());
- Histo("INPUT","INYRANGE","Y")->Fill(part->Y());
- Histo("INPUT","INYRANGE","Eta")->Fill(part->Eta());
- }
-
- nextBin.Reset();
-
- while ( ( r = static_cast<AliAnalysisMuMuBinning::Range*>(nextBin()) ) )
- {
- Bool_t ok(kFALSE);
-
- if ( r->IsNullObject() )
- {
- ok = kTRUE;
- }
- else if ( r->Is2D() )
- {
- if ( r->AsString().BeginsWith("PTVSY") )
- {
- ok = r->IsInRange(part->Y(),part->Pt());
- }
- else if ( r->AsString().BeginsWith("YVSPT") )
- {
- ok = r->IsInRange(part->Pt(),part->Y());
- }
- else
- {
- AliError(Form("Don't know how to deal with 2D bin %s",r->AsString().Data()));
- }
- }
- else
- {
- if ( r->Type() == "PT" )
- {
- ok = r->IsInRange(part->Pt());
- }
- else if ( r->Type() == "Y" )
- {
- ok = r->IsInRange(part->Y());
- }
- else if ( r->Type() == "PHI" )
- {
- ok = r->IsInRange(part->Phi());
- }
- }
-
- if ( ok )
- {
- TString hname = GetMinvHistoName(*r);
-
- if (!IsHistogramDisabled(hname.Data()))
- {
- TH1* h = Histo("INPUT","ALL",hname.Data());
-
- if (!h)
- {
- AliError(Form("Could not get ALL %s",hname.Data()));
- continue;
- }
-
- h->Fill(part->M());
-
- if ( part->Y() < -2.5 && part->Y() > -4.0 )
- {
- h = Histo("INPUT","INYRANGE",hname.Data());
- if (!h)
- {
- AliError(Form("Could not get INYRANGE %s",hname.Data()));
- continue;
- }
- h->Fill(part->M());
- }
-
- }
-
- }
- }
- }
- }
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::Fill(const char* eventtype,
- TObjString* tname,
- const char* centrality,
- float fcent)
-{
- // Fill one set of histograms
-
- TString seventtype(eventtype);
- seventtype.ToLower();
-
- fEventCounters->Count(Form("event:%s/trigger:%s/run:%d", seventtype.Data(), tname->GetName(), fCurrentRunNumber));
-
- if ( !IsHistogrammingDisabled() )
- {
- AssertHistogramCollection(eventtype,tname->String().Data());
- FillHistos(eventtype,tname->String().Data(),centrality);
- if (!IsHistogramDisabled("Centrality"))
- {
- fHistogramCollection->Histo(Form("/%s/%s/Centrality",eventtype,tname->String().Data()))->Fill(fcent);
- }
- }
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::FillEventHistos(const char* physics, const char* triggerClassName,
- const char* centrality)
-{
- // Fill event-wise histograms
-
-// AliCodeTimerAuto("",0);
-
- if (!IsHistogramDisabled("BCX"))
- {
- Histo(physics,triggerClassName,centrality,"BCX")->Fill(1.0*Event()->GetBunchCrossNumber());
- }
-
- if (!IsHistogramDisabled("Nevents"))
- {
- Histo(physics,triggerClassName,centrality,"Nevents")->Fill(1.0);
- }
-
- const AliVVertex* vertex = Event()->GetPrimaryVertex();
-
- if ( vertex )
- {
- if (!IsHistogramDisabled("Xvertex"))
- {
- Histo(physics,triggerClassName,centrality,"Xvertex")->Fill(vertex->GetX());
- }
- if (!IsHistogramDisabled("Yvertex"))
- {
- Histo(physics,triggerClassName,centrality,"Yvertex")->Fill(vertex->GetY());
- }
- if (!IsHistogramDisabled("Zvertex"))
- {
- Histo(physics,triggerClassName,centrality,"Zvertex")->Fill(vertex->GetZ());
- }
- }
-
- if ( !fIsFromESD )
- {
- const AliAODTZERO* tzero = static_cast<const AliAODEvent*>(Event())->GetTZEROData();
-
- if (tzero && !IsHistogramDisabled("T0Zvertex"))
- {
- Histo(physics,triggerClassName,centrality,"T0Zvertex")->Fill(tzero->GetT0VertexRaw());
- }
- }
- else
- {
- const AliESDTZERO* tzero = static_cast<const AliESDEvent*>(Event())->GetESDTZERO();
-
- if (tzero && !IsHistogramDisabled("T0Zvertex"))
- {
- Histo(physics,triggerClassName,centrality,"T0Zvertex")->Fill(tzero->GetT0zVertex());
- }
- }
-
- AliVVZERO* vzero = Event()->GetVZEROData();
-
- if (vzero)
- {
- Float_t v0a = vzero->GetV0ATime();
- Float_t v0c = vzero->GetV0CTime();
-
- Float_t x = v0a-v0c;
- Float_t y = v0a+v0c;
-
- if (!IsHistogramDisabled("V02D"))
- {
- Histo(physics,triggerClassName,centrality,"V02D")->Fill(x,y);
- }
-
- Bool_t background,pileup,satellite;
-
- Bool_t tzero = EAGetTZEROFlags(background,pileup,satellite);
-
- if (tzero)
- {
- if ( background )
- {
- if (!IsHistogramDisabled("V02DwT0BG"))
- {
- Histo(physics,triggerClassName,centrality,"V02DwT0BG")->Fill(x,y);
- }
- }
-
- if ( pileup )
- {
- if (!IsHistogramDisabled("V02DwT0PU"))
- {
- Histo(physics,triggerClassName,centrality,"V02DwT0PU")->Fill(x,y);
- }
- }
-
- if ( satellite )
- {
- if (!IsHistogramDisabled("V02DwT0SAT"))
- {
- Histo(physics,triggerClassName,centrality,"V02DwT0SAT")->Fill(x,y);
- }
- }
-
- if ( !background && !pileup && !satellite )
- {
- if (!IsHistogramDisabled("V02DwT0BB"))
- {
- Histo(physics,triggerClassName,centrality,"V02DwT0BB")->Fill(x,y);
- }
- }
- }
- }
-
- /* FIXME : how to properly get multiplicity from AOD and ESD consistently ?
- is is doable at all ?
- Int_t ntracklets(0);
- AliAODTracklets* tracklets = aod.GetTracklets();
- if ( tracklets )
- {
- ntracklets = tracklets->GetNumberOfTracklets();
- }
- Histo(physics,triggerClassName,centrality,"Tracklets")->Fill(ntracklets);
- */
-
-}
-
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::FillHistogramCollection(const char* physics, const char* triggerClassName)
-{
- /// Actually create the histograms for phyics/triggerClassName
-
- AliDebug(1,Form("(%s,%s)",physics,triggerClassName));
-
- Double_t ptMin = 0;
- Double_t ptMax = 12*3;
- Int_t nbinsPt = GetNbins(ptMin,ptMax,0.5);
- Double_t pMin = 0;
- Double_t pMax = 100*3;
- Int_t nbinsP = GetNbins(pMin,pMax,2.0);
- Double_t etaMin = -5;
- Double_t etaMax = -2;
- Int_t nbinsEta = GetNbins(etaMin,etaMax,0.05);
-
- Double_t rapidityMin = -5;
- Double_t rapidityMax = -2;
- Int_t nbinsRapidity = GetNbins(rapidityMin,rapidityMax,0.05);
-
- Double_t phiMin = -TMath::Pi();
- Double_t phiMax = TMath::Pi();
- Int_t nbinsPhi = GetNbins(phiMin,phiMax,0.05);
-
- CreateSingleHisto(physics,triggerClassName,"Chi2MatchTrigger","Chi2 Match Trigger",72,0,72);
-
- CreateSingleHisto(physics,triggerClassName,"EtaRapidityMu", "Eta distribution vs Rapidity for #mu", nbinsRapidity,rapidityMin,rapidityMax,nbinsEta,etaMin,etaMax, fShouldSeparatePlusAndMinus);
-
- CreateSingleHisto(physics,triggerClassName,"PtEtaMu", "P_{T} distribution vs Eta for #mu", nbinsEta,etaMin,etaMax, nbinsPt,ptMin,ptMax,fShouldSeparatePlusAndMinus);
-
- CreateSingleHisto(physics,triggerClassName,"PtRapidityMu", "P_{T} distribution vs Rapidity for #mu", nbinsRapidity,rapidityMin,rapidityMax, nbinsPt,ptMin,ptMax,fShouldSeparatePlusAndMinus);
-
- CreateSingleHisto(physics,triggerClassName,"PtPhiMu", "P_{T} distribution vs phi for #mu", nbinsPhi,phiMin,phiMax, nbinsPt,ptMin,ptMax,fShouldSeparatePlusAndMinus);
-
-
- CreateSingleHisto(physics,triggerClassName,"PEtaMu", "P distribution for #mu",nbinsEta,etaMin,etaMax,nbinsP,pMin,pMax,fShouldSeparatePlusAndMinus);
-
- Double_t chi2min = 0;
- Double_t chi2max = 20;
- Int_t nbinchi2 = GetNbins(chi2min,chi2max,0.05);
-
- CreateSingleHisto(physics, triggerClassName, "Chi2Mu", "chisquare per NDF #mu", nbinchi2, chi2min, chi2max,fShouldSeparatePlusAndMinus);
-
- CreateMinvHistograms(physics,triggerClassName);
-
- CreatePairHisto(physics,triggerClassName,"Chi12","Chi2MatchTrigger of muon 1 vs muon 2",72,0,72,72,0,72);
- CreatePairHisto(physics,triggerClassName,"Rabs12","Rabs of muon 1 vs muon ",100,0,100,100,0,100);
-
- Double_t xmin = -40;
- Double_t xmax = +40;
- Int_t nbins = GetNbins(xmin,xmax,0.5);
-
- CreateEventHisto(physics,triggerClassName,"Zvertex","z vertex",nbins,xmin,xmax);
-
- CreateEventHisto(physics,triggerClassName,"T0Zvertex","T0 zvertex",nbins,xmin,xmax);
-
- xmin = -5;
- xmax = 5;
- nbins = GetNbins(xmin,xmax,0.01);
-
- CreateEventHisto(physics,triggerClassName,"Xvertex","x vertex",nbins,xmin,xmax);
- CreateEventHisto(physics,triggerClassName,"Yvertex","y vertex",nbins,xmin,xmax);
-
-// CreateEventHisto(physics,triggerClassName,"YXvertex","y vs x vertex",nbins,xmin,xmax,nbins,xmin,xmax);
-
-// if (!fIsFromESD)
-// {
-//
-// CreateEventHisto(physics,triggerClassName,"PileUpZvertex","pileup z vertex",nbins,xmin,xmax);
-//
-// CreateEventHisto(physics,triggerClassName,"PileUpXvertex","pileup x vertex",nbins,xmin,xmax);
-// CreateEventHisto(physics,triggerClassName,"PileUpYvertex","pileup y vertex",nbins,xmin,xmax);
-//
-// CreateEventHisto(physics,triggerClassName,"PileUpYXvertex","pileup y vs x vertex",nbins,xmin,xmax,
-// nbins,xmin,xmax);
-//
-// }
-
- CreateEventHisto(physics,triggerClassName,"Nevents","number of events",2,-0.5,1.5);
-
- xmin = 0;
- xmax = 3564;
- nbins = GetNbins(xmin,xmax,1.0);
-
- CreateEventHisto(physics,triggerClassName,"BCX","bunch-crossing ids",nbins,xmin-0.5,xmax-0.5);
-
- CreateEventHisto(physics,triggerClassName,"BCXD","bunch-crossing distances",nbins,xmin-0.5,xmax-0.5);
-
- xmin = -200;
- xmax = +200;
- nbins = GetNbins(xmin,xmax,1.0);
-
- xmin = 0;
- xmax = 150;
- nbins = GetNbins(xmin,xmax,2.0);
-
- CreateSingleHisto(physics,triggerClassName,"dcaP23Mu","#mu DCA vs P for 2-3 degrees;P (GeV);DCA (cm)",nbinsP,pMin,pMax,nbins,xmin,xmax,fShouldSeparatePlusAndMinus);
-
- CreateSingleHisto(physics,triggerClassName,"dcaP310Mu","#mu DCA vs P for 3-10 degrees;P (GeV);DCA (cm)",nbinsP,pMin,pMax,nbins,xmin,xmax,fShouldSeparatePlusAndMinus);
-
- CreateSingleHisto(physics,triggerClassName,"dcaPwPtCut23Mu","#mu DCA vs P for 2-3 degrees with Pt Cut;P (GeV);DCA (cm)",nbinsP,pMin,pMax,nbins,xmin,xmax,fShouldSeparatePlusAndMinus);
-
- CreateSingleHisto(physics,triggerClassName,"dcaPwPtCut310Mu","#mu DCA vs P for 3-10 degrees with Pt Cut;P (GeV);DCA (cm)",nbinsP,pMin,pMax,nbins,xmin,xmax,fShouldSeparatePlusAndMinus);
-
- xmin = -30;
- xmax = +30;
- nbins = GetNbins(xmin,xmax,0.1);
-
- CreateEventHisto(physics,triggerClassName,"V02D","V0C+V0A versus V0A-V0C;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
-
- CreateEventHisto(physics,triggerClassName,"V02DwT0BB","V0C+V0A versus V0A-V0C with T0 BB;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
-
- CreateEventHisto(physics,triggerClassName,"V02DwT0BG","V0C+V0A versus V0A-V0C with T0 background flag on;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
-
- CreateEventHisto(physics,triggerClassName,"V02DwT0PU","V0C+V0A versus V0A-V0C with T0 pile up flag on;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
-
- CreateEventHisto(physics,triggerClassName,"V02DwT0SAT","V0C+V0A versus V0A-V0C with T0 satellite flag on;Time V0A - V0C (ns);Time V0A+V0C (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
-
- /*
- CreateEventHisto(physics,triggerClassName,"T02D","(T0C+T0A)/2 versus (T0A-T0C)/2;Time (T0A-T0C)/2 (ns);Time (T0A+T0C)/2 (ns)",nbins,xmin,xmax,nbins,xmin,xmax);
- CreateEventHisto(physics,triggerClassName,"T0Flags","T0 flags",3,0,3);
- */
-
-
- if ( !IsHistogramDisabled("Centrality") )
- {
- TH1* h = new TH1F("Centrality","Centrality",12,-10,110);
-
- fHistogramCollection->Adopt(Form("/%s/%s",physics,triggerClassName),h);
- }
-
- xmin = 0;
- xmax = 5000;
- nbins = GetNbins(xmin,xmax,10);
-
- CreateEventHisto(physics,triggerClassName,"Tracklets","Number of tracklets",nbins,xmin,xmax);
-
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::FillHistosForTrack(const char* physics,
- const char* triggerClassName,
- const char* centrality,
- const AliVParticle& track,
- Int_t trackIndex)
-{
- /// Fill histograms for one track
-
-// AliCodeTimerAuto("",0);
-
- TLorentzVector p(track.Px(),track.Py(),track.Pz(),
- TMath::Sqrt(MuonMass2()+track.P()*track.P()));
-
-
- TString charge("");
-
- if ( ShouldSeparatePlusAndMinus() )
- {
- if ( track.Charge() < 0 )
- {
- charge = "Minus";
- }
- else
- {
- charge = "Plus";
- }
- }
-
- UInt_t mask = GetTrackMask(trackIndex);
-
- Double_t dca = EAGetTrackDCA(track);
-
- Double_t theta = AliAnalysisMuonUtility::GetThetaAbsDeg(&track);
-
- TIter next(fSingleTrackCutNames);
- TObjString* str;
-
- while ( ( str = static_cast<TObjString*>(next()) ) )
- {
- Bool_t test = ( ( str->GetUniqueID() & mask ) == str->GetUniqueID() );
-
- if ( test )
- {
- if (!IsHistogramDisabled("Chi2MatchTrigger"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),"Chi2MatchTrigger")->Fill(AliAnalysisMuonUtility::GetChi2MatchTrigger(&track));
- }
-
- if (!IsHistogramDisabled("EtaRapidityMu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("EtaRapidityMu%s",charge.Data()))->Fill(p.Rapidity(),p.Eta());
- }
-
- if (!IsHistogramDisabled("PtEtaMu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("PtEtaMu%s",charge.Data()))->Fill(p.Eta(),p.Pt());
- }
-
- if (!IsHistogramDisabled("PtRapidityMu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("PtRapidityMu%s",charge.Data()))->Fill(p.Rapidity(),p.Pt());
- }
-
- if (!IsHistogramDisabled("PEtaMu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("PEtaMu%s",charge.Data()))->Fill(p.Eta(),p.P());
- }
-
- if (!IsHistogramDisabled("PtPhiMu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("PtPhiMu%s",charge.Data()))->Fill(p.Phi(),p.Pt());
- }
-
- if (!IsHistogramDisabled("Chi2Mu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("Chi2Mu%s",charge.Data()))->Fill(AliAnalysisMuonUtility::GetChi2perNDFtracker(&track));
- }
-
- if ( theta >= 2.0 && theta < 3.0 )
- {
-
- if (!IsHistogramDisabled("dcaP23Mu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("dcaP23Mu%s",charge.Data()))->Fill(p.P(),dca);
- }
-
- if ( p.Pt() > 2 )
- {
- if (!IsHistogramDisabled("dcaPwPtCut23Mu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("dcaPwPtCut23Mu%s",charge.Data()))->Fill(p.P(),dca);
- }
- }
- }
- else if ( theta >= 3.0 && theta < 10.0 )
- {
- if (!IsHistogramDisabled("dcaP310Mu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("dcaP310Mu%s",charge.Data()))->Fill(p.P(),dca);
- }
- if ( p.Pt() > 2 )
- {
- if (!IsHistogramDisabled("dcaPwPtCut310Mu*"))
- {
- Histo(physics,triggerClassName,centrality,str->String().Data(),Form("dcaPwPtCut310Mu%s",charge.Data()))->Fill(p.P(),dca);
- }
- }
- }
- }
- }
-
-
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::FillHistos(const char* physics, const char* triggerClassName,
- const char* centrality)
-{
- /// Fill histograms for /physics/triggerClassName/centrality
-
-// AliCodeTimerAuto("",0);
-
- FillEventHistos(physics,triggerClassName,centrality);
-
- // Track loop
-
- if (!fBinArray)
- {
- fBinArray = fBinning->CreateBinObjArray("psi","y vs pt,integrated,pt,y,phi","");
- }
-
- Int_t nTracks = AliAnalysisMuonUtility::GetNTracks(Event());
-
- for (Int_t i = 0; i < nTracks; ++i)
- {
- AliVParticle* tracki = AliAnalysisMuonUtility::GetTrack(i,Event());
-
- if (!tracki) continue;
-
- FillHistosForTrack(physics,triggerClassName,centrality,*tracki,i);
-
- TLorentzVector pi(tracki->Px(),tracki->Py(),tracki->Pz(),
- TMath::Sqrt(MuonMass2()+tracki->P()*tracki->P()));
-
- for (Int_t j = i+1; j < nTracks; ++j)
- {
- AliVParticle* trackj = AliAnalysisMuonUtility::GetTrack(j,Event());
-
- if (!trackj) continue;
-
- TLorentzVector pj(trackj->Px(),trackj->Py(),trackj->Pz(),
- TMath::Sqrt(MuonMass2()+trackj->P()*trackj->P()));
-
- pj += pi;
-
- TIter next(fPairTrackCutNames);
- AliAnalysisTaskMuMu::PairCut* str;
-
- UInt_t maski(0),maskj(0),maskij(0);
-
- GetPairMask(*tracki,*trackj,i,j,maski,maskj,maskij);
-
- while ( ( str = static_cast<AliAnalysisTaskMuMu::PairCut*>(next()) ) )
- {
- UInt_t singleTrackMask = str->MaskForOneOrBothTrack();
- UInt_t pairMask = str->MaskForTrackPair();
-
- Bool_t testi = ( ( maski & singleTrackMask ) == singleTrackMask ) ;
- Bool_t testj = ( ( maskj & singleTrackMask ) == singleTrackMask ) ;
- Bool_t testij(kTRUE);
-
- if (pairMask>0) testij = ( ( maskij & pairMask ) == pairMask ) ;
-
- if ( ( testi || testj ) && testij )
- {
- if (!IsHistogramDisabled("Chi12"))
- {
- Histo(physics,triggerClassName,centrality,str->GetName(),"Chi12")
- ->Fill(
- AliAnalysisMuonUtility::GetChi2perNDFtracker(tracki),
- AliAnalysisMuonUtility::GetChi2perNDFtracker(trackj));
- }
-
- if (!IsHistogramDisabled("Rabs12"))
- {
- Histo(physics,triggerClassName,centrality,str->GetName(),"Rabs12")
- ->Fill(AliAnalysisMuonUtility::GetRabs(tracki),
- AliAnalysisMuonUtility::GetRabs(trackj));
- }
-
- if ( ( tracki->Charge() != trackj->Charge() ) )
- {
- TIter nextBin(fBinArray);
- AliAnalysisMuMuBinning::Range* r;
-
- Histo(physics,triggerClassName,centrality,str->GetName(),"Pt")->Fill(pj.Pt());
-
- if ( HasMC() )
- {
- Int_t labeli = tracki->GetLabel();
- Int_t labelj = trackj->GetLabel();
-
- if ( labeli < 0 || labelj < 0 )
- {
- AliError("Got negative labels!");
- }
- else
- {
- AliVParticle* mcTracki = MCEvent()->GetTrack(labeli);
- AliVParticle* mcTrackj = MCEvent()->GetTrack(labelj);
-
- TLorentzVector mcpi(mcTracki->Px(),mcTracki->Py(),mcTracki->Pz(),
- TMath::Sqrt(MuonMass2()+mcTracki->P()*mcTracki->P()));
- TLorentzVector mcpj(mcTrackj->Px(),mcTrackj->Py(),mcTrackj->Pz(),
- TMath::Sqrt(MuonMass2()+mcTrackj->P()*mcTrackj->P()));
-
- mcpj += mcpi;
-
- Histo(physics,triggerClassName,centrality,str->GetName(),"PtRecVsSim")->Fill(mcpj.Pt(),pj.Pt());
-
- }
- }
-
- while ( ( r = static_cast<AliAnalysisMuMuBinning::Range*>(nextBin()) ) )
- {
-// AliInfo(Form("%s y %e pt %e ok1 %d ok2 %d",
-// r->AsString().Data(),
-// pj.Rapidity(),
-// pj.Pt(),
-// r->IsInRange(pj.Rapidity(),pj.Pt()),
-// r->IsInRange(pj.Pt(),pj.Rapidity())));
-
-
- Bool_t ok(kFALSE);
-
- if ( r->IsNullObject() )
- {
- ok = kTRUE;
- }
- else if ( r->Is2D() )
- {
- if ( r->AsString().BeginsWith("PTVSY") )
- {
- ok = r->IsInRange(pj.Rapidity(),pj.Pt());
- }
- else if ( r->AsString().BeginsWith("YVSPT") )
- {
- ok = r->IsInRange(pj.Pt(),pj.Rapidity());
- }
- else
- {
- AliError(Form("Don't know how to deal with 2D bin %s",r->AsString().Data()));
- }
- }
- else
- {
- if ( r->Type() == "PT" )
- {
- ok = r->IsInRange(pj.Pt());
- }
- else if ( r->Type() == "Y" )
- {
- ok = r->IsInRange(pj.Rapidity());
- }
- else if ( r->Type() == "PHI" )
- {
- ok = r->IsInRange(pj.Phi());
- }
- }
-
- if ( ok )
- {
- TString hname = GetMinvHistoName(*r);
-
- if (!IsHistogramDisabled(hname.Data()))
- {
- TH1* h = Histo(physics,triggerClassName,centrality,str->GetName(),hname.Data());
-
- if (!h)
- {
- AliError(Form("Could not get %s",hname.Data()));
- }
- h->Fill(pj.M());
- }
- }
- }
-
- }
- }
- }
- }
- } //track loop
-
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::FinishTaskOutput()
-{
- /// prune empty histograms BEFORE mergin, in order to save some bytes...
-
- if ( fHistogramCollection )
- {
- fHistogramCollection->PruneEmptyObjects();
- }
-}
-
-//_____________________________________________________________________________
-UInt_t AliAnalysisTaskMuMu::GetEventMask() const
-{
- /// Compute the event mask
-
- /*
-
- kEventAll = all events
- kEventPS = physics selected events
- kEventTVX = events with 0TVX input present
- kEventV0AND = events with 0VBA and 0VBC present
- kEventV0UP = a check of events within a narrow square range of v0a+c vs v0a-c
- kEventZSPD = events with a vertex computed by SPD
- kEventZ7 = events with | zvertex | < 7cm
- kEventZ10 = events with | zvertex | < 10 cm
- kEventSD2 = events with 0SD2 input present (was for PbPb 2010)
- kEventMSL = events with 0MSL input present
- kEventNOPILEUP = events with the T0 pile-up flag not present
- kEventREJECTED = events not physics selected
- */
-
-// AliCodeTimerAuto("",0);
-
- UInt_t eMask = EventCuts()->GetSelectionMask(fInputHandler);
-
- UInt_t m(AliAnalysisTaskMuMu::kEventAll);
-
- if ( eMask & AliMuonEventCuts::kPhysicsSelected )
- {
- m |= AliAnalysisTaskMuMu::kEventPS;
- }
- else
- {
- m |= AliAnalysisTaskMuMu::kEventREJECTED;
- }
-
- UInt_t trigger = AliAnalysisMuonUtility::GetL0TriggerInputs(Event());
-
- UInt_t l0TVXBIT = GetTriggerInputBitMaskFromInputName("0TVX");
-
- if ( ( trigger & (l0TVXBIT) ) == l0TVXBIT )
- {
- m |= AliAnalysisTaskMuMu::kEventTVX;
- }
-
- UInt_t l0VBABIT = GetTriggerInputBitMaskFromInputName("0VBA");
- UInt_t l0VBCBIT = GetTriggerInputBitMaskFromInputName("0VBC");
-
- if ( ( ( trigger & (l0VBABIT ) ) == l0VBABIT ) &&
- ( ( trigger & (l0VBCBIT ) ) == l0VBCBIT ) )
- {
- m |= AliAnalysisTaskMuMu::kEventV0AND;
- }
-
- UInt_t l0MSLBIT = GetTriggerInputBitMaskFromInputName("0MSL");
-
- if ( ( trigger & (l0MSLBIT) ) == l0MSLBIT )
- {
- m |= AliAnalysisTaskMuMu::kEventMSL;
- }
-
- if ( fBeamYear == "PbPb2010" )
- {
- // consider only events with OSM2 fired
- UInt_t sd2 = GetTriggerInputBitMaskFromInputName("0SM2");
- if ( ( trigger & sd2 ) == sd2 )
- {
- m |= AliAnalysisTaskMuMu::kEventSD2;
- }
- }
-
- // Bool_t hasPileUp = aod->IsPileupFromSPD(3,0.8);
- // Bool_t hasPileUp2 = aod->IsPileupFromSPD(5,0.8);
- // Bool_t isIsolated = ( aod->GetBunchCrossNumber() > 1000 && aod->GetBunchCrossNumber() < 2900 );
-
- // Bool_t hasPileUp2 = aod->IsPileupFromSPDInMultBins();
-
- // TIter nextV(aod->GetVertices());
- // AliAODVertex* v;
- // while ( ( v = static_cast<AliAODVertex*>(nextV())) && !hasPileUp2 )
- // {
- // if ( v->GetType() == AliAODVertex::kPileupSPD ) hasPileUp2 = kTRUE;
- // }
-
- // Bool_t isIsolated = false;//( aod->GetClosestBunchCrossingDistance() > 10 );
-
- const AliVVertex* vertex = Event()->GetPrimaryVertex();
-
- if ( vertex->IsA() == AliAODVertex::Class() )
- {
- AliAODVertex* spdVertex = static_cast<const AliAODEvent*>(Event())->GetPrimaryVertexSPD();
-
- if ( spdVertex && spdVertex->GetNContributors() > 0 )
- {
- m |= AliAnalysisTaskMuMu::kEventZSPD;
- }
- }
-
- if ( TMath::Abs(vertex->GetZ()) < 10.0 )
- {
- m |= AliAnalysisTaskMuMu::kEventZ10;
- }
-
- if ( TMath::Abs(vertex->GetZ()) < 7.0 )
- {
- m |= AliAnalysisTaskMuMu::kEventZ7;
- }
-
-// AliVVZERO* vzero = Event()->GetVZEROData();
-//
-// if (vzero)
-// {
-// Float_t v0a = vzero->GetV0ATime();
-// Float_t v0c = vzero->GetV0CTime();
-//
-// Float_t x = v0a-v0c;
-// Float_t y = v0a+v0c;
-//
-// if ( ( x > 6 && x < 10 ) && y > 20 )
-// {
-// m |= AliAnalysisTaskMuMu::kEventV0UP;
-// }
-// }
-
- Bool_t backgroundFlag(kFALSE);
- Bool_t pileupFlag(kFALSE);
- Bool_t satelliteFlag(kFALSE);
-
- EAGetTZEROFlags(backgroundFlag,pileupFlag,satelliteFlag);
-
- if ( !pileupFlag )
- {
- m |= AliAnalysisTaskMuMu::kEventNOTZEROPILEUP;
- }
-
- int nmu = EAGetNumberOfSelectMuonTracks();
-
- if ( nmu >=1 )
- {
- m |= AliAnalysisTaskMuMu::kEventOFFLINEMUL1;
- }
-
- if ( nmu >=2 )
- {
- m |= AliAnalysisTaskMuMu::kEventOFFLINEMUL2;
- }
-
- return m;
-}
-
-//_____________________________________________________________________________
-UInt_t AliAnalysisTaskMuMu::GetTriggerInputBitMaskFromInputName(const char* inputName) const
-{
- // Get trigger input bit from its name
- // FIXME : this should really come directly from the trigger configuration
- // object, if only this one would be available in a more convenient
- // way than the OCDB (e.g. in RunBasedContainer ?)
- //
-
- if ( fTriggerInputBitMap.empty() )
- {
- // nothing given to us, use the bad bad hard-coded values !
-
- TString sInputName(inputName);
-
- if ( sInputName == "0SM2" ) return (1<<12);
-
-
- if ( sInputName == "0VBA" ) return (1<<0);
- if ( sInputName == "0VBC" ) return (1<<1);
- if ( sInputName == "0SMB" ) return (1<<2);
- if ( sInputName == "0TVX" ) return (1<<3);
- if ( sInputName == "0VGC" ) return (1<<4);
- if ( sInputName == "0VGA" ) return (1<<5);
- if ( sInputName == "0SH1" ) return (1<<6);
- if ( sInputName == "0SH2" ) return (1<<7);
- if ( sInputName == "0HPT" ) return (1<<8);
- if ( sInputName == "0AMU" ) return (1<<9);
- if ( sInputName == "0OB0" ) return (1<<10);
- if ( sInputName == "0ASL" ) return (1<<11);
-
- /*
- if ( sInputName == "0MSL" ) return (1<<12);
-
-// if ( sInputName == "0MSH" ) return (1<<13);
- if ( sInputName == "0MSH" ) return (1<<8);
-
- if ( sInputName == "0MUL" ) return (1<<14);
- if ( sInputName == "0MLL" ) return (1<<15);
- */
-
- if ( sInputName == "0MSL") return (1<<12);
- if ( sInputName == "0MSH") return (1<<13);
- if ( sInputName == "0MUL") return (1<<14);
- if ( sInputName == "0MLL") return (1<<15);
-
- if ( sInputName == "0EMC" ) return (1<<16);
- if ( sInputName == "0PH0" ) return (1<<17);
- if ( sInputName == "0HWU" ) return (1<<18);
- if ( sInputName == "0LSR" ) return (1<<19);
- if ( sInputName == "0T0A" ) return (1<<20);
- if ( sInputName == "0BPA" ) return (1<<21);
- if ( sInputName == "0BPC" ) return (1<<22);
- if ( sInputName == "0T0C" ) return (1<<23);
+void AliAnalysisTaskMuMu::Fill(const char* eventSelection, const char* triggerClassName)
+{
+ // Fill one set of histograms (only called for events which pass the eventSelection cut)
+
+ TString seventSelection(eventSelection);
+ seventSelection.ToLower();
+
+ fEventCounters->Count(Form("event:%s/trigger:%s/centrality:%s/run:%d", seventSelection.Data(), triggerClassName, "ALL", fCurrentRunNumber));
- if ( sInputName == "1EJE" ) return (1<<0);
- if ( sInputName == "1EGA" ) return (1<<1);
- if ( sInputName == "1EJ2" ) return (1<<2);
- if ( sInputName == "1EG2" ) return (1<<3);
- if ( sInputName == "1PHL" ) return (1<<4);
- if ( sInputName == "1PHM" ) return (1<<5);
- if ( sInputName == "1PHH" ) return (1<<6);
- if ( sInputName == "1HCO" ) return (1<<8);
- if ( sInputName == "1HJT" ) return (1<<9);
- if ( sInputName == "1HSE" ) return (1<<10);
- if ( sInputName == "1DUM" ) return (1<<11);
- if ( sInputName == "1HQU" ) return (1<<12);
- if ( sInputName == "1H14" ) return (1<<13);
- if ( sInputName == "1ZMD" ) return (1<<14);
- if ( sInputName == "1ZMB" ) return (1<<16);
- if ( sInputName == "1ZED" ) return (1<<17);
- if ( sInputName == "1ZAC" ) return (1<<18);
- if ( sInputName == "1EJE" ) return (1<<19);
+ if ( !IsHistogrammingDisabled() )
+ {
+ TObjArray* centralities = fBinning->CreateBinObjArray("centrality");
- AliError(Form("Don't know this input %s",inputName));
+ TIter next(centralities);
+ AliAnalysisMuMuBinning::Range* r;
- return (1<<31);
- }
- else
- {
- std::map<std::string,int>::const_iterator it = fTriggerInputBitMap.find(inputName);
- if ( it != fTriggerInputBitMap.end() )
+ while ( ( r = static_cast<AliAnalysisMuMuBinning::Range*>(next()) ) )
{
- return ( 1 << it->second );
- }
- else
- {
- AliError(Form("Don't know this input %s",inputName));
+ TString estimator = r->Quantity();
- return (1<<31);
+ Float_t fcent = Event()->GetCentrality()->GetCentralityPercentile(estimator.Data());
+ if ( fcent < 0.) FillHistos(eventSelection,triggerClassName,"MV0");
+ if ( fcent == 0.) FillHistos(eventSelection,triggerClassName,"0V0");
+ if ( r->IsInRange(fcent) )
+ {
+ FillHistos(eventSelection,triggerClassName,r->AsString());
+ }
}
+ delete centralities;
}
}
//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::GetPairMask(const AliVParticle& t1, const AliVParticle& t2,
- Int_t trackIndex1, Int_t trackIndex2,
- UInt_t& mask1, UInt_t& mask2,
- UInt_t& mask12) const
+void AliAnalysisTaskMuMu::FillHistos(const char* eventSelection,
+ const char* triggerClassName,
+ const char* centrality)
{
- /// Get the mask of the track pair
+ /// Fill histograms for /physics/triggerClassName/centrality
- mask1 = GetTrackMask(trackIndex1);
- mask2 = GetTrackMask(trackIndex2);
+ AliCodeTimerAuto("",0);
- mask12 = mask1 & mask2;
+ TIter nextAnalysis(fSubAnalysisVector);
+ AliAnalysisMuMuBase* analysis;
- if ( PairRapidityCut(t1,t2) ) mask12 |= kPairRapidity;
-}
-
-//_____________________________________________________________________________
-UInt_t AliAnalysisTaskMuMu::GetTrackMask(Int_t trackIndex) const
-{
- /// Get the mask of all the cuts this track pass
+ Int_t nTracks = AliAnalysisMuonUtility::GetNTracks(Event());
- return static_cast<UInt_t>(fPrecomputedTrackMasks.At(trackIndex));
-}
+ fEventCounters->Count(Form("event:%s/trigger:%s/centrality:%s/run:%d", eventSelection, triggerClassName, centrality, fCurrentRunNumber));
+
+ TIter nextTrackCut(fCutRegistry->GetCutCombinations(AliAnalysisMuMuCutElement::kTrack));
+ TIter nextPairCut(fCutRegistry->GetCutCombinations(AliAnalysisMuMuCutElement::kTrackPair));
+
+ // loop on single tracks (whatever the type of tracks
+ while ( ( analysis = static_cast<AliAnalysisMuMuBase*>(nextAnalysis()) ) )
+ {
+ analysis->DefineHistogramCollection(eventSelection,triggerClassName,centrality);
+
+ AliCodeTimerAuto(Form("%s (FillHistosForEvent)",analysis->ClassName()),1);
-//_____________________________________________________________________________
-TH1* AliAnalysisTaskMuMu::Histo(const char* physics, const char* triggerClassName, const char* histoname)
-{
- /// Get one histo back
- return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s",physics,triggerClassName,histoname)) : 0x0;
-}
+ if ( MCEvent() != 0x0 )
+ {
+ analysis->FillHistosForMCEvent(eventSelection,triggerClassName,centrality);
+ }
-//_____________________________________________________________________________
-TH1* AliAnalysisTaskMuMu::Histo(const char* physics, const char* histoname)
-{
- /// Get one histo back
- return fHistogramCollection ? fHistogramCollection->Histo(physics,histoname) : 0x0;
+ analysis->FillHistosForEvent(eventSelection,triggerClassName,centrality);
+
+ for (Int_t i = 0; i < nTracks; ++i)
+ {
+ AliVParticle* tracki = AliAnalysisMuonUtility::GetTrack(i,Event());
+
+ nextTrackCut.Reset();
+ AliAnalysisMuMuCutCombination* trackCut;
+
+ while ( ( trackCut = static_cast<AliAnalysisMuMuCutCombination*>(nextTrackCut()) ) )
+ {
+ if ( trackCut->Pass(*tracki) )
+ {
+ analysis->FillHistosForTrack(eventSelection,triggerClassName,centrality,trackCut->GetName(),*tracki);
+ }
+ }
+
+ if (!AliAnalysisMuonUtility::IsMuonTrack(tracki) ) continue;
+
+ // loop on track pairs (here we only consider muon pairs)
+
+ for (Int_t j = i+1; j < nTracks; ++j)
+ {
+ AliVParticle* trackj = AliAnalysisMuonUtility::GetTrack(j,Event());
+
+ if (!AliAnalysisMuonUtility::IsMuonTrack(trackj) ) continue;
+
+ nextPairCut.Reset();
+ AliAnalysisMuMuCutCombination* pairCut;
+
+ while ( ( pairCut = static_cast<AliAnalysisMuMuCutCombination*>(nextPairCut()) ) )
+ {
+ Bool_t testi = (pairCut->IsTrackCutter()) ? pairCut->Pass(*tracki) : kTRUE;
+ Bool_t testj = (pairCut->IsTrackCutter()) ? pairCut->Pass(*trackj) : kTRUE;
+ Bool_t testij = pairCut->Pass(*tracki,*trackj);
+
+ if ( ( testi || testj ) && testij )
+ {
+ analysis->FillHistosForPair(eventSelection,triggerClassName,centrality,pairCut->GetName(),*tracki,*trackj);
+ }
+ }
+ }
+ }
+ }
}
//_____________________________________________________________________________
-TH1* AliAnalysisTaskMuMu::Histo(const char* physics,
- const char* triggerClassName,
- const char* what,
- const char* histoname)
+void AliAnalysisTaskMuMu::FinishTaskOutput()
{
- /// Get one histo back
- return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s",physics,triggerClassName,what),histoname) : 0x0;
+ /// prune empty histograms BEFORE mergin, in order to save some bytes...
+
+ if ( fHistogramCollection )
+ {
+ fHistogramCollection->PruneEmptyObjects();
+ }
}
//_____________________________________________________________________________
-TH1* AliAnalysisTaskMuMu::Histo(const char* physics,
- const char* triggerClassName,
- const char* cent,
- const char* what,
- const char* histoname)
+void AliAnalysisTaskMuMu::GetSelectedTrigClassesInEvent(const AliVEvent* event, TObjArray& array)
{
- /// Get one histo back
+ /// Fills the array with a list of TObjString of the trigger classes that the various
+ /// cuts accept for this event
+
+ array.Clear();
+
+ if (!event)
+ {
+ AliError("Will get a hard time selecting trigger classes with an empty event...");
+ return;
+ }
+
+ TString firedTriggerClasses = event->GetFiredTriggerClasses();
+ UInt_t l0 = AliAnalysisMuonUtility::GetL0TriggerInputs(event);
+ UInt_t l1 = AliAnalysisMuonUtility::GetL1TriggerInputs(event);
+ UInt_t l2 = AliAnalysisMuonUtility::GetL2TriggerInputs(event);
- return fHistogramCollection ? fHistogramCollection->Histo(Form("/%s/%s/%s/%s",physics,triggerClassName,cent,what),histoname) : 0x0;
+ std::set<std::string> tmpArray;
+
+ TIter nextCutCombination(CutRegistry()->GetCutCombinations(AliAnalysisMuMuCutElement::kTriggerClass));
+ AliAnalysisMuMuCutCombination* cutCombination;
+
+ while ( ( cutCombination = static_cast<AliAnalysisMuMuCutCombination*>(nextCutCombination()) ) )
+ {
+ TString acceptedTriggerClasses;
+
+ if ( cutCombination->Pass(firedTriggerClasses,acceptedTriggerClasses,l0,l1,l2) )
+ {
+ TObjArray* split = acceptedTriggerClasses.Tokenize(" ");
+ TIter next(split);
+ TObjString* str;
+ while ( ( str = static_cast<TObjString*>(next()) ) )
+ {
+ tmpArray.insert(str->String().Data());
+ }
+ delete split;
+ }
+ }
+
+ std::set<std::string>::const_iterator it;
+
+ for ( it = tmpArray.begin(); it != tmpArray.end(); ++it )
+ {
+ array.Add(new TObjString(it->c_str()));
+ }
}
+
//_____________________________________________________________________________
Bool_t AliAnalysisTaskMuMu::IsHistogramDisabled(const char* hname) const
{
/// Whether or not a given histogram (identified by its name)
/// is disabled or not
- if ( !fHistogramToDisable )
- {
- return kFALSE;
- }
- TString shname(hname);
- TIter next(fHistogramToDisable);
- TObjString* str(0x0);
- while ( ( str = static_cast<TObjString*>(next()) ) )
+ TIter next(fSubAnalysisVector);
+ AliAnalysisMuMuBase* analysis;
+
+ while ( ( analysis = static_cast<AliAnalysisMuMuBase*>(next()) ) )
{
- if ( shname.Contains(TRegexp(str->String()) ) )
+ if ( analysis->IsHistogramDisabled(hname) )
{
return kTRUE;
}
}
+
return kFALSE;
}
{
/// Whether or not *all* histograms are disabled
- if ( fHistogramToDisable && fHistogramToDisable->GetEntries()==1 )
+ Bool_t disabled(kTRUE);
+
+ TIter next(fSubAnalysisVector);
+ AliAnalysisMuMuBase* analysis;
+
+ while ( ( analysis = static_cast<AliAnalysisMuMuBase*>(next()) ) )
{
- TObjString* r = static_cast<TObjString*>(fHistogramToDisable->First());
- if ( r->String() == "*" )
- {
- return kTRUE;
- }
+ disabled = disabled && analysis->IsHistogrammingDisabled();
}
- return kFALSE;
+
+ return disabled;
}
//_____________________________________________________________________________
return fBeamYear.Contains("pp");
}
-//_____________________________________________________________________________
-//void AliAnalysisTaskMuMu::MergeCentralities(AliHistogramCollection* histogramCollection)
-//{
- /// FIXME : Reimplement using AliMergeableCollection::GetSum ?
-
- /// Merge CENT10 + CENT20 + ... into CENTMB
-
-// TList* listA = histogramCollection->CreateListOfKeysA();
-// TList* listB = histogramCollection->CreateListOfKeysB();
-// TList* listC = histogramCollection->CreateListOfKeysC();
-// TList* listD = histogramCollection->CreateListOfKeysD();
-//
-// if (!listA)
-// {
-// AliErrorClass("listA=0x0");
-// return;
-// }
-//
-// if (!listB)
-// {
-// AliErrorClass("listB=0x0");
-// return;
-// }
-//
-// if (!listC)
-// {
-// AliErrorClass("listC=0x0");
-// return;
-// }
-//
-// if (!listD)
-// {
-// AliErrorClass("listD=0x0");
-// return;
-// }
-//
-// for ( Int_t id = 0; id <= listD->GetLast(); ++id )
-// {
-// TString keyD = static_cast<TObjString*>(listD->At(id))->String();
-//
-// for ( Int_t ia = 0; ia <= listA->GetLast(); ++ia )
-// {
-// TString keyA = static_cast<TObjString*>(listA->At(ia))->String();
-//
-// for ( Int_t ib = 0; ib <= listB->GetLast(); ++ib )
-// {
-// TString keyB = static_cast<TObjString*>(listB->At(ib))->String();
-//
-// TList* list = new TList;
-// list->SetOwner(kTRUE);
-//
-// AliHistogramCollection* hmerge(0x0);
-//
-// for ( Int_t ic = 0; ic <= listC->GetLast(); ++ic )
-// {
-// TString keyC = static_cast<TObjString*>(listC->At(ic))->String();
-//
-// if ( keyC != "CENTX" && keyC != "CENTMB" )
-// {
-// AliHistogramCollection* hc = histogramCollection->Project(keyA.Data(),keyB.Data(),keyC.Data(),keyD.Data());
-// if (!hmerge)
-// {
-// hmerge = hc;
-// }
-// else
-// {
-// list->Add(hc);
-// }
-// }
-// }
-// if (hmerge)
-// {
-// hmerge->Merge(list);
-// TIter next(hmerge->CreateIterator());
-// TH1* h;
-// while ( ( h = static_cast<TH1*>(next()) ) )
-// {
-// histogramCollection->Adopt(keyA.Data(),keyB.Data(),"CENTMB",keyD.Data(),static_cast<TH1*>(h->Clone()));
-// }
-// }
-// delete list;
-// delete hmerge;
-// }
-// }
-// }
-//
-// delete listA;
-// delete listB;
-// delete listC;
-// delete listD;
-//}
-
-//_____________________________________________________________________________
-Double_t AliAnalysisTaskMuMu::MuonMass2() const
-{
- /// A usefull constant
- static Double_t m2 = 1.11636129640000012e-02; // using a constant here as the line below is a problem for CINT...
- // static Double_t m2 = TDatabasePDG::Instance()->GetParticle("mu-")->Mass()*TDatabasePDG::Instance()->GetParticle("mu-")->Mass();
- return m2;
-}
-
//_____________________________________________________________________________
void AliAnalysisTaskMuMu::NotifyRun()
{
AliDebug(1,Form("Run %09d File %s",fCurrentRunNumber,CurrentFileName()));
- MuonTrackCuts()->SetRun(fInputHandler);
-}
-
-//_____________________________________________________________________________
-Bool_t AliAnalysisTaskMuMu::PairRapidityCut(const AliVParticle& t1, const AliVParticle& t2) const
-{
- /// Whether the pair passes the rapidity cut
-
- TLorentzVector p1(t1.Px(),t1.Py(),t1.Pz(),TMath::Sqrt(MuonMass2()+t1.P()*t1.P()));
- TLorentzVector p2(t2.Px(),t2.Py(),t2.Pz(),TMath::Sqrt(MuonMass2()+t2.P()*t2.P()));
+ TIter next(fSubAnalysisVector);
+ AliAnalysisMuMuBase* analysis;
- TLorentzVector total(p1+p2);
-
- Double_t y = total.Rapidity();
-
- return ( y < -2.5 && y > -4.0 );
+ while ( ( analysis = static_cast<AliAnalysisMuMuBase*>(next()) ) )
+ {
+ analysis->SetRun(fInputHandler);
+ }
}
//_____________________________________________________________________________
void
-AliAnalysisTaskMuMu::Print(Option_t* /*opt*/) const
+AliAnalysisTaskMuMu::Print(Option_t* opt) const
{
/// Print the definition of this analysis
cout << ClassName() << " - " << GetName() << " - " << fBeamYear.Data() << endl;
+
+ TIter next(fSubAnalysisVector);
+ AliAnalysisMuMuBase* analysis;
- if ( !fSingleTrackCutNames || !fSingleTrackCutNames )
- {
- cout << "No single track cut defined yet" << endl;
- }
- else
- {
- TIter next(fSingleTrackCutNames);
- TObjString* str;
-
- while ( ( str = static_cast<TObjString*>(next()) ) )
- {
- cout << Form("SINGLE CUT %20s MASK %x",str->String().Data(),str->GetUniqueID()) << endl;
- }
- }
-
- if ( !fPairTrackCutNames || !fPairTrackCutNames )
- {
- cout << "No track pair cut defined yet" << endl;
- }
- else
+ while ( ( analysis = static_cast<AliAnalysisMuMuBase*>(next()) ) )
{
- TIter next2(fPairTrackCutNames);
- AliAnalysisTaskMuMu::PairCut* str;
-
- while ( ( str = static_cast<AliAnalysisTaskMuMu::PairCut*>(next2()) ) )
- {
- str->Print();
- }
+ analysis->Print(opt);
}
- if ( !fEventCutNames )
- {
- cout << "No event cut defined yet" << endl;
- }
- else
- {
- TIter nextEventCutName(fEventCutNames);
- TObjString* eventCutName;
-
- while ( ( eventCutName = static_cast<TObjString*>(nextEventCutName()) ) )
- {
- cout << Form("EVENT CUT %s MASK %x",eventCutName->String().Data(),eventCutName->GetUniqueID()) << endl;
- }
- }
+ fCutRegistry->Print("ALL");
if ( fBinning )
{
- cout << "Binning for Minv plots" << endl;
+ cout << "Binning" << endl;
fBinning->Print();
}
}
//_____________________________________________________________________________
void
-AliAnalysisTaskMuMu::Terminate(Option_t *)
+AliAnalysisTaskMuMu::Terminate(Option_t* opt)
{
/// Called once at the end of the query
/// Just a simple printout of the stat we analyse and how many histograms
/// we got
+ TIter next(fSubAnalysisVector);
+ AliAnalysisMuMuBase* analysis;
+
+ while ( ( analysis = static_cast<AliAnalysisMuMuBase*>(next()) ) )
+ {
+ analysis->Terminate(opt);
+ }
+
fHistogramCollection = dynamic_cast<AliMergeableCollection*>(GetOutputData(1));
if (!fHistogramCollection)
{
AliError("Could not find back histogram collection in output...");
- return;
}
-
- fHistogramCollection->PruneEmptyObjects();
-
- UInt_t size2 = fHistogramCollection->EstimateSize();
+ else
+ {
+ // Removes empty objects and also the event histos of the Nch task
+ fHistogramCollection->PruneEmptyObjects();
+
+ UInt_t size2 = fHistogramCollection->EstimateSize();
- AliInfo(Form("size after prune histograms = %5.1f MB",size2/1024.0/1024.0));
-
-// if ( !IsPP() && fCentralityLimits.size() > 1 )
-// {
-// MergeCentralities(fHistogramCollection);
-// }
+ TIter nextHistogram(fHistogramCollection->CreateIterator());
+ TObject* object;
+
+ while ( ( object = nextHistogram() ) )
+ {
+ if ( object->IsA()->InheritsFrom(TH1::Class()) )
+ {
+ TH1* h = static_cast<TH1*>(object);
+ if ( h->GetXaxis()->GetLabels() )
+ {
+ h->LabelsDeflate("X");
+ }
+ }
+ }
+
+ AliInfo(Form("size after prune histograms = %5.1f MB",size2/1024.0/1024.0));
- BeautifyHistos();
-
- fHistogramCollection->Print("^MinvUS$");
+ fHistogramCollection->Print("-");
+ }
fEventCounters = dynamic_cast<AliCounterCollection*>(GetOutputData(2));
if (!fEventCounters)
{
AliError("Could not find back counters in output...");
- return;
}
-
- fEventCounters->Print("trigger");
+ else
+ {
+ fEventCounters->Print("trigger/event");
+ }
// post param container(s)
PostData(3,fBinning);
}
//_____________________________________________________________________________
-Bool_t AliAnalysisTaskMuMu::TriggerSBACECondition(const TString& triggerName) const
+AliAnalysisMuMuBinning* AliAnalysisTaskMuMu::Binning() const
{
- // check the beam condition in the trigger name
+ // Return our binning (making a default one if not already created
+ if ( fBinning ) return fBinning;
- if ( triggerName.Contains("-S-") ) return kTRUE;
-
- if ( triggerName.Contains("-B-") ) return kTRUE;
-
- if ( fUseBackgroundTriggers )
- {
- if ( triggerName.Contains("-ACE-") ) return kTRUE;
- }
- return kFALSE;
+ fBinning = new AliAnalysisMuMuBinning("BIN");
+
+ return fBinning;
}
//_____________________________________________________________________________
{
/// Executed at each event
-// AliCodeTimerAuto("",0);
-
- fHasMC = (MCEvent()!=0x0);
-
- if ( HasMC() )
- {
- MuonTrackCuts()->SetIsMC();
- }
-
- TString firedTriggerClasses(AliAnalysisMuonUtility::GetFiredTriggerClasses(Event()));
-
- TString centrality(DefaultCentralityName());
-
- Float_t fcent(EventCuts()->GetCentrality(Event()));
+// static Int_t n(0);
+// AliInfo(Form("EVENT %10d Event()=%p MCEvent()=%p",n,Event(),MCEvent()));
+// ++n;
+//
+ AliCodeTimerAuto("",0);
- Double_t cent(-100);
+ Binning(); // insure we have a binning...
- if ( fcent > 0 )
+ // if ( MCEvent() )
+ // {
+ TIter nextAnalysis(fSubAnalysisVector);
+ AliAnalysisMuMuBase* analysis;
+ while ( ( analysis = static_cast<AliAnalysisMuMuBase*>(nextAnalysis()) ) )
{
-// for ( std::vector<double>::size_type i = 0 ; i < fCentralityLimits.size() && cent < 0 ; ++i )
-// {
-// if ( fcent < fCentralityLimits[i] )
-// {
-// cent = fCentralityLimits[i];
-// }
-// }
+ if ( MCEvent() ) // Set the MC flag for all analysis (prior to call anything from them
+ // (e.g. any trigger class selection that might behave differently for
+ // MC and real trigger classes)
+ {
+ analysis->SetMC();
+ }
+ analysis->SetEvent(Event(),MCEvent()); // Set the new event properties derived in the analysis
}
+ // }
- if ( cent > -1 )
- {
- centrality = CentralityName(cent);
- }
- int nmu = EAGetNumberOfMuonTracks();
+ TString firedTriggerClasses(AliAnalysisMuonUtility::GetFiredTriggerClasses(Event()));
- EAComputeTrackMasks();
-
// first loop to count things not associated to a specific trigger
- TIter nextEventCut(fEventCutNames);
- TObjString* et;
+ TIter nextEventCutCombination(CutRegistry()->GetCutCombinations(AliAnalysisMuMuCutElement::kEvent));
+ AliAnalysisMuMuCutCombination* cutCombination;
- UInt_t mask = GetEventMask();
-
-// TString eventType;
-// eventType.Form("EVENTTYPE%d",event->GetEventType());
-
- while ( ( et = static_cast<TObjString*>(nextEventCut()) ) )
+ while ( ( cutCombination = static_cast<AliAnalysisMuMuCutCombination*>(nextEventCutCombination())))
{
- Bool_t test = ( ( et->GetUniqueID() & mask ) == et->GetUniqueID() );
-
- if ( test )
+ if ( cutCombination->Pass(*fInputHandler) )
{
- fEventCounters->Count(Form("event:%s/trigger:%s/run:%d", et->String().Data(), "EVERYTHING", fCurrentRunNumber));
+ fEventCounters->Count(Form("event:%s/trigger:%s/centrality:%s/run:%d", cutCombination->GetName(), "EVERYTHING", "ALL", fCurrentRunNumber));
- if ( HasMC() )
- {
- fEventCounters->Count(Form("event:%s/trigger:%s/run:%d", et->String().Data(), "HASMC", fCurrentRunNumber));
- }
-
if ( firedTriggerClasses == "" )
{
- fEventCounters->Count(Form("event:%s/trigger:%s/run:%d", et->String().Data(), "EMPTY", fCurrentRunNumber));
- }
-
- if (nmu)
- {
- fEventCounters->Count(Form("event:%s/trigger:%s/run:%d", et->String().Data(), "ATLEASTONEMUONTRACK", fCurrentRunNumber));
- }
-
- if ( AtLeastOneMuonTrigger(firedTriggerClasses) )
- {
- fEventCounters->Count(Form("event:%s/trigger:%s/run:%d", et->String().Data(), "ATLEASTONEMUONTRIGGER", fCurrentRunNumber));
- if ( AtLeastOneMBTrigger(firedTriggerClasses) )
- {
- fEventCounters->Count(Form("event:%s/trigger:%s/run:%d", et->String().Data(), "ATLEASTONEMUONORMBTRIGGER", fCurrentRunNumber));
- }
- }
-
- if ( AtLeastOneMBTrigger(firedTriggerClasses) )
- {
- fEventCounters->Count(Form("event:%s/trigger:%s/run:%d", et->String().Data(), "ATLEASTONEMBTRIGGER", fCurrentRunNumber));
+ fEventCounters->Count(Form("event:%s/trigger:%s/centrality:%s/run:%d", cutCombination->GetName(), "EMPTY", "ALL", fCurrentRunNumber));
}
}
}
// second loop to count only the triggers we're interested in
+ TObjArray selectedTriggerClasses;
- TIter next(EventCuts()->GetSelectedTrigClassesInEvent(Event()));
- TObjString* tname;
+ GetSelectedTrigClassesInEvent(Event(),selectedTriggerClasses);
+ TIter next(&selectedTriggerClasses);
+ TObjString* tname;
+// Bool_t hasSetEventBeenCalled(kFALSE);
+
while ( ( tname = static_cast<TObjString*>(next()) ) )
{
- nextEventCut.Reset();
-
- while ( ( et = static_cast<TObjString*>(nextEventCut()) ) )
+ nextEventCutCombination.Reset();
+
+ while ( ( cutCombination = static_cast<AliAnalysisMuMuCutCombination*>(nextEventCutCombination())) )
{
- Bool_t test = ( ( et->GetUniqueID() & mask ) == et->GetUniqueID() );
-
- if ( test )
+ if ( cutCombination->Pass(*fInputHandler) )
{
- Fill(et->String().Data(),tname,centrality,fcent);
+// if (!hasSetEventBeenCalled)
+// {
+// TIter nextAnalysis(fSubAnalysisVector);
+// AliAnalysisMuMuBase* analysis;
+//
+// while ( ( analysis = static_cast<AliAnalysisMuMuBase*>(nextAnalysis()) ) )
+// {
+// analysis->SetEvent(Event(),MCEvent());
+// }
+// hasSetEventBeenCalled = kTRUE;
+// }
+ Fill(cutCombination->GetName(),tname->String().Data());
}
}
}
-
- FillMC();
// Post output data.
PostData(1, fHistogramCollection);
//_____________________________________________________________________________
void AliAnalysisTaskMuMu::UserCreateOutputObjects()
{
- // Create histograms
- // Called once
+ /// Create histograms
+ /// Called once
OpenFile(1);
- fHistogramCollection = new AliMergeableCollection("MC");
+ AliInfo(Form("fCutRegistry=%p",fCutRegistry));
- // initialize event counters
+ if ( fCutRegistry )
+ {
+ fCutRegistry->Print();
+ }
+
+ fHistogramCollection = new AliMergeableCollection("OC");
+
fEventCounters = new AliCounterCollection("CC");
- TIter nextEventCutName(fEventCutNames);
- TObjString* str;
+ // initialize event counters
+
TString eventRubric;
- while ( ( str = static_cast<TObjString*>(nextEventCutName()) ) )
+ TIter next(CutRegistry()->GetCutCombinations(AliAnalysisMuMuCutElement::kEvent));
+ AliAnalysisMuMuCutCombination* cutCombination;
+
+ while ( ( cutCombination = static_cast<AliAnalysisMuMuCutCombination*>(next())) )
{
- if ( eventRubric.Length() > 0 ) eventRubric += "/";
- eventRubric += str->String();
+ TString cutName = cutCombination->GetName();
+ if ( eventRubric.Length() > 0 ) eventRubric += "/";
+ eventRubric += cutName;
}
fEventCounters->AddRubric("event", eventRubric.Data());
fEventCounters->AddRubric("trigger", 100);
+ fEventCounters->AddRubric("centrality", 100);
+
fEventCounters->AddRubric("run", 1000000);
+ // Initialize our subtasks, if any...
+
+ TIter nextAnalysis(fSubAnalysisVector);
+ AliAnalysisMuMuBase* analysis;
+
+ while ( ( analysis = static_cast<AliAnalysisMuMuBase*>(nextAnalysis()) ) )
+ {
+ analysis->Init(*fEventCounters,*fHistogramCollection,*fBinning,*fCutRegistry);
+ }
+
+ // finally end the counters initialization
fEventCounters->Init();
// Post output data.
PostData(2,fEventCounters);
PostData(3,fBinning);
}
-
-//_____________________________________________________________________________
-AliMuonTrackCuts* AliAnalysisTaskMuMu::MuonTrackCuts()
-{
- if (!fMuonTrackCuts)
- {
- fMuonTrackCuts = new AliMuonTrackCuts;
-
- fMuonTrackCuts->SetAllowDefaultParams(kTRUE);
-
- fMuonTrackCuts->SetFilterMask(AliMuonTrackCuts::kMuEta |
- AliMuonTrackCuts::kMuThetaAbs |
- AliMuonTrackCuts::kMuPdca |
- AliMuonTrackCuts::kMuMatchApt |
- AliMuonTrackCuts::kMuMatchLpt |
- AliMuonTrackCuts::kMuMatchHpt |
- AliMuonTrackCuts::kMuTrackChiSquare);
-
- }
-
- return fMuonTrackCuts;
-}
-
-//_____________________________________________________________________________
-void AliAnalysisTaskMuMu::SetMuonTrackCuts(const AliMuonTrackCuts& trackCuts)
-{
- delete fMuonTrackCuts;
- fMuonTrackCuts = static_cast<AliMuonTrackCuts*>(trackCuts.Clone());
-}
#ifndef ALIANALYSISTASKMUMU_H
#define ALIANALYSISTASKMUMU_H
-//
-// AliAnalysisTaskMuMu : base class for mu pairs analysis
-// Contains common things for ESD-based and AOD-based analysis
-//
-// author: L. Aphecetche (Subatech)
-//
+/**
+ * \defgroup pwg-muon-mumu pwg-muon-mumu
+ *
+ * \brief Small sub-framework to analyse muon pairs and more...
+ *
+ * Started as a simple invariant mass analysis and grew into a bit more general thing...
+ *
+ * Can now compute the charged particle multiplicy (from SPD tracklets only) in order
+ * to be able to correlate it with e.g. J/psi or single mu.
+ */
+
+/**
+ * \ingroup pwg-muon-mumu
+ *
+ * \class AliAnalysisTaskMuMu
+ *
+ * \brief Steering class for mu pairs analysis (and more...)
+ *
+ * This class acts as a small sub-framework to steer various sub-analysis which
+ * share the same MergeableCollection and the same CounterCollection.
+ *
+ * \author: L. Aphecetche (Subatech)
+ */
#ifndef ALIANALYSISTASKSE_H
# include "AliAnalysisTaskSE.h"
#endif
-#include <set>
-#include <vector>
-
-#ifndef ROOT_TArrayI
-# include "TArrayI.h"
-#endif
-
#ifndef ROOT_TMath
# include "TMath.h"
#endif
class AliAnalysisMuMuBinning;
class AliCounterCollection;
class AliMergeableCollection;
-class AliMuonTrackCuts;
-class AliMuonEventCuts;
class AliVParticle;
-class TArrayF;
class TList;
class TObjArray;
+class AliAnalysisMuMuBase;
+class AliAnalysisMuMuCutRegistry;
class AliAnalysisTaskMuMu : public AliAnalysisTaskSE
{
public:
-
- enum ETrackCut
- {
- kAll=BIT(0),
- kPt1=BIT(1),
- kRabs=BIT(2),
- kMatched=BIT(3),
- kMatchedLow=BIT(4),
- kMatchedHigh=BIT(5),
- kEta=BIT(6),
- kChi2=BIT(7),
- kDCA=BIT(8),
- kPairRapidity=BIT(9),
- kBelowPt=BIT(10),
- kPt1dot2=BIT(11),
- kPt1dot5=BIT(12),
- kPt2=BIT(13),
- kDeg23=BIT(14),
- kDeg310=BIT(15),
- kP10=BIT(16),
- kChi2MatchTrigger=BIT(17)
- };
-
- enum EEventCut
- {
- kEventAll=BIT(0),
- kEventPS=BIT(1),
- kEventTVX=BIT(2),
- kEventV0AND=BIT(3),
- kEventV0UP=BIT(4),
- kEventZSPD=BIT(5),
- kEventZ7=BIT(7),
- kEventNOTZEROPILEUP=BIT(8),
- kEventOFFLINEMUL1=BIT(9),
- kEventZ10=BIT(10),
- kEventOFFLINEMUL2=BIT(11),
- kEventSD2=BIT(16),
- kEventMSL=BIT(17),
- kEventREJECTED=BIT(18),
- kEventPSTS=BIT(19)
- };
-
AliAnalysisTaskMuMu();
- AliAnalysisTaskMuMu(Bool_t fromESD, TList* triggerClassesToConsider, const char* beamYear=0x0, TArrayF* centralities=0x0);
- AliAnalysisTaskMuMu(Bool_t fromESD, const char* beamYear, TArrayF* centralities=0x0);
virtual ~AliAnalysisTaskMuMu();
- void AddBin(const char* particle, const char* type,
- Double_t xmin, Double_t xmax,
- Double_t ymin,
- Double_t ymax,
- const char* flavour="");
-
- void AddBin(const char* particle, const char* type,
- Double_t xmin, Double_t xmax,
- const char* flavour="") { AddBin(particle,type,xmin,xmax,TMath::Limits<Double_t>::Max(),TMath::Limits<Double_t>::Max(),flavour); }
-
- void CreateMesh(const char* particle, const char* type1, const char* type2, const char* flavour="", Bool_t remove12=kFALSE);
-
- virtual void AddEventCut(const char* cutName, UInt_t mask);
-
- virtual void AddPairCut(const char* cutName, UInt_t maskForOneOrBothTrack, UInt_t maskForTrackPair=0);
+ AliAnalysisMuMuCutRegistry* CutRegistry() const;
- virtual void AddSingleCut(const char* cutName, UInt_t mask);
+ AliAnalysisMuMuBinning* Binning() const;
+
+ void AdoptSubAnalysis(AliAnalysisMuMuBase* analysis);
virtual void DisableHistograms(const char* pattern="*");
-
- AliMuonEventCuts* EventCuts() const;
+
+ void SetBeamYear(const char* beamYear) { fBeamYear = beamYear; }
virtual void FinishTaskOutput();
- Bool_t IsPP() const;
-
- Bool_t IsHistogrammingDisabled() const;
-
- virtual Bool_t IsHistogramDisabled(const char* hname) const;
-
virtual void NotifyRun();
virtual void Print(Option_t* opt="") const;
- virtual void ShouldSeparatePlusAndMinus(Bool_t value) { fShouldSeparatePlusAndMinus = value; }
-
- virtual Bool_t ShouldSeparatePlusAndMinus() const { return fShouldSeparatePlusAndMinus; }
-
virtual void Terminate(Option_t *);
- void UseBackgroundTriggers(Bool_t value=kTRUE) { fUseBackgroundTriggers = value; }
-
void UserCreateOutputObjects();
virtual void UserExec(Option_t* opt);
- AliMuonTrackCuts* MuonTrackCuts();
-
- void SetMuonTrackCuts(const AliMuonTrackCuts& trackCuts);
-
- class PairCut : public TObject {
- public:
- PairCut(const char* name="", UInt_t maskForOneOrBothTrack=0, UInt_t maskForTrackPair=0)
- : TObject(), fName("p"),fMaskForOneOrBothTrack(maskForOneOrBothTrack),fMaskForTrackPair(maskForTrackPair)
- {
- fName += name;
- }
- const char* GetName() const { return fName.Data(); }
- UInt_t MaskForOneOrBothTrack() const { return fMaskForOneOrBothTrack; }
- UInt_t MaskForTrackPair() const { return fMaskForTrackPair; }
- void Print(Option_t* opt="") const;
-
- private:
- TString fName; // name of the cut
- UInt_t fMaskForOneOrBothTrack; // mask for the cut that at least of the two tracks should match
- UInt_t fMaskForTrackPair; // mask for the cut both tracks should match
-
- ClassDef(AliAnalysisTaskMuMu::PairCut,1); // a simple wrapper for two masks
- };
-
-
private:
-
- virtual void FillHistos(const char* physics, const char* triggerClassName, const char* centrality);
-
- void FillHistosForTrack(const char* physics, const char* triggerClassName, const char* centrality, const AliVParticle& track, Int_t trackIndex);
-
- void FillHistogramCollection(const char* physics, const char* triggerClassName);
- void FillEventHistos(const char* physics, const char* triggerClassName,
- const char* centrality);
-
- void Fill(const char* eventtype, TObjString* tname, const char* centrality, float fcent);
-
- void FillMC();
-
- void AssertHistogramCollection(const char* physics, const char* triggerClassName);
-
- void BeautifyHistos();
-
- void CreateMinvHistograms(const char* physics, const char* triggerClassName);
-
- void CreateHisto(TObjArray* array,
- const char* physics,
- const char* triggerClassName,
- const char* hname, const char* htitle,
- Int_t nbinsx, Double_t xmin, Double_t xmax,
- Int_t nbinsy, Double_t ymin, Double_t ymax) const;
-
- void CreateEventHisto(const char* physics,
+ void CreateTrackHisto(const char* eventSelection,
const char* triggerClassName,
- const char* hname, const char* htitle,
+ const char* hname, const char* htitle,
Int_t nbinsx, Double_t xmin, Double_t xmax,
- Int_t nbinsy=0, Double_t ymin=0.0, Double_t ymax=0.0) const;
+ Int_t nbinsy=-1, Double_t ymin=0.0, Double_t ymax=0.0,
+ Bool_t separatePlusAndMinus=kFALSE) const;
- void CreateSingleHisto(const char* physics,
- const char* triggerClassName,
- const char* hname, const char* htitle,
- Int_t nbinsx, Double_t xmin, Double_t xmax,
- Int_t nbinsy=0, Double_t ymin=0.0, Double_t ymax=0.0,
- Bool_t separatePlusAndMinus=kFALSE) const;
-
- void CreatePairHisto(const char* physics,
+ void CreatePairHisto(const char* eventSelection,
const char* triggerClassName,
- const char* hname, const char* htitle,
+ const char* hname, const char* htitle,
Int_t nbinsx, Double_t xmin, Double_t xmax,
- Int_t nbinsy=0, Double_t ymin=0.0, Double_t ymax=0.0) const;
+ Int_t nbinsy=-1, Double_t ymin=0.0, Double_t ymax=0.0) const;
- void DefineCentralityClasses(TArrayF* centralities);
-
- UInt_t GetTriggerInputBitMaskFromInputName(const char* inputName) const;
-
- TH1* Histo(const char* physics, const char* histoname);
-
- TH1* Histo(const char* physics, const char* triggerClassName, const char* histoname);
-
- TH1* Histo(const char* physics, const char* triggerClassName, const char* what, const char* histoname);
-
- TH1* Histo(const char* physics, const char* triggerClassName, const char* cent, const char* what, const char* histoname);
+ const char* DefaultCentralityName() const;
- Double_t MuonMass2() const;
+ AliVEvent* Event() const;
- const char* DefaultCentralityName() const;
+ void FillHistos(const char* eventSelection, const char* triggerClassName, const char* centrality);
- const char* CentralityName(Double_t centrality) const;
+ void Fill(const char* eventSelection, const char* triggerClassName);
- Bool_t HasMC() const { return fHasMC; }
+ void FillMC();
- void ComputeTrackMask(const AliVParticle& track, Int_t trackIndex);
-
- UInt_t GetEventMask() const;
+ void GetSelectedTrigClassesInEvent(const AliVEvent* event, TObjArray& array);
- void GetPairMask(const AliVParticle& t1, const AliVParticle& t2,
- Int_t trackIndex1, Int_t trackIndex2,
- UInt_t& mask1, UInt_t& mask2,
- UInt_t& mask12) const;
+ Bool_t IsHistogrammingDisabled() const;
- UInt_t GetTrackMask(Int_t trackIndex) const;
+ virtual Bool_t IsHistogramDisabled(const char* hname) const;
- Double_t GetTrackTheta(const AliVParticle& particle) const;
+ Bool_t IsPP() const;
- Bool_t PairRapidityCut(const AliVParticle& t1, const AliVParticle& t2) const;
-
- /* methods prefixed with EA should really not exist at all. They are there
- only because the some of our base interfaces are shamelessly incomplete or
- inadequate...
- */
+private:
- void EAComputeTrackMasks();
-
- Int_t EAGetNumberOfMuonTracks() const;
-
- Int_t EAGetNumberOfSelectMuonTracks() const;
-
- Double_t EAGetTrackDCA(const AliVParticle& particle) const;
-
- Bool_t EAGetTZEROFlags(Bool_t& backgroundFlag, Bool_t& pileupFlag, Bool_t& satelliteFlag) const;
-
- Bool_t AtLeastOneMuonTrigger(const TString& firedTriggerClasses) const;
-
- Bool_t AtLeastOneEmcalTrigger(const TString& firedTriggerClasses) const;
-
- Bool_t AtLeastOneMBTrigger(const TString& firedTriggerClasses) const;
-
- Bool_t TriggerSBACECondition(const TString& triggerName) const;
+ AliAnalysisTaskMuMu(const AliAnalysisTaskMuMu&); // not implemented (on purpose)
+ AliAnalysisTaskMuMu& operator=(const AliAnalysisTaskMuMu&); // not implemented (on purpose)
- void DefineDefaultBinning();
-
- AliVEvent* Event() const;
-
private:
AliMergeableCollection* fHistogramCollection; //! collection of histograms
AliCounterCollection* fEventCounters; //! event counters
-
- AliMuonTrackCuts* fMuonTrackCuts; //! common cuts for muon tracks (from Diego)
- TArrayI fPrecomputedTrackMasks; //! track masks
+ mutable AliAnalysisMuMuBinning* fBinning; // binning for particles
- Bool_t fIsFromESD; // whether we read from ESD or AOD
- Bool_t fShouldSeparatePlusAndMinus; // whether or not to histogram mu+ and mu- separately
- TString fBeamYear; // beam and year
-
- TObjArray* fSingleTrackCutNames; // cut on single tracks (array of TObjString)
- TObjArray* fPairTrackCutNames; // cut on track pairs (array of TObjString)
- TObjArray* fCentralityNames; // names to create histograms
- TObjArray* fEventCutNames; // cut at event level (array of TObjString)
-
- Bool_t fUseBackgroundTriggers; // whether or not we should use the ACE triggers
-
- std::map<std::string,int> fTriggerInputBitMap; // map of L0 input name to bit
-
- AliAnalysisMuMuBinning* fBinning; // binning for particles
+ mutable AliAnalysisMuMuCutRegistry* fCutRegistry; // cuts (owner)
- TList* fHistogramToDisable; // list of regexp of histo name to disable
-
- TObjArray* fBinArray; //! cache for the bins
- Bool_t fHasMC; //! current event has MC information
+ TString fBeamYear; // beam and year
- mutable AliMuonEventCuts* fEventCuts; // common cuts for muon events (from Diego)
+ TList* fHistogramToDisable; // list of regexp of histo name(s) to disable
- AliAnalysisTaskMuMu(const AliAnalysisTaskMuMu&); // not implemented (on purpose)
- AliAnalysisTaskMuMu& operator=(const AliAnalysisTaskMuMu&); // not implemented (on purpose)
+ TObjArray* fSubAnalysisVector; // list of companion analysis
- ClassDef(AliAnalysisTaskMuMu,24) // a class to analyse muon pairs (and single also ;-) )
+ ClassDef(AliAnalysisTaskMuMu,26) // a class to analyse muon pairs (and single also ;-) )
};
#endif
AliMergeableCollection::Histo(const char* identifier,
const char* objectName) const
{
+ /// Get histogram key1/key2/.../objectName:action
+ /// action is used for 2D histograms :
+ /// might be px for projection along x-axis
+ /// py for projection along y-axis
+ /// pfx for profile along x-axis
+ /// pfy for profile along y-axis
+
TObject* o = GetObject(identifier,objectName);
TObjArray* arr = TString(objectName).Tokenize(":");
return static_cast<TH1*>(o);
}
+//_____________________________________________________________________________
+TH2*
+AliMergeableCollection::H2(const char* fullIdentifier) const
+{
+ /// Short-cut method to grab a 2D histogram
+ /// Will return 0x0 if the object if not a TH2xxx
+
+ TObject* o = GetObject(fullIdentifier);
+
+ if (o->IsA()->InheritsFrom(TH2::Class()))
+ {
+ return static_cast<TH2*>(o);
+ }
+ return 0x0;
+}
+
+//_____________________________________________________________________________
+TH2*
+AliMergeableCollection::H2(const char* identifier,
+ const char* objectName) const
+{
+ /// Short-cut method to grab a 2D histogram
+ /// Will return 0x0 if the object if not a TH2xxx
+
+ TObject* o = GetObject(identifier,objectName);
+
+ if (o->IsA()->InheritsFrom(TH2::Class()))
+ {
+ return static_cast<TH2*>(o);
+ }
+ return 0x0;
+}
+
+//_____________________________________________________________________________
+TProfile*
+AliMergeableCollection::Prof(const char* fullIdentifier) const
+{
+ /// Short-cut method to grab a TProfile histogram
+ /// Will return 0x0 if the object if not a TProfile
+
+ TObject* o = GetObject(fullIdentifier);
+
+ if (o->IsA()->InheritsFrom(TProfile::Class()))
+ {
+ return static_cast<TProfile*>(o);
+ }
+ return 0x0;
+}
+
+//_____________________________________________________________________________
+TProfile*
+AliMergeableCollection::Prof(const char* identifier,
+ const char* objectName) const
+{
+ /// Short-cut method to grab a TProfile histogram
+ /// Will return 0x0 if the object if not a TProfile
+
+ TObject* o = GetObject(identifier,objectName);
+
+ if (o->IsA()->InheritsFrom(TProfile::Class()))
+ {
+ return static_cast<TProfile*>(o);
+ }
+ return 0x0;
+}
//_____________________________________________________________________________
TObject*
}
}
-
//_____________________________________________________________________________
TObject*
AliMergeableCollection::GetObject(const char* identifier,
if ( obj->IsA()->InheritsFrom(TH1::Class()) ) (static_cast<TH1*> ( obj ))->SetDirectory(0);
hlist->AddLast(obj);
-
- // invalidate the TFolder structure, if any, so it will
- // be recomputed next time Browse() is called
- delete fFolders;
- fFolders = 0x0;
-
+
return kTRUE;
}
/// output to only those objects matching a given classname pattern
///
- cout << Form("AliMergeableCollection(%s,%s) : %d keys and %d objects",
- GetName(),GetTitle(),
+ cout << Form("AliMergeableCollection(%s,%s)[%p] : %d keys and %d objects",
+ GetName(),GetTitle(),this,
NumberOfKeys(), NumberOfObjects()) << endl;
if (!strlen(option)) return;
TObjArray* identifiers = SortAllIdentifiers();
- printf("identifiers entries %i\n", identifiers->GetEntries());
+ std::cout << Form("Number of identifiers %d", identifiers->GetEntries()) << std::endl;
TIter nextIdentifier(identifiers);
while ( ( obj = next() ) )
{
UInt_t thissize=0;
- if ( obj->IsA()->InheritsFrom(TH1::Class()) ) {
+ if ( obj->IsA()->InheritsFrom(TH1::Class()) || obj->IsA()->InheritsFrom(TProfile::Class()) )
+ {
TH1* histo = static_cast<TH1*> (obj);
Int_t nbins = (histo->GetNbinsX()+2);
if (cname.Contains(TRegexp("I$")) ) nbytesPerBin = sizeof(Int_t);
if (cname.Contains(TRegexp("F$")) ) nbytesPerBin = sizeof(Float_t);
if (cname.Contains(TRegexp("D$")) ) nbytesPerBin = sizeof(Double_t);
+ if (cname=="TProfile") nbytesPerBin = sizeof(Double_t);
if (!nbytesPerBin)
{
+ strlen(histo->GetTitle());
if ( hasErrors) thissize += nbins*8;
+
+ if ( obj->IsA()->InheritsFrom(TProfile::Class()) )
+ {
+ TProfile* prof = static_cast<TProfile*>(obj);
+ TArrayD* d = prof->GetBinSumw2();
+ thissize += d->GetSize()*8*2; // 2 TArrayD
+ thissize += sizeof(prof) - sizeof(histo);
+ }
}
else if ( obj->IsA()->InheritsFrom(THnSparse::Class()) ) {
THnSparse* sparse = static_cast<THnSparse*> (obj);
class TMap;
class AliMergeableCollectionIterator;
class TH1;
+class TH2;
+class TProfile;
class AliMergeableCollection : public TFolder
{
TH1* Histo(const char* fullIdentifier) const;
TH1* Histo(const char* identifier, const char* objectName) const;
+ TH1* H1(const char* fullIdentifier) const { return Histo(fullIdentifier); }
+ TH1* H1(const char* identifier, const char* objectName) const { return Histo(identifier,objectName); }
+
+ TH2* H2(const char* fullIdentifier) const;
+ TH2* H2(const char* identifier, const char* objectName) const;
+
+ TProfile* Prof(const char* fullIdentifier) const;
+ TProfile* Prof(const char* identifier, const char* objectName) const;
+
virtual TIterator* CreateIterator(Bool_t dir = kIterForward) const;
virtual TList* CreateListOfKeys(Int_t index) const;
mutable Int_t fMapVersion; /// internal version of map (to avoid custom streamer...)
mutable std::map<std::string,int> fMessages; //! log messages
- ClassDef(AliMergeableCollection,3) /// A collection of mergeable objects
+ ClassDef(AliMergeableCollection,4) /// A collection of mergeable objects
};
class AliMergeableCollectionIterator : public TIterator
delete fullList;
}
+//________________________________________________________________________
+UInt_t AliMuonEventCuts::GetTriggerInputBitMaskFromInputName(const char* inputName) const
+{
+ // Get trigger input bit from its name
+
+ if (!fTrigInputsMap)
+ {
+ AliError("No Inputs Map available");
+ return TMath::Limits<UInt_t>::Max();
+ }
+
+ TObjString* s = static_cast<TObjString*>(fTrigInputsMap->FindObject(inputName));
+ if (!s)
+ {
+ AliError(Form("Did not find input %s",inputName));
+ return TMath::Limits<UInt_t>::Max();
+ }
+ return s->GetUniqueID();
+}
+
//________________________________________________________________________
TArrayI AliMuonEventCuts::GetTrigClassPtCutLevel ( const TString trigClassName ) const
{
SetTrigInputsMap(trigInputsMap);
}
+//________________________________________________________________________
+const TObjArray*
+AliMuonEventCuts::GetSelectedTrigClassesInEvent(const TString& firedTriggerClasses,
+ UInt_t l0Inputs, UInt_t l1Inputs,
+ UInt_t l2Inputs)
+{
+ /// Return the selected trigger classes in the fired trigger classes
+ /// give also the L0,L1,L2 input bit masks
+
+ BuildTriggerClasses(firedTriggerClasses,l0Inputs,l1Inputs,l2Inputs);
+
+ return fSelectedTrigClassesInEvent;
+}
+
//________________________________________________________________________
const TObjArray* AliMuonEventCuts::GetSelectedTrigClassesInEvent( const AliVEvent* event )
{
/// Get trigger classes found in run
TList* GetAllSelectedTrigClasses () const { return fAllSelectedTrigClasses; }
const TObjArray* GetSelectedTrigClassesInEvent ( const AliVEvent* event );
+ const TObjArray* GetSelectedTrigClassesInEvent(const TString& firedTriggerClasses,
+ UInt_t l0Inputs, UInt_t l1Inputs, UInt_t l2Inputs);
+
+ UInt_t GetTriggerInputBitMaskFromInputName(const char* inputName) const;
-
// Handle centrality
void SetCentralityClasses(Int_t nCentralityBins = -1, Double_t* centralityBins = 0x0);
/// Get centrality classes
--- /dev/null
+# Doxyfile 1.8.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed
+# in front of the TAG it is preceding .
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = "PWG/muon"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = "PWG/muon"
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "Classes relevant to muon analyses"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = $(ALICE_INSTALL)
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian,
+# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic,
+# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields or simple typedef fields will be shown
+# inline in the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO (the default), structs, classes, and unions are shown on a separate
+# page (for HTML and Man pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can
+# be an expensive process and often the same symbol appear multiple times in
+# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too
+# small doxygen will become slower. If the cache is too large, memory is wasted.
+# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid
+# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536
+# symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if section-label ... \endif
+# and \cond section-label ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE = DoxygenLayout.xml
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path. Do not use
+# file names with spaces, bibtex cannot handle them.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+# for the moment we are very specific (instead of just giving the full PWG/muon directory
+# as input ...) as many classes have no doxygen comments at all
+
+INPUT = \
+AliAnalysisMuMuBase.cxx \
+AliAnalysisMuMuBase.h \
+AliAnalysisMuMuBinning.cxx \
+AliAnalysisMuMuBinning.h \
+AliAnalysisMuMuCutCombination.cxx \
+AliAnalysisMuMuCutCombination.h \
+AliAnalysisMuMuCutElement.cxx \
+AliAnalysisMuMuCutElement.h \
+AliAnalysisMuMuCutRegistry.cxx \
+AliAnalysisMuMuCutRegistry.h \
+AliAnalysisMuMuEventCutter.cxx \
+AliAnalysisMuMuEventCutter.h \
+AliAnalysisMuMuGlobal.cxx \
+AliAnalysisMuMuGlobal.h \
+AliAnalysisMuMuMinv.cxx \
+AliAnalysisMuMuMinv.h \
+AliAnalysisMuMuNch.cxx \
+AliAnalysisMuMuNch.h \
+AliAnalysisMuMuSingle.cxx \
+AliAnalysisMuMuSingle.h \
+AliAnalysisMuonUtility.cxx \
+AliAnalysisMuonUtility.h \
+AliAnalysisTaskMuMu.cxx \
+AliAnalysisTaskMuMu.h \
+AliMergeableCollection.cxx \
+AliMergeableCollection.h \
+AliMuonEventCuts.cxx \
+AliMuonEventCuts.h \
+AliMuonTrackCuts.cxx \
+AliMuonTrackCuts.h
+
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = "G__*"
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = .
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be ignored.
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+# If CLANG_ASSISTED_PARSING is set to YES, then doxygen will use the clang parser
+# for more acurate parsing at the cost of reduced performance. This can be
+# particularly helpful with template rich C++ code for which doxygen's built-in
+# parser lacks the necessairy type information.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified at INPUT and INCLUDE_PATH.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 2
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX = Ali
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
+# SVG. The default value is HTML-CSS, which is slower, but has the best
+# compatibility.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript
+# pieces of code that will be used on startup of the MathJax code.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript.
+# There are two flavours of web server based search depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools.
+# See the manual for details.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain
+# the search results. Doxygen ships with an example indexer (doxyindexer) and
+# search engine (doxysearch.cgi) which are based on the open source search
+# engine library Xapian. See the manual for configuration details.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will returned the search results when EXTERNAL_SEARCH is enabled.
+# Doxygen ships with an example search engine (doxysearch) which is based on
+# the open source search engine library Xapian. See the manual for configuration
+# details.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
+# of to a relative location where the documentation can be found.
+# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4 will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images
+# or other source files which should be copied to the LaTeX output directory.
+# Note that the files will be copied as-is; there are no commands or markers
+# available.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files
+# that can be used to generate PDF.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it. If left blank docbook will be used as the default path.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed
+# in the related pages index. If set to NO, only the current project's
+# pages will be listed.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = NO
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# manageable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
--- /dev/null
+<doxygenlayout version="1.0">
+ <!-- Generated by doxygen 1.8.4 -->
+ <!-- Navigation index tabs for HTML output -->
+ <navindex>
+ <tab type="mainpage" visible="yes" title=""/>
+ <tab type="pages" visible="yes" title="" intro=""/>
+ <tab type="modules" visible="yes" title="" intro=""/>
+ <tab type="namespaces" visible="yes" title="">
+ <tab type="namespacelist" visible="yes" title="" intro=""/>
+ <tab type="namespacemembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="classes" visible="yes" title="">
+ <tab type="classlist" visible="yes" title="" intro=""/>
+ <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ <tab type="hierarchy" visible="yes" title="" intro=""/>
+ <tab type="classmembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="files" visible="yes" title="">
+ <tab type="filelist" visible="yes" title="" intro=""/>
+ <tab type="globals" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="examples" visible="yes" title="" intro=""/>
+ <tab type="user" url="http://aliweb.cern.ch/Offline/" title="Alice Offline Pages"/>
+ <tab type="user" url="http://git.cern.ch/pubweb/AliRoot.git/tree" title="AliRoot git web"/>
+ </navindex>
+
+ <!-- Layout definition for a class page -->
+ <class>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <inheritancegraph visible="$CLASS_GRAPH"/>
+ <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+ <detaileddescription title=""/>
+ <memberdecl>
+ <nestedclasses visible="yes" title=""/>
+ <publictypes title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <publicslots title=""/>
+ <signals title=""/>
+ <publicmethods title=""/>
+ <publicstaticmethods title=""/>
+ <publicattributes title=""/>
+ <publicstaticattributes title=""/>
+ <protectedtypes title=""/>
+ <protectedslots title=""/>
+ <protectedmethods title=""/>
+ <protectedstaticmethods title=""/>
+ <protectedattributes title=""/>
+ <protectedstaticattributes title=""/>
+ <packagetypes title=""/>
+ <packagemethods title=""/>
+ <packagestaticmethods title=""/>
+ <packageattributes title=""/>
+ <packagestaticattributes title=""/>
+ <properties title=""/>
+ <events title=""/>
+ <privatetypes title=""/>
+ <privateslots title=""/>
+ <privatemethods title=""/>
+ <privatestaticmethods title=""/>
+ <privateattributes title=""/>
+ <privatestaticattributes title=""/>
+ <friends title=""/>
+ <related title="" subtitle=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <constructors title=""/>
+ <functions title=""/>
+ <related title=""/>
+ <variables title=""/>
+ <properties title=""/>
+ <events title=""/>
+ </memberdef>
+ <allmemberslink visible="yes"/>
+ <usedfiles visible="$SHOW_USED_FILES"/>
+ <authorsection visible="yes"/>
+ </class>
+
+ <!-- Layout definition for a namespace page -->
+ <namespace>
+ <briefdescription visible="yes"/>
+ <memberdecl>
+ <nestednamespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </namespace>
+
+ <!-- Layout definition for a file page -->
+ <file>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <includegraph visible="$INCLUDE_GRAPH"/>
+ <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+ <sourcelink visible="yes"/>
+ <memberdecl>
+ <classes visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection/>
+ </file>
+
+ <!-- Layout definition for a group page -->
+ <group>
+ <briefdescription visible="yes"/>
+ <groupgraph visible="$GROUP_GRAPHS"/>
+ <memberdecl>
+ <nestedgroups visible="yes" title=""/>
+ <dirs visible="yes" title=""/>
+ <files visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+
+ <!-- Layout definition for a directory page -->
+ <directory>
+ <briefdescription visible="yes"/>
+ <directorygraph visible="yes"/>
+ <memberdecl>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ </directory>
+</doxygenlayout>
--- /dev/null
+///
+/// Example macro to run the AliAnalysisTaskMuMu task
+///
+/// \author L. Aphecetche
+///
+
+//______________________________________________________________________________
+void LoadLocalLibs(Bool_t localAnalysis=kTRUE)
+{
+ gSystem->Load("libVMC");
+ gSystem->Load("libMinuit");
+ gSystem->Load("libTree");
+ gSystem->Load("libProofPlayer");
+ gSystem->Load("libXMLParser");
+ gSystem->Load("libSTEERBase");
+ gSystem->Load("libESD");
+ gSystem->Load("libAOD");
+ gSystem->Load("libANALYSIS");
+ gSystem->Load("libANALYSISalice");
+
+ if (!localAnalysis)
+ {
+ gSystem->Load("libCORRFW");
+ }
+ else
+ {
+ gROOT->LoadMacro("AliOADBMuonTrackCutsParam.cxx+g");
+ gROOT->LoadMacro("AliAnalysisMuonUtility.cxx+g");
+ gROOT->LoadMacro("AliMuonTrackCuts.cxx+g");
+ gROOT->LoadMacro("AliMergeableCollection.cxx+g");
+ gROOT->LoadMacro("AliAnalysisMuMuBinning.cxx+g");
+ gROOT->LoadMacro("AliMuonEventCuts.cxx+g");
+
+ gROOT->LoadMacro("AliAnalysisMuMuCutElement.cxx+g");
+ gROOT->LoadMacro("AliAnalysisMuMuCutCombination.cxx+g");
+ gROOT->LoadMacro("AliAnalysisMuMuCutRegistry.cxx+g");
+ gROOT->LoadMacro("AliAnalysisMuMuEventCutter.cxx+g");
+ gROOT->LoadMacro("AliAnalysisMuMuBase.cxx+g");
+
+ gROOT->LoadMacro("AliAnalysisTaskMuMu.cxx+g");
+
+ gROOT->LoadMacro("AliAnalysisMuMuGlobal.cxx+g");
+
+ gROOT->LoadMacro("AliAnalysisMuMuMinv.cxx+g");
+ gROOT->LoadMacro("AliAnalysisMuMuSingle.cxx+g");
+ gROOT->LoadMacro("AliAnalysisMuMuNch.cxx+g");
+
+ }
+}
+
+//______________________________________________________________________________
+TChain* CreateLocalChain(const char* filelist)
+{
+ TChain* c = new TChain("aodTree");
+
+ char line[1024];
+
+ ifstream in(filelist);
+ while ( in.getline(line,1024,'\n') )
+ {
+ c->Add(line);
+ }
+ return c;
+}
+
+//______________________________________________________________________________
+TString GetInputType(const TString& sds, TProof* p)
+{
+ if (sds.Length()==0 ) return "AOD";
+
+ if (sds.Contains("SIM_JPSI")) return "AOD";
+
+ if (sds.Contains("AOD")) return "AOD";
+ if (sds.Contains("ESD")) return "ESD";
+
+ if ( gSystem->AccessPathName(gSystem->ExpandPathName(sds.Data())) )
+ {
+ // dataset is not a local file so it must be a dataset name
+ if (!p) return "NOPROOF";
+
+ TFileCollection* fc = p->GetDataSet(sds.Data());
+ if (!fc) return "NODATASET";
+
+ TIter next(fc->GetList());
+ TFileInfo* fi;
+ while ( ( fi = static_cast<TFileInfo*>(next()) ) )
+ {
+ TUrl url(*(fi->GetFirstUrl()));
+ TString surl(url.GetUrl());
+
+ if (surl.Contains("AOD")) return "AOD";
+ if (surl.Contains("AliESD")) return "ESD";
+ }
+
+ }
+ else
+ {
+ std::cout << "Will use datasets from file " << sds.Data() << std::endl;
+
+ // dataset is a local text file containing a list of dataset names
+ std::ifstream in(sds.Data());
+ char line[1014];
+
+ while (in.getline(line,1023,'\n'))
+ {
+ TString sline(line);
+ sline.ToUpper();
+ if ( sline.Contains("SIM_JPSI") ) return "AOD";
+ if ( sline.Contains("AOD") ) return "AOD";
+ if ( sline.Contains("ESD") ) return "ESD";
+ }
+ }
+
+ return "BUG";
+}
+
+//______________________________________________________________________________
+AliAnalysisTask* runMuMu(const char* dataset="SIM_JPSI_LHC13f_CynthiaTuneWithRejectList_000197388",
+ Bool_t simulations=kTRUE,
+ Bool_t baseline=kFALSE,
+ const char* where="laphecet@nansafmaster.in2p3.fr/?N")
+{
+ // Create the analysis manager
+
+ Bool_t prooflite = (strlen(where)==0) || TString(where).Contains("workers");
+
+ TString sds(dataset);
+
+// if (!prooflite && sds.Length()>0) TProof::Mgr(where)->SetROOTVersion("VO_ALICE@ROOT::v5-34-05");
+
+ TProof* p(0x0);
+ TString alirootMode("");
+ TString workers("workers=8x");
+
+ if (TString(where).Contains("alice-caf"))
+ {
+ workers="workers=1x";
+ }
+ if (TString(where).Contains("localhost:2093"))
+ {
+ workers="workers=8x";
+ }
+
+ if (prooflite)
+ {
+ cout << "Will work in LITE mode" << endl;
+ }
+
+ if ( sds.Length()>0 )
+ {
+ p = TProof::Open(where,workers.Data());
+
+ if (!p)
+ {
+ cout << "Cannot connect to Proof : " << where << endl;
+ return 0;
+ }
+
+ alirootMode.ToUpper();
+
+ if ( alirootMode == "PAR" )
+ {
+ cout << "Will work with PAR files" << endl;
+
+ std::vector<std::string> pars;
+
+ pars.push_back("STEERBase");
+ pars.push_back("ESD");
+ pars.push_back("AOD");
+ pars.push_back("ANALYSIS");
+ pars.push_back("OADB");
+ pars.push_back("ANALYSISalice");
+ // pars.push_back("CORRFW");
+ // pars.push_back("PWGmuon");
+
+ Bool_t ok(kTRUE);
+
+ for ( std::vector<std::string>::size_type i = 0; i < pars.size(); ++i )
+ {
+ std::string package = pars[i];
+
+ if ( gProof->UploadPackage(package.c_str()) )
+ {
+ ok = kFALSE;
+ }
+
+ if ( gProof->EnablePackage(package.c_str(),"",kTRUE) )
+ {
+ ok = kFALSE;
+ }
+
+ if (!ok)
+ {
+ cout << "Problem with PAR " << package.c_str() << endl;
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ TList* list = new TList();
+
+ // list->Add(new TNamed("ALIROOT_EXTRA_LIBS", "PWG3base"));
+ // list->Add(new TNamed("ALIROOT_EXTRA_INCLUDES", "PWG3"));
+ // list->Add(new TNamed("ALIROOT_EXTRA_LIBS", "PWG3base"));//:CORRFW:PWG3muon"));
+ // list->Add(new TNamed("ALIROOT_EXTRA_INCLUDES", "PWG3/base"));//:PWG3/muon"));
+
+ // list->Add(new TNamed("ALIROOT_ENABLE_ALIEN", "1"));
+
+ if (!alirootMode.IsNull())
+ {
+ list->Add(new TNamed("ALIROOT_MODE", alirootMode.Data()));
+ }
+ else
+ {
+ list->Add(new TNamed("ALIROOT_MODE",""));
+ }
+
+ if (!prooflite)
+ {
+// p->SetParameter("PROOF_UseTreeCache", 0);
+ p->EnablePackage("VO_ALICE@AliRoot::v5-04-65-AN", list, kTRUE);
+ }
+ else
+ {
+ // list->Add(new TNamed("ALIROOT_LOCAL_PATH",gSystem->Getenv("ALICE_ROOT")));
+ p->UploadPackage("$ALICE_ROOT/ANALYSIS/macros/AliRootProofLite.par");
+ if (p->EnablePackage("AliRootProofLite",list)) return 0;
+ }
+ }
+
+ // compile task on workers
+ if ( alirootMode != "PAR" )
+ {
+ p->Load("AliOADBMuonTrackCutsParam.cxx+");
+ p->Load("AliAnalysisMuonUtility.cxx+");
+ p->Load("AliMuonTrackCuts.cxx+");
+ p->Load("AliMergeableCollection.cxx+");
+ p->Load("AliAnalysisMuMuBinning.cxx+");
+ p->Load("AliMuonEventCuts.cxx+");
+ p->Load("AliAnalysisMuMuCutElement.cxx+");
+ p->Load("AliAnalysisMuMuCutCombination.cxx+");
+ p->Load("AliAnalysisMuMuCutRegistry.cxx+");
+ p->Load("AliAnalysisMuMuBase.cxx+");
+ p->Load("AliAnalysisTaskMuMu.cxx+");
+ p->Load("AliAnalysisMuMuEventCutter.cxx+");
+ p->Load("AliAnalysisMuMuGlobal.cxx+");
+ p->Load("AliAnalysisMuMuNch.cxx+");
+ p->Load("AliAnalysisMuMuSingle.cxx+");
+ p->Load("AliAnalysisMuMuMinv.cxx+");
+ }
+ }
+
+ LoadLocalLibs(kTRUE);
+
+ AliAnalysisManager *mgr = new AliAnalysisManager("MuMu");
+
+ AliInputEventHandler* input(0x0);
+
+ TString inputType = GetInputType(sds,p);
+
+ if ( inputType == "AOD" )
+ {
+ input = new AliAODInputHandler;
+ }
+ else if ( inputType == "ESD" )
+ {
+ input = new AliESDInputHandler;
+ }
+ else
+ {
+ std::cout << "Cannot get input type !" << std::endl;
+ return 0;
+ }
+
+ mgr->SetInputEventHandler(input);
+
+ TList* triggers = new TList;
+ triggers->SetOwner(kTRUE);
+
+ if (!simulations)
+ {
+ triggers->Add(new TObjString("CINT7-B-NOPF-ALLNOTRD"));
+
+// triggers->Add(new TObjString("CINT7-B-NOPF-ALLNOTRD & 0MUL"));
+// triggers->Add(new TObjString("CINT7-B-NOPF-ALLNOTRD & 0MSL"));
+// triggers->Add(new TObjString("CINT7-B-NOPF-ALLNOTRD & 0MSH"));
+// triggers->Add(new TObjString("CMSL7-B-NOPF-MUON & 0MUL"));
+// triggers->Add(new TObjString("CMSL7-B-NOPF-MUON & 0MSH"));
+//
+// triggers->Add(new TObjString("CMSL7-B-NOPF-MUON"));
+// triggers->Add(new TObjString("CMSH7-B-NOPF-MUON"));
+// triggers->Add(new TObjString("CMUL7-B-NOPF-MUON"));
+
+ // below for MB periods only
+// triggers->Add(new TObjString("CMSL7-B-NOPF-ALLNOTRD"));
+// triggers->Add(new TObjString("CMSH7-B-NOPF-ALLNOTRD"));
+ triggers->Add(new TObjString("CMUL7-B-NOPF-ALLNOTRD"));
+ triggers->Add(new TObjString("CMUL7-B-NOPF-MUON"));
+// triggers->Add(new TObjString("CMSL7-B-NOPF-ALLNOTRD & 0MUL"));
+// triggers->Add(new TObjString("CMSL7-B-NOPF-ALLNOTRD & 0MSH"));
+ }
+
+ TString outputname("test.MuMu.AOD.1.root");
+
+ if ( sds.Length()>0 )
+ {
+ TString af("local");
+
+ if ( gProof )
+ {
+ af="unknown";
+ TString master(gProof->GetSessionTag());
+ if (master.Contains("lx")) af = "caf";
+ if (master.Contains("nansaf")) af = "saf";
+ if (master.Contains("skaf")) af = "skaf";
+ if (master.Contains("localhost:2093")) af="laf";
+ }
+ outputname = Form("%s.%s.root",gSystem->BaseName(sds.Data()),af.Data());
+ outputname.ReplaceAll("|","-");
+ cout << outputname << endl;
+ }
+
+ AliAnalysisTask* task(0x0);
+
+ if (!baseline)
+ {
+ gROOT->LoadMacro("AddTaskMuMu.C");
+
+ task = AddTaskMuMu(outputname.Data(),triggers,"pA",simulations);
+ }
+ else
+ {
+ gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/train/AddTaskBaseLine.C");
+ task = AddTaskBaseLine();
+ }
+
+ if (!mgr->InitAnalysis())
+ {
+ cout << "Could not InitAnalysis" << endl;
+ return 0;
+ }
+
+ if ( sds.Length()>0 )
+ {
+ TStopwatch timer;
+
+ mgr->StartAnalysis("proof",sds.Data());
+
+ timer.Print();
+ }
+ else
+ {
+ mgr->PrintStatus();
+
+ task->Print();
+
+// return task;
+
+ TChain* c = CreateLocalChain("list.aod.txt");
+// mgr->SetNSysInfo(10);
+ TStopwatch timer;
+// mgr->SetDebugLevel(10);
+ mgr->StartAnalysis("local",c);
+ timer.Print();
+// mgr->ProfileTask("AliAnalysisTaskMuMu");
+// if (baseline) mgr->ProfileTask("baseline");
+ }
+
+ AliCodeTimer::Instance()->Print();
+
+ if (alirootMode=="PAR")
+ {
+ TProofLog *pl = TProof::Mgr(where)->GetSessionLogs(); pl->Save("*","aod.log");
+ }
+
+ delete triggers;
+
+ return task;
+}
+
if (!hminv)
{
- if (!fBinning && bin->IsNullObject() )
+ if (!fBinning && bin->IsIntegrated() )
{
// old file, we only had MinvUSPt
hminv = fMergeableCollection->Histo(Form("/%s/%s/%s/%s",eventType,trigger,centrality,pairCut),"MinvUSPt:py");
}
- AliAnalysisMuMuSpectra* s = static_cast<AliAnalysisMuMuSpectra*>(SIM()->GetSpectra(bin.Type().Data(),bin.Flavour().Data()));
+ AliAnalysisMuMuSpectra* s = static_cast<AliAnalysisMuMuSpectra*>(SIM()->GetSpectra(bin.Quantity().Data(),bin.Flavour().Data()));
if (!s)
{
- AliError(Form("Could not find spectra %s,%s for associated simulation",bin.Type().Data(),bin.Flavour().Data()));
+ AliError(Form("Could not find spectra %s,%s for associated simulation",bin.Quantity().Data(),bin.Flavour().Data()));
fAssociatedSimulation->MC()->Print("*:Ali*");
return par;
}
Double_t ylowcms, yhighcms;
Double_t ylownorm, yhighnorm;
- if ( bin->IsNullObject() )
+ if ( bin->IsIntegrated() )
{
ylowlab = -4;
yhighlab = -2.5;
r->Set("NofInputJpsi",rsim->GetValue("NofInputJpsi",accEffSubResultName),rsim->GetErrorStat("NofInputJpsi",accEffSubResultName));
r->Set("AccEffJpsi",rsim->GetValue("AccEffJpsi",accEffSubResultName),rsim->GetErrorStat("AccEffJpsi",accEffSubResultName));
- AliAnalysisMuMuBinning::Range* bincm = new AliAnalysisMuMuBinning::Range(bin->Particle(),bin->Type(),ylowcms,yhighcms);
+ AliAnalysisMuMuBinning::Range* bincm = new AliAnalysisMuMuBinning::Range(bin->What(),bin->Quantity(),ylowcms,yhighcms);
r->SetBin(*bincm);
return kFALSE;
}
- TObjArray* particles = fBinning->CreateParticleArray();
- TObjArray* types = fBinning->CreateTypeArray();
+ TObjArray* particles = fBinning->CreateWhatArray();
+ TObjArray* types = fBinning->CreateQuantityArray();
if (particles->GetEntries()!=1 || types->GetEntries()!=1 )
{