--- /dev/null
+#define AliAnalysisTaskTrigChEff_cxx
+
+// ROOT includes
+#include "TChain.h"
+#include "TH1.h"
+#include "TCanvas.h"
+#include "TROOT.h"
+#include "TString.h"
+#include "TList.h"
+
+// STEER includes
+#include "AliLog.h"
+
+#include "AliESDEvent.h"
+#include "AliESDMuonTrack.h"
+#include "AliESDInputHandler.h"
+
+#include "AliAODEvent.h"
+#include "AliAODTrack.h"
+#include "AliAODInputHandler.h"
+
+// ANALYSIS includes
+#include "AliAnalysisTask.h"
+#include "AliAnalysisDataSlot.h"
+#include "AliAnalysisManager.h"
+#include "AliAnalysisTaskTrigChEff.h"
+
+ClassImp(AliAnalysisTaskTrigChEff)
+
+//________________________________________________________________________
+AliAnalysisTaskTrigChEff::AliAnalysisTaskTrigChEff(const char *name) :
+ AliAnalysisTask(name,""),
+ fESD(0),
+ fAOD(0),
+ fAnalysisType("ESD"),
+ fList(0)
+{
+ //
+ /// Constructor.
+ //
+ // Input slot #0 works with an Ntuple
+ DefineInput(0, TChain::Class());
+ // Output slot #0 writes into a TObjArray container
+ DefineOutput(0, TList::Class());
+}
+
+//___________________________________________________________________________
+void AliAnalysisTaskTrigChEff::ConnectInputData(Option_t *) {
+ //
+ /// Connect ESD or AOD here
+ /// Called once
+ //
+
+ TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
+ if (!tree) {
+ Printf("ERROR: Could not read chain from input slot 0");
+ } else {
+ // Disable all branches and enable only the needed ones
+ // The next two lines are different when data produced as AliESDEvent is read
+ if(fAnalysisType == "ESD") {
+ tree->SetBranchStatus("*", kFALSE);
+ tree->SetBranchStatus("MuonTracks.*", kTRUE);
+
+ AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
+
+ if (!esdH) {
+ Printf("ERROR: Could not get ESDInputHandler");
+ } else
+ fESD = esdH->GetEvent();
+ }
+ else if(fAnalysisType == "AOD") {
+ AliAODInputHandler *aodH = dynamic_cast<AliAODInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
+
+ if (!aodH) {
+ Printf("ERROR: Could not get AODInputHandler");
+ } else
+ fAOD = aodH->GetEvent();
+ }
+ else
+ Printf("Wrong analysis type: Only ESD and AOD types are allowed!");
+ }
+}
+
+//___________________________________________________________________________
+void AliAnalysisTaskTrigChEff::CreateOutputObjects() {
+ //
+ /// Create histograms
+ /// Called once
+ //
+ Printf(" CreateOutputObjects of task %s\n", GetName());
+
+ TString cathCode[2] = {"bendPlane", "nonBendPlane"};
+ TString countTypeName[2] = {"CountInCh", "NonCountInCh"};
+
+ Char_t* yAxisTitle = "counts";
+
+ const Int_t kNboards = 234; //AliMpConstants::NofLocalBoards();
+ const Int_t kFirstTrigCh = 11;//AliMpConstants::NofTrackingChambers()+1;
+
+ Int_t chamberBins = kNchambers;
+ Float_t chamberLow = kFirstTrigCh-0.5, chamberHigh = kFirstTrigCh+kNchambers-0.5;
+ Char_t* chamberName = "chamber";
+
+ Int_t slatBins = kNslats;
+ Float_t slatLow = 0-0.5, slatHigh = kNslats-0.5;
+ Char_t* slatName = "slat";
+
+ Int_t boardBins = kNboards;
+ Float_t boardLow = 1-0.5, boardHigh = kNboards+1.-0.5;
+ Char_t* boardName = "board";
+
+ TString baseName, histoName;
+ fList = new TList();
+
+ TH1F* histo;
+
+ histo = new TH1F("nTracksInSlat", "Num. of tracks used for efficiency calculation",
+ slatBins, slatLow, slatHigh);
+ histo->GetXaxis()->SetTitle(slatName);
+ histo->GetYaxis()->SetTitle("num of used tracks");
+
+ fList->AddAt(histo, kHtracksInSlat);
+
+ histo = new TH1F("nTracksInBoard", "Num. of tracks used for efficiency calculation",
+ boardBins, boardLow, boardHigh);
+ histo->GetXaxis()->SetTitle(boardName);
+ histo->GetYaxis()->SetTitle("num of used tracks");
+
+ fList->AddAt(histo, kHtracksInBoard);
+
+ for(Int_t hType=0; hType<kNcounts; hType++){
+ Int_t hindex = (hType==0) ? kHchamberAllEff : kHchamberNonEff;
+ for(Int_t cath=0; cath<kNcathodes; cath++){
+ histoName = Form("%sChamber%s", cathCode[cath].Data(), countTypeName[hType].Data());
+ histo = new TH1F(histoName, histoName,
+ chamberBins, chamberLow, chamberHigh);
+ histo->GetXaxis()->SetTitle(chamberName);
+ histo->GetYaxis()->SetTitle(yAxisTitle);
+
+ fList->AddAt(histo, hindex + cath);
+ } // loop on cath
+ } // loop on counts
+
+ for(Int_t hType=0; hType<kNcounts; hType++){
+ Int_t hindex = (hType==0) ? kHslatAllEff : kHslatNonEff;
+ for(Int_t cath=0; cath<kNcathodes; cath++){
+ for(Int_t ch=0; ch<kNchambers; ch++){
+ Int_t chCath = GetPlane(cath, ch);
+ histoName = Form("%sSlat%s%i", cathCode[cath].Data(), countTypeName[hType].Data(), kFirstTrigCh+ch);
+ histo = new TH1F(histoName, histoName,
+ slatBins, slatLow, slatHigh);
+ histo->GetXaxis()->SetTitle(slatName);
+ histo->GetYaxis()->SetTitle(yAxisTitle);
+
+ fList->AddAt(histo, hindex + chCath);
+ } // loop on chamber
+ } // loop on cath
+ } // loop on counts
+
+ for(Int_t hType=0; hType<kNcounts; hType++){
+ Int_t hindex = (hType==0) ? kHboardAllEff : kHboardNonEff;
+ for(Int_t cath=0; cath<kNcathodes; cath++){
+ for(Int_t ch=0; ch<kNchambers; ch++){
+ Int_t chCath = GetPlane(cath, ch);
+ histoName = Form("%sBoard%s%i", cathCode[cath].Data(), countTypeName[hType].Data(), kFirstTrigCh+ch);
+ histo = new TH1F(histoName, histoName,
+ boardBins, boardLow, boardHigh);
+ histo->GetXaxis()->SetTitle(boardName);
+ histo->GetYaxis()->SetTitle(yAxisTitle);
+
+ fList->AddAt(histo, hindex + chCath);
+ } // loop on chamber
+ } // loop on cath
+ } // loop on counts
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskTrigChEff::Exec(Option_t *) {
+ //
+ /// Main loop
+ /// Called for each event
+ //
+ Int_t nTracks = 0, board = 0;
+ UShort_t pattern = 0;
+ AliESDMuonTrack *esdTrack = 0x0;
+ AliAODTrack* aodTrack = 0x0;
+
+ if(fAnalysisType == "ESD") {
+ if (!fESD) {
+ Printf("ERROR: fESD not available");
+ return;
+ }
+ nTracks = fESD->GetNumberOfMuonTracks();
+ }
+ else if(fAnalysisType == "AOD") {
+ if (!fAOD) {
+ Printf("ERROR: fAOD not available");
+ return;
+ }
+ nTracks = fAOD->GetNumberOfTracks();
+ }
+
+ // Object declaration
+ const Int_t kFirstTrigCh = 11; //AliMpConstants::NofTrackingChambers()+1;
+
+ for (Int_t itrack = 0; itrack < nTracks; itrack++) {
+ if(fAnalysisType == "ESD") {
+ esdTrack = fESD->GetMuonTrack(itrack);
+ pattern = esdTrack->GetHitsPatternInTrigCh();
+ board = esdTrack->LoCircuit();
+ }
+ else if(fAnalysisType == "AOD") {
+ aodTrack = fAOD->GetTrack(itrack);
+ if(!aodTrack->IsMuonTrack()) continue;
+ pattern = aodTrack->GetHitsPatternInTrigCh();
+ board = 0; // aodTrack->LoCircuit(); Lo Circuit not implemented in AOD
+ }
+
+ Int_t effFlag = GetEffFlag(pattern);
+
+ if(effFlag < kChEff) continue; // Track not good for efficiency calculation
+
+ Int_t slat = GetSlat(pattern);
+
+ if(effFlag >= kSlatEff) ((TH1F*)fList->At(kHtracksInSlat))->Fill(slat);
+ if(effFlag >= kBoardEff) ((TH1F*)fList->At(kHtracksInBoard))->Fill(board);
+
+ for(Int_t cath=0; cath<kNcathodes; cath++){
+ Int_t ineffCh = IsChInefficient(pattern, cath);
+ Int_t nChambers = kNchambers;
+ for(Int_t ch=0; ch<nChambers; ch++){
+ Int_t whichType = kAllChEff;
+ Int_t currCh = ch;
+ if(ineffCh>=0){
+ whichType = kChNonEff;
+ currCh = ineffCh;
+ nChambers = -1;
+ }
+
+ Int_t iChamber = kFirstTrigCh + currCh;
+ Int_t hindex = (whichType==kAllChEff) ? kHchamberAllEff : kHchamberNonEff;
+ ((TH1F*)fList->At(hindex + cath))->Fill(iChamber);
+
+ if(effFlag < kSlatEff) continue; // Track crossed different slats
+ Int_t chCath = GetPlane(cath, currCh);
+ hindex = (whichType==kAllChEff) ? kHslatAllEff : kHslatNonEff;
+ ((TH1F*)fList->At(hindex + chCath))->Fill(slat);
+
+ if(effFlag < kBoardEff) continue; // Track crossed different boards
+ hindex = (whichType==kAllChEff) ? kHboardAllEff : kHboardNonEff;
+ ((TH1F*)fList->At(hindex + chCath))->Fill(board);
+ } // loop on chambers
+ } // loop on cathodes
+ }
+
+ // Post final data. It will be written to a file with option "RECREATE"
+ PostData(0, fList);
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskTrigChEff::Terminate(Option_t *) {
+ //
+ /// Draw result to the screen
+ /// Called once at the end of the query.
+ //
+ if (!gROOT->IsBatch()) {
+ TCanvas *can[kNcathodes];
+ TH1F *num = 0x0;
+ TH1F *den = 0x0;
+ for(Int_t cath=0; cath<kNcathodes; cath++){
+ TString canName = Form("can%i",cath);
+ can[cath] = new TCanvas(canName.Data(),canName.Data(),10*(1+cath),10*(1+cath),310,310);
+ can[cath]->SetFillColor(10); can[cath]->SetHighLightColor(10);
+ can[cath]->SetLeftMargin(0.15); can[cath]->SetBottomMargin(0.15);
+ can[cath]->Divide(2,2);
+ for(Int_t ch=0; ch<kNchambers; ch++){
+ Int_t chCath = GetPlane(cath, ch);
+ num = (TH1F*)(fList->At(kHboardAllEff + chCath)->Clone());
+ den = (TH1F*)(fList->At(kHboardNonEff + chCath)->Clone());
+ den->Add(num);
+ num->Divide(den);
+ can[cath]->cd(ch+1);
+ num->DrawCopy("E");
+ }
+ }
+ }
+}
+
+//________________________________________________________________________
+Int_t AliAnalysisTaskTrigChEff::IsChInefficient(UShort_t pattern,
+ Int_t cathode)
+{
+ //
+ /// Check which chamber was inefficient.
+ //
+ Int_t ineffCh = -999;
+ for(Int_t ch=0; ch<kNchambers; ch++){
+ Int_t chCath = GetPlane(cathode, ch);
+ Int_t invert = kNplanes - chCath - 1;
+ Int_t response = (pattern >> invert) & 0x01;
+ if(!response) ineffCh = ch;
+ }
+ return ineffCh;
+}
--- /dev/null
+#include "TH1.h"
+#include "TList.h"
+
+#include "AliESDEvent.h"
+#include "AliAODEvent.h"
+
+class AliAnalysisTaskTrigChEff : public AliAnalysisTask {
+ public:
+ AliAnalysisTaskTrigChEff(const char *name = "AliAnalysisTaskTrigChEff");
+ virtual ~AliAnalysisTaskTrigChEff() {}
+
+ virtual void ConnectInputData(Option_t *);
+ virtual void CreateOutputObjects();
+ virtual void Exec(Option_t *option);
+ virtual void Terminate(Option_t *);
+
+ void SetType(const char* type) {fAnalysisType = type;}
+
+protected:
+ void ResetHistos();
+
+ /// Getting flag telling which efficiency is performable for current track
+ Int_t GetEffFlag(UShort_t pattern) { return (pattern >> 8) & 0x03; }
+
+ /// Getting crossed slat
+ Int_t GetSlat(UShort_t pattern) { return (pattern >> 10) & 0x1F; }
+
+ Int_t IsChInefficient(UShort_t pattern, Int_t cathode);
+
+private:
+ AliESDEvent* fESD; //!< ESDevent object
+ AliAODEvent* fAOD; //!< AODevent object
+ TString fAnalysisType; //"ESD" or "AOD"
+
+ TList* fList; //TList output object
+
+ enum {
+ kNcathodes = 2, ///< Number of cathodes
+ kNchambers = 4, ///< Number of chambers
+ kNplanes = 8, ///< Number of planes
+ kNslats = 18 ///< Number of slats
+ };
+
+ enum {kAllChEff, kChNonEff, kNcounts};
+
+ enum {
+ kNoEff,
+ kChEff,
+ kSlatEff,
+ kBoardEff
+ };
+
+ enum {
+ kHtracksInSlat = 0, ///< Tracks in slat histogram index
+ kHtracksInBoard = 1, ///< Tracks in board histogram index
+ kHchamberAllEff = 2, ///< N44 per cathode histogram index
+ kHchamberNonEff = 4, ///< N33 per cathode histogram index
+ kHslatAllEff = 6, ///< N44 per slat histogram index
+ kHslatNonEff = 14, ///< N33 per slat histogram index
+ kHboardAllEff = 22, ///< N44 per board histogram index
+ kHboardNonEff = 30 ///< N33 per board histogram index
+ };
+
+ /// Given cathode and chamber, return plane number
+ Int_t GetPlane(Int_t cathode, Int_t chamber) { return kNchambers*cathode + chamber; }
+
+ ClassDef(AliAnalysisTaskTrigChEff, 0); // Single muon analysis
+};
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Base macro for submitting trigger chamber efficiency determination.
+//
+// In case it is not run with full aliroot, it needs to have in the working directory:
+// - STEERBase.par
+// - ESD.par
+// - AOD.par
+// - ANALYSIS.par
+// - ANALYSISalice.par
+//
+// The macro reads ESDs and outputs file:
+// - MUON.TriggerEfficiencyMap.root
+//
+// To display the trigger chamber efficiency:
+// > aliroot
+// > AliMUONTriggerEfficiencyCells effCells("MUON.TriggerEfficiencyMap.root")
+// > effCells.DisplayEfficiency()
+//--------------------------------------------------------------------------
+
+enum anaModes {kMlocal, kMgridLocal, kMgrid};
+TString modeName[3] = {"local", "local", "grid"};
+const TString kDefaultLocalInputDir="$ALICE_ROOT/MUON/test_out.100";
+const TString kDefaultXmlFile="wn.xml";
+
+void AnalysisTrigChEff(Int_t mode=kMlocal)
+{
+// Example of running analysis train
+ TStopwatch timer;
+ timer.Start();
+
+ gSystem->Load("libTree.so");
+ gSystem->Load("libGeom.so");
+ gSystem->Load("libVMC.so");
+ gSystem->Load("libPhysics.so");
+
+ // Common packages
+ SetupPar("STEERBase");
+ SetupPar("ESD");
+ SetupPar("AOD");
+ SetupPar("ANALYSIS");
+ SetupPar("ANALYSISalice");
+
+ // Analysis using standard AliRoot libraries
+ gSystem->Load("libSTEERBase.so");
+ gSystem->Load("libESD.so");
+ gSystem->Load("libAOD.so");
+ gSystem->Load("libANALYSIS.so");
+ gSystem->Load("libANALYSISalice.so");
+
+
+ // A task can be compiled dynamically with AClic
+ gROOT->ProcessLine(".L AliAnalysisTaskTrigChEff.cxx+");
+
+ //
+ // Connect to alien
+ //
+ if(mode==kMgridLocal || mode==kMgrid)
+ TGrid::Connect("alien://");
+
+ //
+ // Create the chain
+ //
+ TChain* chain = CreateChain(mode);
+
+ TString outFileName("MUON.TriggerEfficiencyMap.root");
+ //
+ //
+ // Make the analysis manager
+ AliAnalysisManager *mgr = new AliAnalysisManager("Analysis Train", "A test setup for the analysis train");
+ // ESD input handler
+ AliESDInputHandler *esdHandler = new AliESDInputHandler();
+ //esdHandler->SetInactiveBranches("FMD CaloCluster");
+ // Monte Carlo handler
+ //AliMCEventHandler* mcHandler = new AliMCEventHandler();
+
+ mgr->SetInputEventHandler(esdHandler);
+ //mgr->SetMCtruthEventHandler(mcHandler);
+
+ // Trigger chamber efficiency analysis
+ AliAnalysisTaskTrigChEff* taskTrigChEff = new AliAnalysisTaskTrigChEff("TaskTrigChEff");
+ mgr->AddTask(taskTrigChEff);
+
+ // Create containers for input/output
+ // Top container for ESD input
+ AliAnalysisDataContainer *cin_esd = mgr->CreateContainer("cESD",TChain::Class(),
+ AliAnalysisManager::kInputContainer);
+
+ // Output histograms list for single muons analysis
+ AliAnalysisDataContainer *cout_trigChEff = mgr->CreateContainer("triggerChamberEff", TList::Class(),
+ AliAnalysisManager::kOutputContainer, outFileName.Data());
+
+ mgr->ConnectInput (taskTrigChEff, 0, cin_esd);
+ mgr->ConnectOutput (taskTrigChEff, 0, cout_trigChEff);
+
+ //
+ // Run the analysis
+ //
+ if (mgr->InitAnalysis()) {
+ mgr->PrintStatus();
+ mgr->StartAnalysis(modeName[mode].Data(), chain);
+ }
+ timer.Stop();
+ timer.Print();
+}
+
+//______________________________________________________________________________
+TChain* CreateChain(Int_t mode)
+{
+ printf("*******************************\n");
+ printf("*** Getting the Chain ***\n");
+ printf("*******************************\n");
+ TChain *chain = 0x0;
+ if(mode==kMgridLocal || mode==kMgrid){
+ AliTagAnalysis *analysis = new AliTagAnalysis();
+ chain = analysis->GetChainFromCollection(kDefaultXmlFile.Data(),"esdTree");
+ }
+ else{
+ chain = new TChain("esdTree");
+ TString inFileName("AliESDs.root");
+ inFileName.Prepend(Form("%s/",kDefaultLocalInputDir.Data()));
+ chain->Add(inFileName.Data());
+ }
+ if (chain) chain->ls();
+ return chain;
+}
+
+//______________________________________________________________________________
+void SetupPar(char* pararchivename)
+{
+ if (pararchivename) {
+ char processline[1024];
+ sprintf(processline,".! tar xvzf %s.par",pararchivename);
+ gROOT->ProcessLine(processline);
+ const char* ocwd = gSystem->WorkingDirectory();
+ gSystem->ChangeDirectory(pararchivename);
+ printf("Current directory = %s\n",gSystem->pwd());
+
+ // check for BUILD.sh and execute
+ if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
+ printf("*******************************\n");
+ printf("*** Building PAR archive ***\n");
+ printf("*******************************\n");
+
+ if (gSystem->Exec("PROOF-INF/BUILD.sh")) {
+ Error("runProcess","Cannot Build the PAR Archive! - Abort!");
+ return -1;
+ }
+ }
+ // check for SETUP.C and execute
+ if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
+ printf("*******************************\n");
+ printf("*** Setup PAR archive ***\n");
+ printf("*******************************\n");
+ gROOT->Macro("PROOF-INF/SETUP.C");
+ }
+
+ gSystem->ChangeDirectory("../");
+ }
+}